@optimizely-opal/opal-tool-ocp-sdk 0.0.0-OCP-1487.1

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 (72) hide show
  1. package/README.md +631 -0
  2. package/dist/auth/AuthUtils.d.ts +31 -0
  3. package/dist/auth/AuthUtils.d.ts.map +1 -0
  4. package/dist/auth/AuthUtils.js +64 -0
  5. package/dist/auth/AuthUtils.js.map +1 -0
  6. package/dist/auth/AuthUtils.test.d.ts +2 -0
  7. package/dist/auth/AuthUtils.test.d.ts.map +1 -0
  8. package/dist/auth/AuthUtils.test.js +469 -0
  9. package/dist/auth/AuthUtils.test.js.map +1 -0
  10. package/dist/auth/TokenVerifier.d.ts +31 -0
  11. package/dist/auth/TokenVerifier.d.ts.map +1 -0
  12. package/dist/auth/TokenVerifier.js +127 -0
  13. package/dist/auth/TokenVerifier.js.map +1 -0
  14. package/dist/auth/TokenVerifier.test.d.ts +2 -0
  15. package/dist/auth/TokenVerifier.test.d.ts.map +1 -0
  16. package/dist/auth/TokenVerifier.test.js +125 -0
  17. package/dist/auth/TokenVerifier.test.js.map +1 -0
  18. package/dist/decorator/Decorator.d.ts +48 -0
  19. package/dist/decorator/Decorator.d.ts.map +1 -0
  20. package/dist/decorator/Decorator.js +53 -0
  21. package/dist/decorator/Decorator.js.map +1 -0
  22. package/dist/decorator/Decorator.test.d.ts +2 -0
  23. package/dist/decorator/Decorator.test.d.ts.map +1 -0
  24. package/dist/decorator/Decorator.test.js +528 -0
  25. package/dist/decorator/Decorator.test.js.map +1 -0
  26. package/dist/function/GlobalToolFunction.d.ts +28 -0
  27. package/dist/function/GlobalToolFunction.d.ts.map +1 -0
  28. package/dist/function/GlobalToolFunction.js +56 -0
  29. package/dist/function/GlobalToolFunction.js.map +1 -0
  30. package/dist/function/GlobalToolFunction.test.d.ts +2 -0
  31. package/dist/function/GlobalToolFunction.test.d.ts.map +1 -0
  32. package/dist/function/GlobalToolFunction.test.js +425 -0
  33. package/dist/function/GlobalToolFunction.test.js.map +1 -0
  34. package/dist/function/ToolFunction.d.ts +28 -0
  35. package/dist/function/ToolFunction.d.ts.map +1 -0
  36. package/dist/function/ToolFunction.js +60 -0
  37. package/dist/function/ToolFunction.js.map +1 -0
  38. package/dist/function/ToolFunction.test.d.ts +2 -0
  39. package/dist/function/ToolFunction.test.d.ts.map +1 -0
  40. package/dist/function/ToolFunction.test.js +314 -0
  41. package/dist/function/ToolFunction.test.js.map +1 -0
  42. package/dist/index.d.ts +6 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +26 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/service/Service.d.ts +80 -0
  47. package/dist/service/Service.d.ts.map +1 -0
  48. package/dist/service/Service.js +210 -0
  49. package/dist/service/Service.js.map +1 -0
  50. package/dist/service/Service.test.d.ts +2 -0
  51. package/dist/service/Service.test.d.ts.map +1 -0
  52. package/dist/service/Service.test.js +427 -0
  53. package/dist/service/Service.test.js.map +1 -0
  54. package/dist/types/Models.d.ts +126 -0
  55. package/dist/types/Models.d.ts.map +1 -0
  56. package/dist/types/Models.js +181 -0
  57. package/dist/types/Models.js.map +1 -0
  58. package/package.json +64 -0
  59. package/src/auth/AuthUtils.test.ts +586 -0
  60. package/src/auth/AuthUtils.ts +66 -0
  61. package/src/auth/TokenVerifier.test.ts +165 -0
  62. package/src/auth/TokenVerifier.ts +145 -0
  63. package/src/decorator/Decorator.test.ts +649 -0
  64. package/src/decorator/Decorator.ts +111 -0
  65. package/src/function/GlobalToolFunction.test.ts +505 -0
  66. package/src/function/GlobalToolFunction.ts +61 -0
  67. package/src/function/ToolFunction.test.ts +374 -0
  68. package/src/function/ToolFunction.ts +64 -0
  69. package/src/index.ts +5 -0
  70. package/src/service/Service.test.ts +661 -0
  71. package/src/service/Service.ts +213 -0
  72. package/src/types/Models.ts +163 -0
@@ -0,0 +1,213 @@
1
+ /* eslint-disable max-classes-per-file */
2
+ import { AuthRequirement, Parameter } from '../types/Models';
3
+ import * as App from '@zaiusinc/app-sdk';
4
+ import { logger } from '@zaiusinc/app-sdk';
5
+ import { ToolFunction } from '../function/ToolFunction';
6
+ import { GlobalToolFunction } from '../function/GlobalToolFunction';
7
+
8
+ /**
9
+ * Default OptiID authentication requirement that will be enforced for all tools
10
+ */
11
+ const DEFAULT_OPTIID_AUTH = new AuthRequirement('OptiID', 'default', true);
12
+
13
+
14
+
15
+ /**
16
+ * Result type for interaction handlers
17
+ */
18
+ export class InteractionResult {
19
+ public constructor(
20
+ public message: string,
21
+ public link?: string
22
+ ) {}
23
+ }
24
+
25
+ /**
26
+ * Interaction definition for an Opal interaction
27
+ */
28
+ export class Interaction<TAuthData> {
29
+ public constructor(
30
+ public name: string,
31
+ public endpoint: string,
32
+ public handler: (
33
+ functionContext: ToolFunction | GlobalToolFunction,
34
+ data: unknown,
35
+ authData?: TAuthData
36
+ ) => Promise<InteractionResult>
37
+ ) {}
38
+ }
39
+
40
+ /**
41
+ * Tool definition for an Opal tool
42
+ */
43
+ export class Tool<TAuthData> {
44
+ /**
45
+ * HTTP method for the endpoint (default: POST)
46
+ */
47
+ public httpMethod: string = 'POST';
48
+
49
+ /**
50
+ * Create a new function definition
51
+ * @param name Function name
52
+ * @param description Function description
53
+ * @param parameters Function parameters
54
+ * @param endpoint API endpoint
55
+ * @param handler Function implementing the tool
56
+ * @param authRequirements Authentication requirements (mandatory - OptiID enforced)
57
+ */
58
+ public constructor(
59
+ public name: string,
60
+ public description: string,
61
+ public parameters: Parameter[],
62
+ public endpoint: string,
63
+ public handler: (
64
+ functionContext: ToolFunction | GlobalToolFunction,
65
+ params: unknown,
66
+ authData?: TAuthData
67
+ ) => Promise<unknown>,
68
+ public authRequirements: AuthRequirement[] = [DEFAULT_OPTIID_AUTH]
69
+ ) {}
70
+
71
+ /**
72
+ * Convert to JSON for the discovery endpoint
73
+ */
74
+ public toJSON(): Record<string, unknown> {
75
+ const result: Record<string, unknown> = {
76
+ name: this.name,
77
+ description: this.description,
78
+ parameters: this.parameters.map((p) => p.toJSON()),
79
+ endpoint: this.endpoint,
80
+ http_method: this.httpMethod,
81
+ auth_requirements: this.authRequirements.map((auth) => auth.toJSON())
82
+ };
83
+
84
+ return result;
85
+ }
86
+ }
87
+
88
+ export class ToolsService {
89
+ private functions: Map<string, Tool<any>> = new Map();
90
+ private interactions: Map<string, Interaction<any>> = new Map();
91
+
92
+ /**
93
+ * Enforce OptiID authentication for tools by ensuring OptiID auth requirement is present
94
+ * @param authRequirements Original authentication requirements
95
+ * @returns Enforced authentication requirements with OptiID
96
+ */
97
+ private enforceOptiIdAuth(authRequirements?: AuthRequirement[]): AuthRequirement[] {
98
+ const hasOptiIdProvider = authRequirements
99
+ && authRequirements.some((auth) => auth.provider.toLowerCase() === 'optiid');
100
+
101
+ if (hasOptiIdProvider) {
102
+ return authRequirements;
103
+ }
104
+
105
+ return [...(authRequirements || []), DEFAULT_OPTIID_AUTH];
106
+ }
107
+
108
+ /**
109
+ * Register a tool function with generic auth data
110
+ * @param name Tool name
111
+ * @param description Tool description
112
+ * @param handler Function implementing the tool
113
+ * @param parameters List of parameters for the tool
114
+ * @param endpoint API endpoint for the tool
115
+ * @param authRequirements Authentication requirements (optional)
116
+ */
117
+ public registerTool<TAuthData>(
118
+ name: string,
119
+ description: string,
120
+ handler: (
121
+ functionContext: ToolFunction | GlobalToolFunction,
122
+ params: unknown,
123
+ authData?: TAuthData
124
+ ) => Promise<unknown>,
125
+ parameters: Parameter[],
126
+ endpoint: string,
127
+ authRequirements?: AuthRequirement[]
128
+ ): void {
129
+ // Enforce OptiID authentication for all tools
130
+ const enforcedAuthRequirements = this.enforceOptiIdAuth(authRequirements);
131
+ const func = new Tool<TAuthData>(
132
+ name,
133
+ description,
134
+ parameters,
135
+ endpoint,
136
+ handler,
137
+ enforcedAuthRequirements
138
+ );
139
+ this.functions.set(endpoint, func);
140
+ }
141
+
142
+ /**
143
+ * Register a tool interaction with generic auth data
144
+ * @param name Tool name
145
+ * @param handler Function implementing the tool
146
+ * @param endpoint API endpoint for the tool
147
+ */
148
+ public registerInteraction<TAuthData>(
149
+ name: string,
150
+ handler: (
151
+ functionContext: ToolFunction | GlobalToolFunction,
152
+ data: unknown,
153
+ authData?: TAuthData
154
+ ) => Promise<InteractionResult>,
155
+ endpoint: string
156
+ ): void {
157
+ const func = new Interaction<TAuthData>(name, endpoint, handler);
158
+ this.interactions.set(endpoint, func);
159
+ }
160
+
161
+ public async processRequest(req: App.Request,
162
+ functionContext: ToolFunction | GlobalToolFunction): Promise<App.Response> {
163
+ if (req.path === '/discovery') {
164
+ return new App.Response(200, { functions: Array.from(this.functions.values()).map((f) => f.toJSON()) });
165
+ } else {
166
+ const func = this.functions.get(req.path);
167
+ if (func) {
168
+ try {
169
+ let params;
170
+ if (req.bodyJSON && req.bodyJSON.parameters) {
171
+ params = req.bodyJSON.parameters;
172
+ } else {
173
+ params = req.bodyJSON;
174
+ }
175
+
176
+ // Extract auth data from body JSON
177
+ const authData = req.bodyJSON ? req.bodyJSON.auth : undefined;
178
+
179
+ const result = await func.handler(functionContext, params, authData);
180
+ return new App.Response(200, result);
181
+ } catch (error: any) {
182
+ logger.error(`Error in function ${func.name}:`, error);
183
+ return new App.Response(500, { error: error.message || 'Unknown error' });
184
+ }
185
+ }
186
+
187
+ const interaction = this.interactions.get(req.path);
188
+ if (interaction) {
189
+ try {
190
+ let params;
191
+ if (req.bodyJSON && req.bodyJSON.data) {
192
+ params = req.bodyJSON.data;
193
+ } else {
194
+ params = req.bodyJSON;
195
+ }
196
+
197
+ // Extract auth data from body JSON
198
+ const authData = req.bodyJSON ? req.bodyJSON.auth : undefined;
199
+
200
+ const result = await interaction.handler(functionContext, params, authData);
201
+ return new App.Response(200, result);
202
+ } catch (error: any) {
203
+ logger.error(`Error in function ${interaction.name}:`, error);
204
+ return new App.Response(500, { error: error.message || 'Unknown error' });
205
+ }
206
+ }
207
+
208
+ return new App.Response(404, 'Function not found');
209
+ }
210
+ }
211
+ }
212
+
213
+ export const toolsService = new ToolsService();
@@ -0,0 +1,163 @@
1
+ /* eslint-disable max-classes-per-file */
2
+ /**
3
+ * Types of parameters supported by Opal tools
4
+ */
5
+ export enum ParameterType {
6
+ String = 'string',
7
+ Integer = 'integer',
8
+ Number = 'number',
9
+ Boolean = 'boolean',
10
+ List = 'list',
11
+ Dictionary = 'object'
12
+ }
13
+
14
+ /**
15
+ * Parameter definition for an Opal tool
16
+ */
17
+ export class Parameter {
18
+ /**
19
+ * Create a new parameter definition
20
+ * @param name Parameter name
21
+ * @param type Parameter type
22
+ * @param description Parameter description
23
+ * @param required Whether the parameter is required
24
+ */
25
+ public constructor(
26
+ public name: string,
27
+ public type: ParameterType,
28
+ public description: string,
29
+ public required: boolean
30
+ ) {}
31
+
32
+ /**
33
+ * Convert to JSON for the discovery endpoint
34
+ */
35
+ public toJSON() {
36
+ return {
37
+ name: this.name,
38
+ type: this.type,
39
+ description: this.description,
40
+ required: this.required
41
+ };
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Credentials structure
47
+ */
48
+ export class OptiIdAuthDataCredentials {
49
+
50
+ public constructor(
51
+ public customer_id: string,
52
+ public instance_id: string,
53
+ public access_token: string,
54
+ public product_sku: string
55
+ ) {}
56
+ }
57
+
58
+
59
+ /**
60
+ * Auth data structure
61
+ */
62
+ export class OptiIdAuthData {
63
+
64
+ public constructor(
65
+ public provider: string,
66
+ public credentials: OptiIdAuthDataCredentials
67
+ ) {}
68
+ }
69
+
70
+ /**
71
+ * Authentication requirements for an Opal tool
72
+ */
73
+ export class AuthRequirement {
74
+ /**
75
+ * Create a new authentication requirement
76
+ * @param provider Auth provider (e.g., "optiId")
77
+ * @param scopeBundle Scope bundle (e.g., "calendar", "drive")
78
+ * @param required Whether authentication is required
79
+ */
80
+ public constructor(
81
+ public provider: string,
82
+ public scopeBundle: string,
83
+ public required: boolean = true
84
+ ) {}
85
+
86
+ /**
87
+ * Convert to JSON for the discovery endpoint
88
+ */
89
+ public toJSON() {
90
+ return {
91
+ provider: this.provider,
92
+ scope_bundle: this.scopeBundle,
93
+ required: this.required
94
+ };
95
+ }
96
+ }
97
+
98
+ export class IslandField {
99
+
100
+ public constructor(
101
+ public name: string,
102
+ public label: string,
103
+ public type: 'string' | 'boolean' | 'json',
104
+ public value: string | boolean | object = '',
105
+ public hidden: boolean = false,
106
+ public options: string[] = []
107
+ ) {}
108
+
109
+ public toJSON() {
110
+ return {
111
+ name: this.name,
112
+ label: this.label,
113
+ type: this.type,
114
+ hidden: this.hidden,
115
+ options: this.options,
116
+ value: this.value
117
+ };
118
+ }
119
+ }
120
+
121
+ export class IslandAction {
122
+
123
+ public constructor(
124
+ public name: string,
125
+ public label: string,
126
+ public type: string,
127
+ public endpoint: string,
128
+ public operation: string = 'create'
129
+ ) {}
130
+
131
+ public toJSON() {
132
+ return {
133
+ name: this.name,
134
+ label: this.label,
135
+ type: this.type,
136
+ endpoint: this.endpoint,
137
+ operation: this.operation
138
+ };
139
+ }
140
+ }
141
+
142
+ export class IslandConfig {
143
+
144
+ public constructor(
145
+ public fields: IslandField[],
146
+ public actions: IslandAction[]
147
+ ) {}
148
+ }
149
+
150
+ export class IslandResponse {
151
+
152
+ public constructor(
153
+ public type: 'island',
154
+ public config: {
155
+ islands: IslandConfig[];
156
+ }
157
+ ) {}
158
+
159
+ public static create(islands: IslandConfig[]): IslandResponse {
160
+ return new IslandResponse('island', { islands });
161
+ }
162
+ }
163
+