@optimizely-opal/opal-tool-ocp-sdk 0.0.0-dev.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 (42) hide show
  1. package/README.md +437 -0
  2. package/dist/decorator/Decorator.d.ts +46 -0
  3. package/dist/decorator/Decorator.d.ts.map +1 -0
  4. package/dist/decorator/Decorator.js +31 -0
  5. package/dist/decorator/Decorator.js.map +1 -0
  6. package/dist/decorator/Decorator.test.d.ts +2 -0
  7. package/dist/decorator/Decorator.test.d.ts.map +1 -0
  8. package/dist/decorator/Decorator.test.js +418 -0
  9. package/dist/decorator/Decorator.test.js.map +1 -0
  10. package/dist/function/ToolFunction.d.ts +15 -0
  11. package/dist/function/ToolFunction.d.ts.map +1 -0
  12. package/dist/function/ToolFunction.js +25 -0
  13. package/dist/function/ToolFunction.js.map +1 -0
  14. package/dist/function/ToolFunction.test.d.ts +2 -0
  15. package/dist/function/ToolFunction.test.d.ts.map +1 -0
  16. package/dist/function/ToolFunction.test.js +189 -0
  17. package/dist/function/ToolFunction.test.js.map +1 -0
  18. package/dist/index.d.ts +5 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +25 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/service/Service.d.ts +78 -0
  23. package/dist/service/Service.d.ts.map +1 -0
  24. package/dist/service/Service.js +204 -0
  25. package/dist/service/Service.js.map +1 -0
  26. package/dist/service/Service.test.d.ts +2 -0
  27. package/dist/service/Service.test.d.ts.map +1 -0
  28. package/dist/service/Service.test.js +341 -0
  29. package/dist/service/Service.test.js.map +1 -0
  30. package/dist/types/Models.d.ts +126 -0
  31. package/dist/types/Models.d.ts.map +1 -0
  32. package/dist/types/Models.js +181 -0
  33. package/dist/types/Models.js.map +1 -0
  34. package/package.json +58 -0
  35. package/src/decorator/Decorator.test.ts +523 -0
  36. package/src/decorator/Decorator.ts +83 -0
  37. package/src/function/ToolFunction.test.ts +224 -0
  38. package/src/function/ToolFunction.ts +25 -0
  39. package/src/index.ts +4 -0
  40. package/src/service/Service.test.ts +550 -0
  41. package/src/service/Service.ts +182 -0
  42. package/src/types/Models.ts +163 -0
package/README.md ADDED
@@ -0,0 +1,437 @@
1
+ # OPAL Tool OCP SDK
2
+
3
+ > **Optimizely Connect Platform (OCP) SDK for OPAL Tool**
4
+
5
+ A TypeScript SDK for building Opal tools in Optimizely Connect Platform. This SDK provides decorators, abstractions, and utilities to simplify the development.
6
+
7
+ ## Features
8
+
9
+ - ๐ŸŽฏ **Decorator-based Tool Registration** - Use `@tool` and `@interaction` decorators to easily register functions
10
+ - ๐Ÿ”ง **Type-safe Development** - Full TypeScript support with comprehensive type definitions
11
+ - ๐Ÿ—๏ธ **Abstract Base Classes** - Extend `ToolFunction` for standardized request processing
12
+ - ๐Ÿ” **Authentication Support** - OptiID authentication
13
+ - ๐Ÿ›ก๏ธ **Authorization Support** - Bearer token tool authorization
14
+ - ๐Ÿ“ **Parameter Validation** - Define and validate tool parameters with types
15
+ - ๐Ÿงช **Comprehensive Testing** - Fully tested with Jest
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ npm install @optimizely-opal/opal-tool-ocp-sdk
21
+ ```
22
+
23
+ or
24
+
25
+ ```bash
26
+ yarn add @optimizely-opal/opal-tool-ocp-sdk
27
+ ```
28
+
29
+ ## Quick Start
30
+
31
+ Create a tool function class by extending `ToolFunction` and registering your tools and interactions:
32
+
33
+ ```typescript
34
+ import { ToolFunction, tool, interaction, ParameterType, InteractionResult, OptiIdAuthData } from '@optimizely-opal/opal-tool-ocp-sdk';
35
+
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
+
43
+ // Register a simple tool without authentication
44
+ @tool({
45
+ name: 'create_task',
46
+ description: 'Creates a new task in the system',
47
+ endpoint: '/create-task',
48
+ parameters: [
49
+ {
50
+ name: 'title',
51
+ type: ParameterType.String,
52
+ description: 'The task title',
53
+ required: true
54
+ },
55
+ {
56
+ name: 'priority',
57
+ type: ParameterType.String,
58
+ description: 'Task priority level',
59
+ required: false
60
+ }
61
+ ]
62
+ })
63
+ async createTask(params: { title: string; priority?: string }, authData?: OptiIdAuthData) {
64
+ return {
65
+ id: '123',
66
+ title: params.title,
67
+ priority: params.priority || 'medium'
68
+ };
69
+ }
70
+
71
+ // Register a tool with OptiID authentication
72
+ @tool({
73
+ name: 'secure_task',
74
+ description: 'Creates a secure task with OptiID authentication',
75
+ endpoint: '/secure-task',
76
+ parameters: [
77
+ {
78
+ name: 'title',
79
+ type: ParameterType.String,
80
+ description: 'The task title',
81
+ required: true
82
+ }
83
+ ],
84
+ authRequirements: [
85
+ {
86
+ provider: 'OptiID',
87
+ scopeBundle: 'tasks',
88
+ required: true
89
+ }
90
+ ]
91
+ })
92
+ async createSecureTask(params: { title: string }, authData?: OptiIdAuthData) {
93
+ if (!authData) {
94
+ throw new Error('OptiID authentication required');
95
+ }
96
+
97
+ const { customerId, instanceId, accessToken } = authData.credentials;
98
+ return {
99
+ id: '456',
100
+ title: params.title,
101
+ customerId,
102
+ instanceId
103
+ };
104
+ }
105
+
106
+ // Register an interaction
107
+ @interaction({
108
+ name: 'task_webhook',
109
+ endpoint: '/webhook/task'
110
+ })
111
+ async handleTaskWebhook(data: any): Promise<InteractionResult> {
112
+ return new InteractionResult(
113
+ `Task ${data.taskId} was updated`,
114
+ `https://app.example.com/tasks/${data.taskId}`
115
+ );
116
+ }
117
+ }
118
+ ```
119
+
120
+ Your function class inherits a `perform()` method from `ToolFunction` that serves as the main entry point for handling all incoming requests. When called, the SDK automatically:
121
+
122
+ - **Routes requests** to your registered tools and interactions based on endpoints
123
+ - **Handles authentication** and bearer token validation before calling your methods
124
+ - **Provides discovery** at `/discovery` endpoint for OCP platform integration
125
+ - **Returns proper HTTP responses** with correct status codes and JSON formatting
126
+
127
+ ## Core Concepts
128
+
129
+ ### Tools
130
+
131
+ Tools are functions that can be discovered and executed through the OCP platform. They:
132
+
133
+ - Have a name, description, and endpoint
134
+ - Define parameters with types and validation
135
+ - Can require authentication
136
+ - Return structured responses
137
+
138
+ ### Interactions
139
+
140
+ Interactions are event handlers that process incoming data (like webhooks):
141
+
142
+ - Have a name and endpoint
143
+ - Process unstructured data
144
+ - Return interaction results with messages and optional links
145
+
146
+ ### Parameters
147
+
148
+ Supported parameter types:
149
+
150
+ ```typescript
151
+ enum ParameterType {
152
+ String = 'string',
153
+ Integer = 'integer',
154
+ Number = 'number',
155
+ Boolean = 'boolean',
156
+ List = 'list',
157
+ Dictionary = 'object'
158
+ }
159
+ ```
160
+
161
+ ### Authentication
162
+
163
+ The SDK supports authentication and authorization mechanisms:
164
+
165
+ #### OptiID Authentication
166
+
167
+ OptiID provides user authentication with type safety. This is the only user authentication provider currently supported in Opal:
168
+
169
+ ```typescript
170
+ interface AuthRequirementConfig {
171
+ provider: string; // 'OptiID'
172
+ scopeBundle: string; // e.g., 'calendar', 'tasks'
173
+ required?: boolean; // default: true
174
+ }
175
+ ```
176
+
177
+ #### Bearer Token Support
178
+
179
+ The SDK automatically extracts Bearer tokens from the `authorization` header for tool authorization. When users register tools in Opal, they can specify a Bearer token that Opal will include in requests to validate the tool's identity.
180
+
181
+ **Token Validation:**
182
+ - Bearer tokens are extracted from the `authorization: Bearer <token>` header
183
+ - Empty strings and `undefined` tokens are treated as missing (no validation performed)
184
+ - Implement the abstract `validateBearerToken(token: string): boolean` method to define your validation logic
185
+
186
+ ```typescript
187
+ export class MyToolFunction extends ToolFunction {
188
+ // Implement the required bearer token validation method
189
+ validateBearerToken(token: string): boolean {
190
+ // If you don't need bearer token validation, simply return true
191
+ // return true;
192
+
193
+ // For actual validation, compare against expected token
194
+ const expectedToken = process.env.OPAL_TOOL_TOKEN;
195
+ return token === expectedToken;
196
+ }
197
+
198
+ @tool({
199
+ name: 'secure_tool',
200
+ description: 'Tool that validates requests from Opal',
201
+ endpoint: '/secure-endpoint',
202
+ parameters: [
203
+ { name: 'data', type: ParameterType.String, description: 'Data to process', required: true }
204
+ ]
205
+ })
206
+ async secureToolHandler(
207
+ params: { data: string },
208
+ authData?: OptiIdAuthData
209
+ ) {
210
+
211
+ // Process the request knowing it's from a trusted Opal instance
212
+ return {
213
+ status: 'success',
214
+ data: `Processed: ${params.data}`,
215
+ authorizedBy: 'Opal'
216
+ };
217
+ }
218
+ }
219
+ ```
220
+
221
+ **Bearer Token Usage:**
222
+ - Set by users when registering tools in Opal
223
+ - Used to authorize tool requests from Opal instances
224
+ - Validates that requests are coming from trusted Opal sources
225
+ - Requires implementing the abstract `validateBearerToken(token: string): boolean` method
226
+ - If validation fails, returns HTTP 403 Forbidden before reaching your handler methods
227
+
228
+
229
+ ## API Reference
230
+
231
+ ### Handler Function Signatures
232
+
233
+ All tool and interaction handler methods follow this signature pattern:
234
+
235
+ ```typescript
236
+ async handlerMethod(
237
+ params: TParams, // Tool parameters or interaction data
238
+ authData?: OptiIdAuthData // OptiID user authentication data (if authenticated)
239
+ ): Promise<TResult>
240
+ ```
241
+
242
+ - **params**: The input parameters for tools, or interaction data for webhooks
243
+ - **authData**: Available when OptiID user authentication is configured and successful
244
+
245
+ **Note**: Bearer token validation is handled automatically by the base class. If a bearer token is present and fails validation, the request is rejected before reaching your handler methods.
246
+
247
+ ### Decorators
248
+
249
+ #### `@tool(config: ToolConfig)`
250
+
251
+ Registers a method as a discoverable tool.
252
+
253
+ ```typescript
254
+ interface ToolConfig {
255
+ name: string;
256
+ description: string;
257
+ parameters: ParameterConfig[];
258
+ authRequirements?: AuthRequirementConfig[];
259
+ endpoint: string;
260
+ }
261
+ ```
262
+
263
+ #### `@interaction(config: InteractionConfig)`
264
+
265
+ Registers a method as an interaction handler.
266
+
267
+ ```typescript
268
+ interface InteractionConfig {
269
+ name: string;
270
+ endpoint: string;
271
+ }
272
+ ```
273
+
274
+ ### Base Classes
275
+
276
+ #### `ToolFunction`
277
+
278
+ Abstract base class for OCP functions:
279
+
280
+ ```typescript
281
+ export abstract class ToolFunction extends Function {
282
+ public async perform(): Promise<Response>;
283
+ protected abstract validateBearerToken(token: string): boolean;
284
+ }
285
+ ```
286
+
287
+ Extend this class and implement your OCP function. The `perform` method automatically routes requests to registered tools and handles bearer token validation. You must implement the `validateBearerToken` method to define how bearer tokens should be validated for your tools.
288
+
289
+ ### Models
290
+
291
+ Key model classes with generic type support:
292
+
293
+ - `Tool<TAuthData>` - Represents a registered tool with typed auth data
294
+ - `Interaction<TAuthData>` - Represents an interaction handler with typed auth data
295
+ - `Parameter` - Defines tool parameters
296
+ - `AuthRequirement` - Defines authentication needs
297
+ - `InteractionResult` - Response from interactions
298
+ - `OptiIdAuthData` - OptiID specific authentication data
299
+
300
+ ## Discovery Endpoint
301
+
302
+ The SDK automatically provides a discovery endpoint at `/discovery` that returns all registered tools in the proper OCP format:
303
+
304
+ ```json
305
+ {
306
+ "functions": [
307
+ {
308
+ "name": "create_task",
309
+ "description": "Creates a new task in the system",
310
+ "parameters": [
311
+ {
312
+ "name": "title",
313
+ "type": "string",
314
+ "description": "The task title",
315
+ "required": true
316
+ },
317
+ {
318
+ "name": "priority",
319
+ "type": "string",
320
+ "description": "Task priority level",
321
+ "required": false
322
+ }
323
+ ],
324
+ "endpoint": "/create-task",
325
+ "http_method": "POST"
326
+ },
327
+ {
328
+ "name": "secure_task",
329
+ "description": "Creates a secure task with OptiID authentication",
330
+ "parameters": [
331
+ {
332
+ "name": "title",
333
+ "type": "string",
334
+ "description": "The task title",
335
+ "required": true
336
+ }
337
+ ],
338
+ "endpoint": "/secure-task",
339
+ "http_method": "POST",
340
+ "auth_requirements": [
341
+ {
342
+ "provider": "OptiID",
343
+ "scope_bundle": "tasks",
344
+ "required": true
345
+ }
346
+ ]
347
+ }
348
+ ]
349
+ }
350
+ ```
351
+
352
+ ## Development
353
+
354
+ ### Prerequisites
355
+
356
+ - Node.js >= 22.0.0
357
+ - TypeScript 5.x
358
+
359
+ ### Building
360
+
361
+ ```bash
362
+ yarn build
363
+ ```
364
+
365
+ ### Testing
366
+
367
+ ```bash
368
+ # Run tests
369
+ yarn test
370
+
371
+ # Run tests in watch mode
372
+ yarn test:watch
373
+
374
+ # Run tests with coverage
375
+ yarn test:coverage
376
+ ```
377
+
378
+ ### Linting
379
+
380
+ ```bash
381
+ yarn lint
382
+ ```
383
+
384
+ ## Examples
385
+
386
+ ### Function with Authentication
387
+
388
+ ```typescript
389
+ import { ToolFunction, tool, interaction, ParameterType, OptiIdAuthData, InteractionResult } from '@optimizely-opal/opal-ocp-sdk';
390
+
391
+ export class AuthenticatedFunction extends ToolFunction {
392
+ // Implement required bearer token validation
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
398
+ const expectedToken = process.env.OPAL_TOOL_TOKEN;
399
+ return token === expectedToken;
400
+ }
401
+
402
+ // OptiID authentication example
403
+ @tool({
404
+ name: 'secure_operation',
405
+ description: 'Performs a secure operation with OptiID',
406
+ endpoint: '/secure',
407
+ parameters: [],
408
+ authRequirements: [{ provider: 'OptiID', scopeBundle: 'tasks', required: true }]
409
+ })
410
+ async secureOperation(params: unknown, authData?: OptiIdAuthData) {
411
+ if (!authData) throw new Error('OptiID authentication required');
412
+
413
+ const { customerId, accessToken } = authData.credentials;
414
+ // Use OptiID credentials for API calls
415
+ return { success: true, customerId };
416
+ }
417
+
418
+ // Interaction with authentication example
419
+ @interaction({
420
+ name: 'authenticated_webhook',
421
+ endpoint: '/secure-webhook'
422
+ })
423
+ async handleSecureWebhook(data: any, authData?: OptiIdAuthData): Promise<InteractionResult> {
424
+ if (!authData) {
425
+ return new InteractionResult('Authentication required for webhook processing');
426
+ }
427
+
428
+ const { customerId } = authData.credentials;
429
+
430
+ // Process webhook data with authentication context
431
+ return new InteractionResult(
432
+ `Webhook processed for customer ${customerId}: ${data.eventType}`,
433
+ `https://app.example.com/events/${data.eventId}`
434
+ );
435
+ }
436
+ }
437
+ ```
@@ -0,0 +1,46 @@
1
+ import { ParameterType } from '../types/Models';
2
+ /**
3
+ * Configuration for @tool decorator
4
+ */
5
+ export interface ToolConfig {
6
+ name: string;
7
+ description: string;
8
+ parameters: ParameterConfig[];
9
+ authRequirements?: AuthRequirementConfig[];
10
+ endpoint: string;
11
+ }
12
+ /**
13
+ * Parameter configuration for decorators
14
+ */
15
+ export interface ParameterConfig {
16
+ name: string;
17
+ type: ParameterType;
18
+ description: string;
19
+ required: boolean;
20
+ }
21
+ /**
22
+ * AuthRequirement configuration for decorators
23
+ */
24
+ export interface AuthRequirementConfig {
25
+ provider: string;
26
+ scopeBundle: string;
27
+ required?: boolean;
28
+ }
29
+ /**
30
+ * Configuration for @interaction decorator
31
+ */
32
+ export interface InteractionConfig {
33
+ name: string;
34
+ endpoint: string;
35
+ }
36
+ /**
37
+ * Decorator for registering tool functions
38
+ * Immediately registers the tool with the global ToolsService
39
+ */
40
+ export declare function tool(config: ToolConfig): (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) => void;
41
+ /**
42
+ * Decorator for registering interaction functions
43
+ * Immediately registers the interaction with the global ToolsService
44
+ */
45
+ export declare function interaction(config: InteractionConfig): (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) => void;
46
+ //# sourceMappingURL=Decorator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Decorator.d.ts","sourceRoot":"","sources":["../../src/decorator/Decorator.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAG5E;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,gBAAgB,CAAC,EAAE,qBAAqB,EAAE,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,aAAa,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,IAAI,CAAC,MAAM,EAAE,UAAU,IACrB,SAAS,GAAG,EAAE,cAAc,MAAM,EAAE,YAAY,kBAAkB,UAqBnF;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,iBAAiB,IACnC,SAAS,GAAG,EAAE,cAAc,MAAM,EAAE,YAAY,kBAAkB,UAQnF"}
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.tool = tool;
4
+ exports.interaction = interaction;
5
+ const Models_1 = require("../types/Models");
6
+ const Service_1 = require("../service/Service");
7
+ /**
8
+ * Decorator for registering tool functions
9
+ * Immediately registers the tool with the global ToolsService
10
+ */
11
+ function tool(config) {
12
+ return function (_target, _propertyKey, descriptor) {
13
+ // Convert parameter configs to Parameter instances
14
+ const parameters = (config.parameters || []).map((p) => new Models_1.Parameter(p.name, p.type, p.description, p.required));
15
+ // Convert auth requirement configs to AuthRequirement instances
16
+ const authRequirements = (config.authRequirements || []).map((a) => new Models_1.AuthRequirement(a.provider, a.scopeBundle, a.required));
17
+ // Immediately register with global ToolsService
18
+ Service_1.toolsService.registerTool(config.name, config.description, descriptor.value, parameters, config.endpoint, authRequirements);
19
+ };
20
+ }
21
+ /**
22
+ * Decorator for registering interaction functions
23
+ * Immediately registers the interaction with the global ToolsService
24
+ */
25
+ function interaction(config) {
26
+ return function (_target, _propertyKey, descriptor) {
27
+ // Immediately register with global ToolsService
28
+ Service_1.toolsService.registerInteraction(config.name, descriptor.value, config.endpoint);
29
+ };
30
+ }
31
+ //# sourceMappingURL=Decorator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Decorator.js","sourceRoot":"","sources":["../../src/decorator/Decorator.ts"],"names":[],"mappings":";;AA6CA,oBAsBC;AAMD,kCASC;AAlFD,4CAA4E;AAC5E,gDAAkD;AAwClD;;;GAGG;AACH,SAAgB,IAAI,CAAC,MAAkB;IACrC,OAAO,UAAS,OAAY,EAAE,YAAoB,EAAE,UAA8B;QAChF,mDAAmD;QACnD,MAAM,UAAU,GAAG,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACrD,IAAI,kBAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,CACzD,CAAC;QAEF,gEAAgE;QAChE,MAAM,gBAAgB,GAAG,CAAC,MAAM,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACjE,IAAI,wBAAe,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,CAC3D,CAAC;QAEF,gDAAgD;QAChD,sBAAY,CAAC,YAAY,CACvB,MAAM,CAAC,IAAI,EACX,MAAM,CAAC,WAAW,EAClB,UAAU,CAAC,KAAK,EAChB,UAAU,EACV,MAAM,CAAC,QAAQ,EACf,gBAAgB,CACjB,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAgB,WAAW,CAAC,MAAyB;IACnD,OAAO,UAAS,OAAY,EAAE,YAAoB,EAAE,UAA8B;QAChF,gDAAgD;QAChD,sBAAY,CAAC,mBAAmB,CAC9B,MAAM,CAAC,IAAI,EACX,UAAU,CAAC,KAAK,EAChB,MAAM,CAAC,QAAQ,CAChB,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=Decorator.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Decorator.test.d.ts","sourceRoot":"","sources":["../../src/decorator/Decorator.test.ts"],"names":[],"mappings":""}