@slates/provider 1.0.0-rc.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.
- package/package.json +37 -0
- package/src/action/action.ts +191 -0
- package/src/action/builder.ts +150 -0
- package/src/action/index.ts +5 -0
- package/src/action/tool.ts +52 -0
- package/src/action/trigger.ts +112 -0
- package/src/auth/auth.ts +82 -0
- package/src/auth/index.ts +2 -0
- package/src/auth/types.ts +150 -0
- package/src/axios/index.ts +28 -0
- package/src/config/config.ts +56 -0
- package/src/config/index.ts +1 -0
- package/src/context/context.ts +68 -0
- package/src/context/hook.ts +23 -0
- package/src/context/index.ts +1 -0
- package/src/error/base.ts +10 -0
- package/src/error/declaration.ts +12 -0
- package/src/error/index.ts +2 -0
- package/src/index.ts +8 -0
- package/src/logger/index.ts +1 -0
- package/src/logger/logger.ts +85 -0
- package/src/specification/index.ts +2 -0
- package/src/specification/slate.ts +28 -0
- package/src/specification/specification.ts +70 -0
- package/tsconfig.json +8 -0
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@slates/provider",
|
|
3
|
+
"version": "1.0.0-rc.1",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"author": "Tobias Herber",
|
|
8
|
+
"license": "Apache 2",
|
|
9
|
+
"type": "module",
|
|
10
|
+
"source": "src/index.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"require": "./dist/index.cjs",
|
|
14
|
+
"import": "./dist/index.module.js",
|
|
15
|
+
"default": "./dist/index.module.js"
|
|
16
|
+
},
|
|
17
|
+
"main": "./dist/index.cjs",
|
|
18
|
+
"module": "./dist/index.module.js",
|
|
19
|
+
"types": "dist/index.d.ts",
|
|
20
|
+
"unpkg": "./dist/index.umd.js",
|
|
21
|
+
"scripts": {
|
|
22
|
+
"test": "vitest run --passWithNoTests",
|
|
23
|
+
"lint": "prettier src/**/*.ts --check",
|
|
24
|
+
"build": "microbundle"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@toon-format/toon": "^2.1.0",
|
|
28
|
+
"axios": "^1.13.2",
|
|
29
|
+
"zod": "^4.2.1"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"microbundle": "^0.15.1",
|
|
33
|
+
"@slates/tsconfig": "^1.0.0",
|
|
34
|
+
"typescript": "5.8.2",
|
|
35
|
+
"vitest": "^3.1.2"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { SlateContext } from '../context';
|
|
3
|
+
import { SlateSpecification } from '../specification/specification';
|
|
4
|
+
|
|
5
|
+
export type SlateActionType = 'tool' | 'trigger';
|
|
6
|
+
|
|
7
|
+
export interface SlateActionParameters {
|
|
8
|
+
key: string;
|
|
9
|
+
name: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
instructions?: string[];
|
|
12
|
+
constraints?: string[];
|
|
13
|
+
tags?: {
|
|
14
|
+
destructive?: boolean;
|
|
15
|
+
readOnly?: boolean;
|
|
16
|
+
[key: string]: boolean | undefined;
|
|
17
|
+
};
|
|
18
|
+
metadata?: Record<string, any>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type SlateToolInvocationHandler<
|
|
22
|
+
ConfigType extends {},
|
|
23
|
+
AuthType extends {},
|
|
24
|
+
InputType extends {},
|
|
25
|
+
OutputType extends {}
|
|
26
|
+
> = (context: SlateContext<ConfigType, AuthType, InputType>) => Promise<{
|
|
27
|
+
output: OutputType;
|
|
28
|
+
message: string;
|
|
29
|
+
}>;
|
|
30
|
+
|
|
31
|
+
export type SlateTriggerMappingHandler<
|
|
32
|
+
ConfigType extends {},
|
|
33
|
+
AuthType extends {},
|
|
34
|
+
InputType extends {},
|
|
35
|
+
OutputType extends {}
|
|
36
|
+
> = (context: SlateContext<ConfigType, AuthType, InputType>) => Promise<{
|
|
37
|
+
type: string;
|
|
38
|
+
id: string;
|
|
39
|
+
output: OutputType;
|
|
40
|
+
}>;
|
|
41
|
+
|
|
42
|
+
export type SlateTriggerPollingHandler<
|
|
43
|
+
ConfigType extends {},
|
|
44
|
+
AuthType extends {},
|
|
45
|
+
InputType extends {}
|
|
46
|
+
> = (context: SlateContext<ConfigType, AuthType, { state: any | null }>) => Promise<{
|
|
47
|
+
inputs: InputType[];
|
|
48
|
+
updatedState?: any;
|
|
49
|
+
}>;
|
|
50
|
+
|
|
51
|
+
export type SlateTriggerWebhookRequestHandler<
|
|
52
|
+
ConfigType extends {},
|
|
53
|
+
AuthType extends {},
|
|
54
|
+
InputType extends {}
|
|
55
|
+
> = (
|
|
56
|
+
context: SlateContext<ConfigType, AuthType, { request: Request; state: any | null }>
|
|
57
|
+
) => Promise<{
|
|
58
|
+
inputs: InputType[];
|
|
59
|
+
updatedState?: any;
|
|
60
|
+
}>;
|
|
61
|
+
|
|
62
|
+
export type SlateTriggerWebhookAutoRegistrationHandler<
|
|
63
|
+
ConfigType extends {},
|
|
64
|
+
AuthType extends {}
|
|
65
|
+
> = (context: SlateContext<ConfigType, AuthType, { webhookBaseUrl: string }>) => Promise<{
|
|
66
|
+
registrationDetails: any;
|
|
67
|
+
state?: any;
|
|
68
|
+
}>;
|
|
69
|
+
|
|
70
|
+
export type SlateTriggerWebhookAutoUnregistrationHandler<
|
|
71
|
+
ConfigType extends {},
|
|
72
|
+
AuthType extends {}
|
|
73
|
+
> = (
|
|
74
|
+
context: SlateContext<
|
|
75
|
+
ConfigType,
|
|
76
|
+
AuthType,
|
|
77
|
+
{ webhookBaseUrl: string; registrationDetails: any; state: any | null }
|
|
78
|
+
>
|
|
79
|
+
) => Promise<unknown>;
|
|
80
|
+
|
|
81
|
+
export interface SlateActionParametersTool<
|
|
82
|
+
ConfigType extends {},
|
|
83
|
+
AuthType extends {},
|
|
84
|
+
InputType extends {},
|
|
85
|
+
OutputType extends {}
|
|
86
|
+
> {
|
|
87
|
+
type: 'tool';
|
|
88
|
+
handleInvocation: SlateToolInvocationHandler<ConfigType, AuthType, InputType, OutputType>;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface SlatePollingOptions {
|
|
92
|
+
intervalInSeconds?: number;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface SlateActionParametersTrigger<
|
|
96
|
+
ConfigType extends {},
|
|
97
|
+
AuthType extends {},
|
|
98
|
+
InputType extends {},
|
|
99
|
+
OutputType extends {}
|
|
100
|
+
> {
|
|
101
|
+
type: 'trigger';
|
|
102
|
+
source: 'polling' | 'webhook';
|
|
103
|
+
polling?: SlatePollingOptions;
|
|
104
|
+
handleEvent: SlateTriggerMappingHandler<ConfigType, AuthType, InputType, OutputType>;
|
|
105
|
+
handleRequest?: SlateTriggerWebhookRequestHandler<ConfigType, AuthType, InputType>;
|
|
106
|
+
pollEvents?: SlateTriggerPollingHandler<ConfigType, AuthType, InputType>;
|
|
107
|
+
autoRegisterWebhook?: SlateTriggerWebhookAutoRegistrationHandler<ConfigType, AuthType>;
|
|
108
|
+
autoUnregisterWebhook?: SlateTriggerWebhookAutoUnregistrationHandler<ConfigType, AuthType>;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export type SlateActionParametersAny<
|
|
112
|
+
ConfigType extends {},
|
|
113
|
+
AuthType extends {},
|
|
114
|
+
InputType extends {},
|
|
115
|
+
OutputType extends {}
|
|
116
|
+
> =
|
|
117
|
+
| SlateActionParametersTool<ConfigType, AuthType, InputType, OutputType>
|
|
118
|
+
| SlateActionParametersTrigger<ConfigType, AuthType, InputType, OutputType>;
|
|
119
|
+
|
|
120
|
+
export type SlateActionCreateParameters<
|
|
121
|
+
ConfigType extends {},
|
|
122
|
+
AuthType extends {},
|
|
123
|
+
InputType extends {},
|
|
124
|
+
OutputType extends {}
|
|
125
|
+
> = SlateActionParametersAny<ConfigType, AuthType, InputType, OutputType> &
|
|
126
|
+
SlateActionParameters & {
|
|
127
|
+
configSchema: z.ZodType<ConfigType>;
|
|
128
|
+
authSchema: z.ZodType<AuthType>;
|
|
129
|
+
inputSchema: z.ZodType<InputType>;
|
|
130
|
+
outputSchema: z.ZodType<OutputType>;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export abstract class SlateAction<
|
|
134
|
+
Type extends SlateActionType,
|
|
135
|
+
ConfigType extends {},
|
|
136
|
+
AuthType extends {},
|
|
137
|
+
InputType extends {},
|
|
138
|
+
OutputType extends {}
|
|
139
|
+
> {
|
|
140
|
+
constructor(
|
|
141
|
+
public readonly type: Type,
|
|
142
|
+
protected readonly _spec: SlateSpecification<ConfigType, AuthType>,
|
|
143
|
+
protected readonly _inputSchema: z.ZodType<InputType>,
|
|
144
|
+
protected readonly _outputSchema: z.ZodType<OutputType>,
|
|
145
|
+
protected readonly _params: SlateActionParameters
|
|
146
|
+
) {}
|
|
147
|
+
|
|
148
|
+
get configSchema() {
|
|
149
|
+
return this._spec.configSchema;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
get inputSchema() {
|
|
153
|
+
return this._inputSchema;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
get outputSchema() {
|
|
157
|
+
return this._outputSchema;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
get parameters() {
|
|
161
|
+
return this._params;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
get key() {
|
|
165
|
+
return this._params.key;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
get name() {
|
|
169
|
+
return this._params.name;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
get description() {
|
|
173
|
+
return this._params.description;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
get tags() {
|
|
177
|
+
return this._params.tags;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
get instructions() {
|
|
181
|
+
return this._params.instructions;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
get constraints() {
|
|
185
|
+
return this._params.constraints;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
get metadata() {
|
|
189
|
+
return this._params.metadata;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
import { SlateDeclarationError } from '../error';
|
|
3
|
+
import { SlateSpecification } from '../specification/specification';
|
|
4
|
+
import {
|
|
5
|
+
SlateAction,
|
|
6
|
+
SlateActionCreateParameters,
|
|
7
|
+
SlateActionParameters,
|
|
8
|
+
SlateActionParametersTool,
|
|
9
|
+
SlateActionParametersTrigger,
|
|
10
|
+
SlateActionType,
|
|
11
|
+
SlatePollingOptions,
|
|
12
|
+
SlateToolInvocationHandler,
|
|
13
|
+
SlateTriggerMappingHandler,
|
|
14
|
+
SlateTriggerPollingHandler,
|
|
15
|
+
SlateTriggerWebhookAutoRegistrationHandler,
|
|
16
|
+
SlateTriggerWebhookAutoUnregistrationHandler,
|
|
17
|
+
SlateTriggerWebhookRequestHandler
|
|
18
|
+
} from './action';
|
|
19
|
+
|
|
20
|
+
export class SlateActionBuilder<
|
|
21
|
+
Type extends SlateActionType,
|
|
22
|
+
ConfigType extends {},
|
|
23
|
+
AuthType extends {},
|
|
24
|
+
InputType extends {},
|
|
25
|
+
OutputType extends {},
|
|
26
|
+
Result extends SlateAction<Type, ConfigType, AuthType, any, any>
|
|
27
|
+
> {
|
|
28
|
+
#configSchema: z.ZodType<ConfigType>;
|
|
29
|
+
#authSchema: z.ZodType<AuthType>;
|
|
30
|
+
#inputSchema: z.ZodType<InputType> | null = null;
|
|
31
|
+
#outputSchema: z.ZodType<OutputType> | null = null;
|
|
32
|
+
|
|
33
|
+
#toolParams: SlateActionParametersTool<ConfigType, AuthType, InputType, OutputType> | null =
|
|
34
|
+
null;
|
|
35
|
+
#triggerParams: SlateActionParametersTrigger<
|
|
36
|
+
ConfigType,
|
|
37
|
+
AuthType,
|
|
38
|
+
InputType,
|
|
39
|
+
OutputType
|
|
40
|
+
> | null = null;
|
|
41
|
+
|
|
42
|
+
constructor(
|
|
43
|
+
private readonly type: Type,
|
|
44
|
+
private readonly spec: SlateSpecification<ConfigType, AuthType>,
|
|
45
|
+
private readonly params: SlateActionParameters,
|
|
46
|
+
private readonly factory: (
|
|
47
|
+
params: SlateActionCreateParameters<any, any, any, any>
|
|
48
|
+
) => Result
|
|
49
|
+
) {
|
|
50
|
+
this.#configSchema = spec.configSchema;
|
|
51
|
+
this.#authSchema = spec.authSchema;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
input<NewInputType extends {}>(
|
|
55
|
+
schema: z.ZodType<NewInputType>
|
|
56
|
+
): SlateActionBuilder<Type, ConfigType, AuthType, NewInputType, OutputType, Result> {
|
|
57
|
+
this.#inputSchema = schema as any;
|
|
58
|
+
return this as any;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
output<NewOutputType extends {}>(
|
|
62
|
+
schema: z.ZodType<NewOutputType>
|
|
63
|
+
): SlateActionBuilder<Type, ConfigType, AuthType, InputType, NewOutputType, Result> {
|
|
64
|
+
this.#outputSchema = schema as any;
|
|
65
|
+
return this as any;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
handleInvocation(
|
|
69
|
+
handler: SlateToolInvocationHandler<ConfigType, AuthType, InputType, OutputType>
|
|
70
|
+
): SlateActionBuilder<Type, ConfigType, AuthType, InputType, OutputType, Result> {
|
|
71
|
+
if (this.type !== 'tool') {
|
|
72
|
+
throw new SlateDeclarationError('handleInvocation can only be set for tool actions');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
this.#toolParams = {
|
|
76
|
+
type: 'tool',
|
|
77
|
+
handleInvocation: handler
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
return this;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
webhook(props: {
|
|
84
|
+
handleEvent: SlateTriggerMappingHandler<ConfigType, AuthType, InputType, OutputType>;
|
|
85
|
+
handleRequest: SlateTriggerWebhookRequestHandler<ConfigType, AuthType, InputType>;
|
|
86
|
+
autoRegisterWebhook?: SlateTriggerWebhookAutoRegistrationHandler<ConfigType, AuthType>;
|
|
87
|
+
autoUnregisterWebhook?: SlateTriggerWebhookAutoUnregistrationHandler<ConfigType, AuthType>;
|
|
88
|
+
}): SlateActionBuilder<Type, ConfigType, AuthType, InputType, OutputType, Result> {
|
|
89
|
+
if (this.type !== 'trigger') {
|
|
90
|
+
throw new SlateDeclarationError('handleEvent can only be set for trigger actions');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
this.#triggerParams = {
|
|
94
|
+
type: 'trigger',
|
|
95
|
+
source: 'webhook',
|
|
96
|
+
handleEvent: props.handleEvent,
|
|
97
|
+
handleRequest: props.handleRequest,
|
|
98
|
+
autoRegisterWebhook: props.autoRegisterWebhook,
|
|
99
|
+
autoUnregisterWebhook: props.autoUnregisterWebhook
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
return this;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
polling(props: {
|
|
106
|
+
options?: SlatePollingOptions;
|
|
107
|
+
pollEvents?: SlateTriggerPollingHandler<ConfigType, AuthType, InputType>;
|
|
108
|
+
handleEvent: SlateTriggerMappingHandler<ConfigType, AuthType, InputType, OutputType>;
|
|
109
|
+
}): SlateActionBuilder<Type, ConfigType, AuthType, InputType, OutputType, Result> {
|
|
110
|
+
if (this.type !== 'trigger') {
|
|
111
|
+
throw new SlateDeclarationError('handleEvent can only be set for trigger actions');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
this.#triggerParams = {
|
|
115
|
+
type: 'trigger',
|
|
116
|
+
source: 'polling',
|
|
117
|
+
polling: props.options,
|
|
118
|
+
pollEvents: props.pollEvents,
|
|
119
|
+
handleEvent: props.handleEvent
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
return this;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
build() {
|
|
126
|
+
if (!this.#inputSchema) {
|
|
127
|
+
throw new SlateDeclarationError('Input schema is not defined');
|
|
128
|
+
}
|
|
129
|
+
if (!this.#outputSchema) {
|
|
130
|
+
throw new SlateDeclarationError('Output schema is not defined');
|
|
131
|
+
}
|
|
132
|
+
if (this.type === 'tool' && !this.#toolParams) {
|
|
133
|
+
throw new SlateDeclarationError('Tool invocation handler is not defined');
|
|
134
|
+
}
|
|
135
|
+
if (this.type === 'trigger' && !this.#triggerParams) {
|
|
136
|
+
throw new SlateDeclarationError('Trigger event handlers are not defined');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return this.factory({
|
|
140
|
+
...this.params,
|
|
141
|
+
configSchema: this.#configSchema,
|
|
142
|
+
authSchema: this.#authSchema,
|
|
143
|
+
inputSchema: this.#inputSchema,
|
|
144
|
+
outputSchema: this.#outputSchema,
|
|
145
|
+
|
|
146
|
+
...this.#toolParams!,
|
|
147
|
+
...this.#triggerParams!
|
|
148
|
+
}) as Result;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
import { SlateSpecification } from '../specification/specification';
|
|
3
|
+
import { SlateAction, SlateActionParameters, SlateToolInvocationHandler } from './action';
|
|
4
|
+
import { SlateActionBuilder } from './builder';
|
|
5
|
+
|
|
6
|
+
export interface SlateToolParameters<
|
|
7
|
+
ConfigType extends {},
|
|
8
|
+
AuthType extends {},
|
|
9
|
+
InputType extends {},
|
|
10
|
+
OutputType extends {}
|
|
11
|
+
> extends SlateActionParameters {
|
|
12
|
+
handleInvocation: SlateToolInvocationHandler<ConfigType, AuthType, InputType, OutputType>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class SlateTool<
|
|
16
|
+
ConfigType extends {},
|
|
17
|
+
AuthType extends {},
|
|
18
|
+
InputType extends {},
|
|
19
|
+
OutputType extends {}
|
|
20
|
+
> extends SlateAction<'tool', ConfigType, AuthType, InputType, OutputType> {
|
|
21
|
+
#handleInvocation: SlateToolInvocationHandler<ConfigType, AuthType, InputType, OutputType>;
|
|
22
|
+
|
|
23
|
+
private constructor(
|
|
24
|
+
spec: SlateSpecification<ConfigType, AuthType>,
|
|
25
|
+
inputSchema: z.ZodType<InputType>,
|
|
26
|
+
outputSchema: z.ZodType<OutputType>,
|
|
27
|
+
params: SlateToolParameters<ConfigType, AuthType, InputType, OutputType>
|
|
28
|
+
) {
|
|
29
|
+
super('tool', spec, inputSchema, outputSchema, params);
|
|
30
|
+
|
|
31
|
+
this.#handleInvocation = params.handleInvocation;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static create<ConfigType extends {}, AuthType extends {}>(
|
|
35
|
+
spec: SlateSpecification<ConfigType, AuthType>,
|
|
36
|
+
params: SlateActionParameters
|
|
37
|
+
) {
|
|
38
|
+
return new SlateActionBuilder('tool', spec, params, params => {
|
|
39
|
+
if (params.type != 'tool') throw new Error('Invalid action type for tool');
|
|
40
|
+
return new SlateTool(spec, params.inputSchema, params.outputSchema, params);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
get handleInvocation() {
|
|
45
|
+
return this.#handleInvocation;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export let tool = <ConfigType extends {}, AuthType extends {}>(
|
|
50
|
+
spec: SlateSpecification<ConfigType, AuthType>,
|
|
51
|
+
params: SlateActionParameters
|
|
52
|
+
) => SlateTool.create(spec, params);
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
import { SlateSpecification } from '../specification/specification';
|
|
3
|
+
import {
|
|
4
|
+
SlateAction,
|
|
5
|
+
SlateActionParameters,
|
|
6
|
+
SlatePollingOptions,
|
|
7
|
+
SlateTriggerMappingHandler,
|
|
8
|
+
SlateTriggerPollingHandler,
|
|
9
|
+
SlateTriggerWebhookAutoRegistrationHandler,
|
|
10
|
+
SlateTriggerWebhookAutoUnregistrationHandler,
|
|
11
|
+
SlateTriggerWebhookRequestHandler
|
|
12
|
+
} from './action';
|
|
13
|
+
import { SlateActionBuilder } from './builder';
|
|
14
|
+
|
|
15
|
+
export const SlateDefaultPollingIntervalSeconds = 60 * 10;
|
|
16
|
+
|
|
17
|
+
export interface SlateTriggerParameters<
|
|
18
|
+
ConfigType extends {},
|
|
19
|
+
AuthType extends {},
|
|
20
|
+
InputType extends {},
|
|
21
|
+
OutputType extends {
|
|
22
|
+
type: string;
|
|
23
|
+
}
|
|
24
|
+
> extends SlateActionParameters {
|
|
25
|
+
type: 'trigger';
|
|
26
|
+
source: 'polling' | 'webhook';
|
|
27
|
+
polling?: SlatePollingOptions;
|
|
28
|
+
handleEvent: SlateTriggerMappingHandler<ConfigType, AuthType, InputType, OutputType>;
|
|
29
|
+
handleRequest?: SlateTriggerWebhookRequestHandler<ConfigType, AuthType, InputType>;
|
|
30
|
+
pollEvents?: SlateTriggerPollingHandler<ConfigType, AuthType, InputType>;
|
|
31
|
+
autoRegisterWebhook?: SlateTriggerWebhookAutoRegistrationHandler<ConfigType, AuthType>;
|
|
32
|
+
autoUnregisterWebhook?: SlateTriggerWebhookAutoUnregistrationHandler<ConfigType, AuthType>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export class SlateTrigger<
|
|
36
|
+
ConfigType extends {},
|
|
37
|
+
AuthType extends {},
|
|
38
|
+
InputType extends {},
|
|
39
|
+
OutputType extends {
|
|
40
|
+
type: string;
|
|
41
|
+
}
|
|
42
|
+
> extends SlateAction<'trigger', ConfigType, AuthType, InputType, OutputType> {
|
|
43
|
+
#source: 'polling' | 'webhook';
|
|
44
|
+
#polling: SlatePollingOptions;
|
|
45
|
+
#handleEvent: SlateTriggerMappingHandler<ConfigType, AuthType, InputType, OutputType>;
|
|
46
|
+
#handleRequest?: SlateTriggerWebhookRequestHandler<ConfigType, AuthType, InputType>;
|
|
47
|
+
#pollEvents?: SlateTriggerPollingHandler<ConfigType, AuthType, InputType>;
|
|
48
|
+
#autoRegisterWebhook?: SlateTriggerWebhookAutoRegistrationHandler<ConfigType, AuthType>;
|
|
49
|
+
#autoUnregisterWebhook?: SlateTriggerWebhookAutoUnregistrationHandler<ConfigType, AuthType>;
|
|
50
|
+
|
|
51
|
+
private constructor(
|
|
52
|
+
spec: SlateSpecification<ConfigType, AuthType>,
|
|
53
|
+
inputSchema: z.ZodType<InputType>,
|
|
54
|
+
outputSchema: z.ZodType<OutputType>,
|
|
55
|
+
params: SlateTriggerParameters<ConfigType, AuthType, InputType, OutputType>
|
|
56
|
+
) {
|
|
57
|
+
super('trigger', spec, inputSchema, outputSchema, params);
|
|
58
|
+
|
|
59
|
+
this.#source = params.source;
|
|
60
|
+
this.#polling = params.polling || {
|
|
61
|
+
intervalInSeconds: SlateDefaultPollingIntervalSeconds
|
|
62
|
+
};
|
|
63
|
+
this.#handleEvent = params.handleEvent;
|
|
64
|
+
this.#handleRequest = params.handleRequest;
|
|
65
|
+
this.#pollEvents = params.pollEvents;
|
|
66
|
+
this.#autoRegisterWebhook = params.autoRegisterWebhook;
|
|
67
|
+
this.#autoUnregisterWebhook = params.autoUnregisterWebhook;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
static create<ConfigType extends {}, AuthType extends {}>(
|
|
71
|
+
spec: SlateSpecification<ConfigType, AuthType>,
|
|
72
|
+
params: SlateActionParameters
|
|
73
|
+
) {
|
|
74
|
+
return new SlateActionBuilder('trigger', spec, params, params => {
|
|
75
|
+
if (params.type != 'trigger') throw new Error('Invalid action type for trigger');
|
|
76
|
+
return new SlateTrigger(spec, params.inputSchema, params.outputSchema, params);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
get polling() {
|
|
81
|
+
return this.#polling;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
get source() {
|
|
85
|
+
return this.#source;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
get handleEvent() {
|
|
89
|
+
return this.#handleEvent;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
get handleRequest() {
|
|
93
|
+
return this.#handleRequest;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
get pollEvents() {
|
|
97
|
+
return this.#pollEvents;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
get autoRegisterWebhook() {
|
|
101
|
+
return this.#autoRegisterWebhook;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
get autoUnregisterWebhook() {
|
|
105
|
+
return this.#autoUnregisterWebhook;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export let trigger = <ConfigType extends {}, AuthType extends {}>(
|
|
110
|
+
spec: SlateSpecification<ConfigType, AuthType>,
|
|
111
|
+
params: SlateActionParameters
|
|
112
|
+
) => SlateTrigger.create(spec, params);
|
package/src/auth/auth.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
import { SlateAuthType } from './types';
|
|
3
|
+
|
|
4
|
+
export class SlateAuth<OutputType extends {} = {}> {
|
|
5
|
+
#outputSchema: z.ZodType<OutputType> | null = null;
|
|
6
|
+
#authStack: SlateAuthType<any, OutputType>[] = [];
|
|
7
|
+
|
|
8
|
+
private constructor() {}
|
|
9
|
+
|
|
10
|
+
static create<OutputType extends {}>() {
|
|
11
|
+
return new SlateAuth<OutputType>();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
output<NewOutputType extends {}>(
|
|
15
|
+
schema: z.ZodType<NewOutputType>
|
|
16
|
+
): SlateAuth<NewOutputType> {
|
|
17
|
+
this.#outputSchema = schema as any;
|
|
18
|
+
return this as any as SlateAuth<NewOutputType>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
private addAuth<InputType extends {}>(
|
|
22
|
+
auth: SlateAuthType<InputType, OutputType>
|
|
23
|
+
): SlateAuth<OutputType> {
|
|
24
|
+
let existingKeys = this.#authStack.map(a => a.key);
|
|
25
|
+
if (existingKeys.includes(auth.key)) {
|
|
26
|
+
throw new Error(`Auth with key "${auth.key}" already exists in the auth stack`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
this.#authStack.push(auth);
|
|
30
|
+
return this;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
addOauth<InputType extends {}>(
|
|
34
|
+
auth: SlateAuthType<InputType, OutputType> & { type: 'auth.oauth' }
|
|
35
|
+
): SlateAuth<OutputType> {
|
|
36
|
+
this.addAuth(auth as any);
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
addTokenAuth<InputType extends {}>(
|
|
41
|
+
auth: SlateAuthType<InputType, OutputType> & { type: 'auth.token' }
|
|
42
|
+
): SlateAuth<OutputType> {
|
|
43
|
+
this.addAuth(auth as any);
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
addServiceAccountAuth<InputType extends {}>(
|
|
48
|
+
auth: SlateAuthType<InputType, OutputType> & { type: 'auth.service_account' }
|
|
49
|
+
): SlateAuth<OutputType> {
|
|
50
|
+
this.addAuth(auth as any);
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
addCustomAuth<InputType extends {}>(
|
|
55
|
+
auth: SlateAuthType<InputType, OutputType> & { type: 'auth.custom' }
|
|
56
|
+
): SlateAuth<OutputType> {
|
|
57
|
+
this.addAuth(auth as any);
|
|
58
|
+
return this;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
addNone(): SlateAuth<OutputType> {
|
|
62
|
+
this.addAuth({
|
|
63
|
+
type: 'auth.none',
|
|
64
|
+
name: 'No Authentication',
|
|
65
|
+
key: 'none'
|
|
66
|
+
});
|
|
67
|
+
return this;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
get authStack() {
|
|
71
|
+
return this.#authStack.filter(a => a.type != 'auth.none');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
get outputSchema() {
|
|
75
|
+
if (!this.#outputSchema) {
|
|
76
|
+
throw new Error('Output schema is not defined for this auth');
|
|
77
|
+
}
|
|
78
|
+
return this.#outputSchema;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export let auth = <OutputType extends {} = {}>() => SlateAuth.create<OutputType>();
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
|
|
3
|
+
export type SlateAuthWithOauth<
|
|
4
|
+
InputType extends {},
|
|
5
|
+
OutputType extends {
|
|
6
|
+
token: string;
|
|
7
|
+
refreshToken?: string;
|
|
8
|
+
expiresAt?: number | string | Date;
|
|
9
|
+
}
|
|
10
|
+
> = {
|
|
11
|
+
type: 'auth.oauth';
|
|
12
|
+
|
|
13
|
+
name: string;
|
|
14
|
+
key: string;
|
|
15
|
+
|
|
16
|
+
scopes: {
|
|
17
|
+
title: string;
|
|
18
|
+
description?: string;
|
|
19
|
+
scope: string;
|
|
20
|
+
}[];
|
|
21
|
+
|
|
22
|
+
inputSchema?: z.ZodType<InputType>;
|
|
23
|
+
|
|
24
|
+
onInputChanged?: (params: {
|
|
25
|
+
previousInput: InputType | null;
|
|
26
|
+
newInput: InputType;
|
|
27
|
+
}) => Promise<{ input?: InputType } | void>;
|
|
28
|
+
|
|
29
|
+
getDefaultInput?: () => Promise<InputType>;
|
|
30
|
+
|
|
31
|
+
getAuthorizationUrl: (ctx: {
|
|
32
|
+
redirectUri: string;
|
|
33
|
+
state: string;
|
|
34
|
+
input: InputType;
|
|
35
|
+
clientId: string;
|
|
36
|
+
clientSecret: string;
|
|
37
|
+
scopes: string[];
|
|
38
|
+
}) => Promise<{
|
|
39
|
+
url: string;
|
|
40
|
+
input?: InputType;
|
|
41
|
+
}>;
|
|
42
|
+
|
|
43
|
+
handleCallback: (ctx: {
|
|
44
|
+
code: string;
|
|
45
|
+
state: string;
|
|
46
|
+
redirectUri: string;
|
|
47
|
+
input: InputType;
|
|
48
|
+
clientId: string;
|
|
49
|
+
clientSecret: string;
|
|
50
|
+
scopes: string[];
|
|
51
|
+
}) => Promise<{
|
|
52
|
+
output: OutputType;
|
|
53
|
+
input?: InputType;
|
|
54
|
+
}>;
|
|
55
|
+
|
|
56
|
+
handleTokenRefresh?: (ctx: {
|
|
57
|
+
output: OutputType;
|
|
58
|
+
input: InputType;
|
|
59
|
+
clientId: string;
|
|
60
|
+
clientSecret: string;
|
|
61
|
+
scopes: string[];
|
|
62
|
+
}) => Promise<{
|
|
63
|
+
output: OutputType;
|
|
64
|
+
input?: InputType;
|
|
65
|
+
}>;
|
|
66
|
+
|
|
67
|
+
getProfile?: (ctx: { output: OutputType; input: InputType; scopes: string[] }) => Promise<{
|
|
68
|
+
profile: Record<string, any>;
|
|
69
|
+
}>;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export type SlateAuthWithToken<InputType extends {}, OutputType extends { token?: string }> = {
|
|
73
|
+
type: 'auth.token';
|
|
74
|
+
|
|
75
|
+
name: string;
|
|
76
|
+
key: string;
|
|
77
|
+
|
|
78
|
+
inputSchema?: z.ZodType<InputType>;
|
|
79
|
+
|
|
80
|
+
getOutput: (ctx: { input: InputType }) => Promise<{ output: OutputType }>;
|
|
81
|
+
|
|
82
|
+
onInputChanged?: (params: {
|
|
83
|
+
previousInput: InputType;
|
|
84
|
+
newInput: InputType;
|
|
85
|
+
}) => Promise<{ input?: InputType } | void>;
|
|
86
|
+
|
|
87
|
+
getDefaultInput?: () => Promise<InputType>;
|
|
88
|
+
|
|
89
|
+
getProfile?: (ctx: { output: OutputType; input: InputType }) => Promise<{
|
|
90
|
+
profile: Record<string, any>;
|
|
91
|
+
}>;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export type SlateAuthWithServiceAccount<InputType extends {}, OutputType extends {}> = {
|
|
95
|
+
type: 'auth.service_account';
|
|
96
|
+
|
|
97
|
+
name: string;
|
|
98
|
+
key: string;
|
|
99
|
+
|
|
100
|
+
inputSchema?: z.ZodType<InputType>;
|
|
101
|
+
|
|
102
|
+
getOutput: (ctx: { input: InputType }) => Promise<{ output: OutputType }>;
|
|
103
|
+
|
|
104
|
+
onInputChanged?: (params: {
|
|
105
|
+
previousInput: InputType;
|
|
106
|
+
newInput: InputType;
|
|
107
|
+
}) => Promise<{ input?: InputType } | void>;
|
|
108
|
+
|
|
109
|
+
getDefaultInput?: () => Promise<InputType>;
|
|
110
|
+
|
|
111
|
+
getProfile?: (ctx: { output: OutputType; input: InputType }) => Promise<{
|
|
112
|
+
profile: Record<string, any>;
|
|
113
|
+
}>;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export type SlateAuthWithCustomData<InputType extends {}, OutputType extends {}> = {
|
|
117
|
+
type: 'auth.custom';
|
|
118
|
+
|
|
119
|
+
name: string;
|
|
120
|
+
key: string;
|
|
121
|
+
|
|
122
|
+
inputSchema?: z.ZodType<InputType>;
|
|
123
|
+
|
|
124
|
+
getOutput: (ctx: { input: InputType }) => Promise<{ output: OutputType }>;
|
|
125
|
+
|
|
126
|
+
onInputChanged?: (params: {
|
|
127
|
+
previousInput: InputType;
|
|
128
|
+
newInput: InputType;
|
|
129
|
+
}) => Promise<{ input?: InputType } | void>;
|
|
130
|
+
|
|
131
|
+
getDefaultInput?: () => Promise<InputType>;
|
|
132
|
+
|
|
133
|
+
getProfile?: (ctx: { output: OutputType; input: InputType }) => Promise<{
|
|
134
|
+
profile: Record<string, any>;
|
|
135
|
+
}>;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
export type SlateAuthWithNone<InputType extends {}, OutputType extends {}> = {
|
|
139
|
+
type: 'auth.none';
|
|
140
|
+
|
|
141
|
+
name: string;
|
|
142
|
+
key: string;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
export type SlateAuthType<InputType extends {}, OutputType extends {}> =
|
|
146
|
+
| SlateAuthWithOauth<InputType, OutputType & { token: string }>
|
|
147
|
+
| SlateAuthWithToken<InputType, OutputType & { token?: string }>
|
|
148
|
+
| SlateAuthWithServiceAccount<InputType, OutputType>
|
|
149
|
+
| SlateAuthWithCustomData<InputType, OutputType>
|
|
150
|
+
| SlateAuthWithNone<InputType, OutputType>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import baseAxios, { CreateAxiosDefaults } from 'axios';
|
|
2
|
+
import { getCurrentContext } from '../context/hook';
|
|
3
|
+
|
|
4
|
+
export let createAxios = (config?: CreateAxiosDefaults) => {
|
|
5
|
+
let instance = baseAxios.create({
|
|
6
|
+
...config,
|
|
7
|
+
headers: {
|
|
8
|
+
...config?.headers
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
instance.interceptors.request.use(
|
|
13
|
+
request => {
|
|
14
|
+
// Has to be called in the context of an action execution
|
|
15
|
+
let ctx = getCurrentContext();
|
|
16
|
+
let spec = ctx.specification;
|
|
17
|
+
|
|
18
|
+
request.headers.set('User-Agent', `slates.dev@1.0.0/${spec.key}`);
|
|
19
|
+
|
|
20
|
+
return request;
|
|
21
|
+
},
|
|
22
|
+
error => Promise.reject(error)
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
return instance;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export let axios = createAxios();
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
|
|
3
|
+
export class SlateConfig<ConfigType extends {}> {
|
|
4
|
+
#configSchema: z.ZodType<ConfigType>;
|
|
5
|
+
#configChanged:
|
|
6
|
+
| ((params: {
|
|
7
|
+
previousConfig: ConfigType | null;
|
|
8
|
+
newConfig: ConfigType;
|
|
9
|
+
}) => { config: ConfigType | undefined } | void)
|
|
10
|
+
| null = null;
|
|
11
|
+
#getDefaultConfig: (() => ConfigType) | null = null;
|
|
12
|
+
|
|
13
|
+
private constructor(schema: z.ZodType<ConfigType>) {
|
|
14
|
+
this.#configSchema = schema;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
static create<ConfigType extends {}>(schema: z.ZodType<ConfigType>) {
|
|
18
|
+
return new SlateConfig<ConfigType>(schema);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
config<NewConfigType extends {}>(
|
|
22
|
+
schema: z.ZodType<NewConfigType>
|
|
23
|
+
): SlateConfig<NewConfigType> {
|
|
24
|
+
this.#configSchema = schema as any;
|
|
25
|
+
return this as any as SlateConfig<NewConfigType>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
onConfigChanged(
|
|
29
|
+
handler: (params: {
|
|
30
|
+
previousConfig: ConfigType | null;
|
|
31
|
+
newConfig: ConfigType;
|
|
32
|
+
}) => { config: ConfigType | undefined } | void
|
|
33
|
+
): SlateConfig<ConfigType> {
|
|
34
|
+
this.#configChanged = handler;
|
|
35
|
+
return this;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
getDefaultConfig(getter: () => ConfigType): SlateConfig<ConfigType> {
|
|
39
|
+
this.#getDefaultConfig = getter;
|
|
40
|
+
return this;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
get configSchema() {
|
|
44
|
+
return this.#configSchema;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
get handlers() {
|
|
48
|
+
return {
|
|
49
|
+
configChanged: this.#configChanged,
|
|
50
|
+
getDefaultConfig: this.#getDefaultConfig
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export let config = <ConfigType extends {}>(schema: z.ZodType<ConfigType>) =>
|
|
56
|
+
SlateConfig.create<ConfigType>(schema);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './config';
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { SlateLogger, SlateLogMessageInput } from '../logger';
|
|
2
|
+
import { SlateSpecification } from '../specification/specification';
|
|
3
|
+
|
|
4
|
+
export class SlateContext<ConfigType extends {}, AuthType extends {}, InputType extends {}> {
|
|
5
|
+
#config: ConfigType;
|
|
6
|
+
#input: InputType;
|
|
7
|
+
#auth: AuthType;
|
|
8
|
+
|
|
9
|
+
constructor(
|
|
10
|
+
config: ConfigType,
|
|
11
|
+
input: InputType,
|
|
12
|
+
auth: AuthType,
|
|
13
|
+
private readonly spec: SlateSpecification<ConfigType, AuthType>,
|
|
14
|
+
private readonly logger: SlateLogger
|
|
15
|
+
) {
|
|
16
|
+
this.#config = config;
|
|
17
|
+
this.#input = input;
|
|
18
|
+
this.#auth = auth;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get specification() {
|
|
22
|
+
return this.spec;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
get config() {
|
|
26
|
+
return Object.freeze(this.#config);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
get input() {
|
|
30
|
+
return Object.freeze(this.#input);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get event() {
|
|
34
|
+
return Object.freeze(this.#input);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
get state() {
|
|
38
|
+
return Object.freeze((this.#input as any).state) as 'state' extends keyof InputType
|
|
39
|
+
? InputType['state']
|
|
40
|
+
: never;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
get request() {
|
|
44
|
+
return Object.freeze((this.#input as any).request) as 'request' extends keyof InputType
|
|
45
|
+
? InputType['request']
|
|
46
|
+
: never;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
get auth() {
|
|
50
|
+
return Object.freeze(this.#auth);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
info(message: SlateLogMessageInput) {
|
|
54
|
+
this.logger.info(message);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
warn(message: SlateLogMessageInput) {
|
|
58
|
+
this.logger.warn(message);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
error(message: SlateLogMessageInput) {
|
|
62
|
+
this.logger.error(message);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
progress(message: SlateLogMessageInput) {
|
|
66
|
+
this.logger.progress(message);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from 'async_hooks';
|
|
2
|
+
import { SlateContext } from './context';
|
|
3
|
+
|
|
4
|
+
let asyncLocalStorage = new AsyncLocalStorage<SlateContext<any, any, any>>();
|
|
5
|
+
|
|
6
|
+
export let runWithContext = <ConfigType extends {}, AuthType extends {}, InputType extends {}>(
|
|
7
|
+
context: SlateContext<ConfigType, AuthType, InputType>,
|
|
8
|
+
fn: () => Promise<void>
|
|
9
|
+
) => {
|
|
10
|
+
return asyncLocalStorage.run(context, fn);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export let getCurrentContext = <
|
|
14
|
+
ConfigType extends {},
|
|
15
|
+
AuthType extends {},
|
|
16
|
+
InputType extends {}
|
|
17
|
+
>(): SlateContext<ConfigType, AuthType, InputType> => {
|
|
18
|
+
let context = asyncLocalStorage.getStore();
|
|
19
|
+
if (!context) {
|
|
20
|
+
throw new Error('No Slate context is available');
|
|
21
|
+
}
|
|
22
|
+
return context as SlateContext<ConfigType, AuthType, InputType>;
|
|
23
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './context';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { SlateError } from './base';
|
|
2
|
+
|
|
3
|
+
export class SlateDeclarationError extends SlateError {
|
|
4
|
+
constructor(message: string) {
|
|
5
|
+
super(`[Declaration Error]: ${message}`);
|
|
6
|
+
this.name = 'SlateError.DeclarationError';
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
static is(error: unknown): error is SlateDeclarationError {
|
|
10
|
+
return error instanceof SlateDeclarationError;
|
|
11
|
+
}
|
|
12
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './logger';
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { encode } from '@toon-format/toon';
|
|
2
|
+
|
|
3
|
+
export type SlateLogType = 'info' | 'warn' | 'error' | 'progress';
|
|
4
|
+
|
|
5
|
+
export type SlateLogMessageInput =
|
|
6
|
+
| string
|
|
7
|
+
| Error
|
|
8
|
+
| boolean
|
|
9
|
+
| number
|
|
10
|
+
| null
|
|
11
|
+
| undefined
|
|
12
|
+
| object
|
|
13
|
+
| SlateLogMessageInput[];
|
|
14
|
+
|
|
15
|
+
let formatMessage = (message: SlateLogMessageInput): string => {
|
|
16
|
+
if (typeof message === 'object') {
|
|
17
|
+
if (message === null) return 'null';
|
|
18
|
+
if (message instanceof Error) {
|
|
19
|
+
return `[ERROR]: ${message.name}: ${message.message}\n${message.stack}`;
|
|
20
|
+
}
|
|
21
|
+
return encode(message);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return String(message);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export interface SlateLogEntry {
|
|
28
|
+
type: SlateLogType;
|
|
29
|
+
message: string;
|
|
30
|
+
timestamp: Date;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type SlateLogListener = (entries: SlateLogEntry[]) => void;
|
|
34
|
+
|
|
35
|
+
export class SlateLogger {
|
|
36
|
+
#logs: SlateLogEntry[] = [];
|
|
37
|
+
#listeners: SlateLogListener[] = [];
|
|
38
|
+
#timer: NodeJS.Timeout | null = null;
|
|
39
|
+
|
|
40
|
+
constructor(listeners: SlateLogListener[] = []) {
|
|
41
|
+
this.#listeners.push(...listeners);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private flush() {
|
|
45
|
+
if (this.#timer) clearTimeout(this.#timer);
|
|
46
|
+
if (this.#logs.length === 0) return;
|
|
47
|
+
|
|
48
|
+
for (let listener of this.#listeners) {
|
|
49
|
+
listener(this.#logs);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private scheduleFlush() {
|
|
54
|
+
if (this.#timer) return;
|
|
55
|
+
this.#timer = setTimeout(() => {
|
|
56
|
+
this.flush();
|
|
57
|
+
this.#timer = null;
|
|
58
|
+
}, 10);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
log(type: SlateLogType, message: SlateLogMessageInput) {
|
|
62
|
+
this.#logs.push({
|
|
63
|
+
type,
|
|
64
|
+
timestamp: new Date(),
|
|
65
|
+
message: formatMessage(message)
|
|
66
|
+
});
|
|
67
|
+
this.scheduleFlush();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
info(...message: SlateLogMessageInput[]) {
|
|
71
|
+
this.log('info', message.flat());
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
warn(...message: SlateLogMessageInput[]) {
|
|
75
|
+
this.log('warn', message.flat());
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
error(...message: SlateLogMessageInput[]) {
|
|
79
|
+
this.log('error', message.flat());
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
progress(...message: SlateLogMessageInput[]) {
|
|
83
|
+
this.log('progress', message.flat());
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { SlateTool, SlateTrigger } from '../action';
|
|
2
|
+
import { SlateSpecification } from './specification';
|
|
3
|
+
|
|
4
|
+
export class Slate<ConfigType extends {}, AuthType extends {}> {
|
|
5
|
+
private constructor(
|
|
6
|
+
private readonly _spec: SlateSpecification<ConfigType, AuthType>,
|
|
7
|
+
private readonly _actions: (
|
|
8
|
+
| SlateTrigger<ConfigType, AuthType, any, any>
|
|
9
|
+
| SlateTool<ConfigType, AuthType, any, any>
|
|
10
|
+
)[]
|
|
11
|
+
) {}
|
|
12
|
+
|
|
13
|
+
static create<ConfigType extends {}, AuthType extends {}>(params: {
|
|
14
|
+
spec: SlateSpecification<ConfigType, AuthType>;
|
|
15
|
+
triggers: SlateTrigger<ConfigType, AuthType, any, any>[];
|
|
16
|
+
tools: SlateTool<ConfigType, AuthType, any, any>[];
|
|
17
|
+
}) {
|
|
18
|
+
return new Slate(params.spec, [...params.triggers, ...params.tools]);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get spec() {
|
|
22
|
+
return this._spec;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
get actions() {
|
|
26
|
+
return this._actions;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
import { SlateAuth } from '../auth';
|
|
3
|
+
import { SlateConfig } from '../config';
|
|
4
|
+
|
|
5
|
+
export interface SlateSpecificationParameters {
|
|
6
|
+
key: string;
|
|
7
|
+
name: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
metadata?: Record<string, any>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface SlateSpecificationCreateParameters<
|
|
13
|
+
ConfigType extends {},
|
|
14
|
+
AuthType extends {}
|
|
15
|
+
> extends SlateSpecificationParameters {
|
|
16
|
+
config: SlateConfig<ConfigType>;
|
|
17
|
+
auth: SlateAuth<AuthType>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class SlateSpecification<ConfigType extends {}, AuthType extends {}> {
|
|
21
|
+
private constructor(
|
|
22
|
+
private readonly _config: SlateConfig<ConfigType>,
|
|
23
|
+
private readonly _auth: SlateAuth<AuthType>,
|
|
24
|
+
private readonly _params: SlateSpecificationParameters
|
|
25
|
+
) {}
|
|
26
|
+
|
|
27
|
+
static create<ConfigType extends {}, AuthType extends {}>(
|
|
28
|
+
params: SlateSpecificationCreateParameters<ConfigType, AuthType>
|
|
29
|
+
): SlateSpecification<ConfigType, AuthType> {
|
|
30
|
+
return new SlateSpecification(params.config, params.auth, params);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get configSchema() {
|
|
34
|
+
return this._config.configSchema;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
get authSchema() {
|
|
38
|
+
return (
|
|
39
|
+
'outputSchema' in this._auth ? this._auth.outputSchema : z.object({})
|
|
40
|
+
) as z.ZodType<AuthType>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
get config() {
|
|
44
|
+
return this._config;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
get auth() {
|
|
48
|
+
return this._auth;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
get parameters() {
|
|
52
|
+
return this._params;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
get key() {
|
|
56
|
+
return this._params.key;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
get name() {
|
|
60
|
+
return this._params.name;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
get description() {
|
|
64
|
+
return this._params.description;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export let spec = <ConfigType extends {}, AuthType extends {}>(
|
|
69
|
+
params: SlateSpecificationCreateParameters<ConfigType, AuthType>
|
|
70
|
+
): SlateSpecification<ConfigType, AuthType> => SlateSpecification.create(params);
|