@slates/provider 1.0.0-rc.1 → 1.0.0-rc.10

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 CHANGED
@@ -1,11 +1,17 @@
1
1
  {
2
2
  "name": "@slates/provider",
3
- "version": "1.0.0-rc.1",
3
+ "version": "1.0.0-rc.10",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
+ "files": [
8
+ "src/**",
9
+ "dist/**",
10
+ "README.md",
11
+ "package.json"
12
+ ],
7
13
  "author": "Tobias Herber",
8
- "license": "Apache 2",
14
+ "license": "FSL 1.1",
9
15
  "type": "module",
10
16
  "source": "src/index.ts",
11
17
  "exports": {
@@ -17,20 +23,22 @@
17
23
  "main": "./dist/index.cjs",
18
24
  "module": "./dist/index.module.js",
19
25
  "types": "dist/index.d.ts",
20
- "unpkg": "./dist/index.umd.js",
26
+ "unpkg": "./dist/index.module.js",
21
27
  "scripts": {
22
28
  "test": "vitest run --passWithNoTests",
23
29
  "lint": "prettier src/**/*.ts --check",
24
- "build": "microbundle"
30
+ "build": "tsup --config ../../tsup.packages.config.ts --external async_hooks",
31
+ "typecheck": "tsc --noEmit"
25
32
  },
26
33
  "dependencies": {
34
+ "@lowerdeck/error": "^1.1.0",
27
35
  "@toon-format/toon": "^2.1.0",
28
36
  "axios": "^1.13.2",
29
37
  "zod": "^4.2.1"
30
38
  },
31
39
  "devDependencies": {
32
40
  "microbundle": "^0.15.1",
33
- "@slates/tsconfig": "^1.0.0",
41
+ "@slates/tsconfig": "1.0.0-rc.1",
34
42
  "typescript": "5.8.2",
35
43
  "vitest": "^3.1.2"
36
44
  }
@@ -1,9 +1,18 @@
1
- import { z } from 'zod';
2
- import { SlateContext } from '../context';
3
- import { SlateSpecification } from '../specification/specification';
1
+ import type { z } from 'zod';
2
+ import type { SlateContext } from '../context';
3
+ import type { SlateSpecification } from '../specification/specification';
4
+ import type { SlateAttachment } from './attachment';
4
5
 
5
6
  export type SlateActionType = 'tool' | 'trigger';
6
7
 
8
+ export interface SlateActionScopeClause {
9
+ OR: string[];
10
+ }
11
+
12
+ export interface SlateActionScopes {
13
+ AND: SlateActionScopeClause[];
14
+ }
15
+
7
16
  export interface SlateActionParameters {
8
17
  key: string;
9
18
  name: string;
@@ -16,6 +25,7 @@ export interface SlateActionParameters {
16
25
  [key: string]: boolean | undefined;
17
26
  };
18
27
  metadata?: Record<string, any>;
28
+ scopes?: SlateActionScopes;
19
29
  }
20
30
 
21
31
  export type SlateToolInvocationHandler<
@@ -26,6 +36,7 @@ export type SlateToolInvocationHandler<
26
36
  > = (context: SlateContext<ConfigType, AuthType, InputType>) => Promise<{
27
37
  output: OutputType;
28
38
  message: string;
39
+ attachments?: SlateAttachment[];
29
40
  }>;
30
41
 
31
42
  export type SlateTriggerMappingHandler<
@@ -188,4 +199,8 @@ export abstract class SlateAction<
188
199
  get metadata() {
189
200
  return this._params.metadata;
190
201
  }
202
+
203
+ get scopes() {
204
+ return this._params.scopes;
205
+ }
191
206
  }
@@ -0,0 +1,41 @@
1
+ export interface SlateAttachmentUrlContent {
2
+ type: 'url';
3
+ url: string;
4
+ }
5
+
6
+ export interface SlateAttachmentInlineContent {
7
+ type: 'content';
8
+ encoding: 'base64' | 'utf-8';
9
+ content: string;
10
+ }
11
+
12
+ export interface SlateAttachment {
13
+ mimeType?: string;
14
+ content: SlateAttachmentUrlContent | SlateAttachmentInlineContent;
15
+ }
16
+
17
+ export let createUrlAttachment = (url: string, mimeType?: string): SlateAttachment => ({
18
+ mimeType,
19
+ content: {
20
+ type: 'url',
21
+ url
22
+ }
23
+ });
24
+
25
+ export let createBase64Attachment = (content: string, mimeType?: string): SlateAttachment => ({
26
+ mimeType,
27
+ content: {
28
+ type: 'content',
29
+ encoding: 'base64',
30
+ content
31
+ }
32
+ });
33
+
34
+ export let createTextAttachment = (content: string, mimeType?: string): SlateAttachment => ({
35
+ mimeType,
36
+ content: {
37
+ type: 'content',
38
+ encoding: 'utf-8',
39
+ content
40
+ }
41
+ });
@@ -1,9 +1,10 @@
1
- import z from 'zod';
1
+ import type z from 'zod';
2
2
  import { SlateDeclarationError } from '../error';
3
- import { SlateSpecification } from '../specification/specification';
4
- import {
3
+ import type { SlateSpecification } from '../specification/specification';
4
+ import type {
5
5
  SlateAction,
6
6
  SlateActionCreateParameters,
7
+ SlateActionScopes,
7
8
  SlateActionParameters,
8
9
  SlateActionParametersTool,
9
10
  SlateActionParametersTrigger,
@@ -16,6 +17,7 @@ import {
16
17
  SlateTriggerWebhookAutoUnregistrationHandler,
17
18
  SlateTriggerWebhookRequestHandler
18
19
  } from './action';
20
+ import { validateScopes } from './scopes';
19
21
 
20
22
  export class SlateActionBuilder<
21
23
  Type extends SlateActionType,
@@ -29,6 +31,7 @@ export class SlateActionBuilder<
29
31
  #authSchema: z.ZodType<AuthType>;
30
32
  #inputSchema: z.ZodType<InputType> | null = null;
31
33
  #outputSchema: z.ZodType<OutputType> | null = null;
34
+ #scopes: SlateActionScopes | undefined;
32
35
 
33
36
  #toolParams: SlateActionParametersTool<ConfigType, AuthType, InputType, OutputType> | null =
34
37
  null;
@@ -41,7 +44,7 @@ export class SlateActionBuilder<
41
44
 
42
45
  constructor(
43
46
  private readonly type: Type,
44
- private readonly spec: SlateSpecification<ConfigType, AuthType>,
47
+ readonly spec: SlateSpecification<ConfigType, AuthType>,
45
48
  private readonly params: SlateActionParameters,
46
49
  private readonly factory: (
47
50
  params: SlateActionCreateParameters<any, any, any, any>
@@ -65,6 +68,14 @@ export class SlateActionBuilder<
65
68
  return this as any;
66
69
  }
67
70
 
71
+ scopes(
72
+ scopes: SlateActionScopes
73
+ ): SlateActionBuilder<Type, ConfigType, AuthType, InputType, OutputType, Result> {
74
+ validateScopes(scopes);
75
+ this.#scopes = scopes;
76
+ return this;
77
+ }
78
+
68
79
  handleInvocation(
69
80
  handler: SlateToolInvocationHandler<ConfigType, AuthType, InputType, OutputType>
70
81
  ): SlateActionBuilder<Type, ConfigType, AuthType, InputType, OutputType, Result> {
@@ -123,6 +134,11 @@ export class SlateActionBuilder<
123
134
  }
124
135
 
125
136
  build() {
137
+ let scopes = this.#scopes ?? this.params.scopes;
138
+ if (scopes) {
139
+ validateScopes(scopes);
140
+ }
141
+
126
142
  if (!this.#inputSchema) {
127
143
  throw new SlateDeclarationError('Input schema is not defined');
128
144
  }
@@ -138,6 +154,7 @@ export class SlateActionBuilder<
138
154
 
139
155
  return this.factory({
140
156
  ...this.params,
157
+ scopes,
141
158
  configSchema: this.#configSchema,
142
159
  authSchema: this.#authSchema,
143
160
  inputSchema: this.#inputSchema,
@@ -1,5 +1,5 @@
1
1
  export * from './action';
2
+ export * from './scopes';
3
+ export type * from './builder';
2
4
  export * from './tool';
3
5
  export * from './trigger';
4
-
5
- export type * from './builder';
@@ -0,0 +1,77 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { allOf, anyOf, mergeScopes, scopeClause, validateScopes } from './scopes';
3
+
4
+ describe('action scope helpers', () => {
5
+ it('builds OR and AND scope clauses', () => {
6
+ expect(scopeClause('scope:read', 'scope:admin')).toEqual({
7
+ OR: ['scope:read', 'scope:admin']
8
+ });
9
+
10
+ expect(anyOf('scope:read', 'scope:admin')).toEqual({
11
+ AND: [{ OR: ['scope:read', 'scope:admin'] }]
12
+ });
13
+
14
+ expect(allOf(['scope:calendar'], ['scope:sharing', 'scope:sharing:admin'])).toEqual({
15
+ AND: [
16
+ { OR: ['scope:calendar'] },
17
+ { OR: ['scope:sharing', 'scope:sharing:admin'] }
18
+ ]
19
+ });
20
+ });
21
+
22
+ it('accepts nested scope structures and flattens them', () => {
23
+ expect(
24
+ allOf(
25
+ anyOf('scope:events.read', 'scope:events.write'),
26
+ scopeClause('scope:calendar'),
27
+ 'scope:profile'
28
+ )
29
+ ).toEqual({
30
+ AND: [
31
+ { OR: ['scope:events.read', 'scope:events.write'] },
32
+ { OR: ['scope:calendar'] },
33
+ { OR: ['scope:profile'] }
34
+ ]
35
+ });
36
+ });
37
+
38
+ it('merges multiple scope sets and skips empty inputs', () => {
39
+ expect(
40
+ mergeScopes(
41
+ anyOf('scope:calendar'),
42
+ undefined,
43
+ false,
44
+ allOf(['scope:events.read', 'scope:events.write'], 'scope:profile')
45
+ )
46
+ ).toEqual({
47
+ AND: [
48
+ { OR: ['scope:calendar'] },
49
+ { OR: ['scope:events.read', 'scope:events.write'] },
50
+ { OR: ['scope:profile'] }
51
+ ]
52
+ });
53
+
54
+ expect(mergeScopes(undefined, false, null)).toBeUndefined();
55
+ });
56
+
57
+ it('validates and clones incoming scope objects', () => {
58
+ let input = {
59
+ AND: [{ OR: ['scope:calendar', 'scope:calendar:admin'] }]
60
+ };
61
+ let validated = validateScopes(input);
62
+
63
+ expect(validated).toEqual({
64
+ AND: [{ OR: ['scope:calendar', 'scope:calendar:admin'] }]
65
+ });
66
+ expect(validated).not.toBe(input);
67
+ expect(validated.AND[0]).not.toBe(input.AND[0]);
68
+ });
69
+
70
+ it('throws helpful errors for invalid scope definitions', () => {
71
+ expect(() => scopeClause()).toThrow('Each action scope clause must include at least one OR scope');
72
+ expect(() => scopeClause('')).toThrow('Action scopes must be non-empty strings');
73
+ expect(() => validateScopes({ AND: [] })).toThrow(
74
+ 'Action scopes must include at least one AND clause'
75
+ );
76
+ });
77
+ });
@@ -0,0 +1,101 @@
1
+ import { SlateDeclarationError } from '../error';
2
+ import type { SlateActionScopeClause, SlateActionScopes } from './action';
3
+
4
+ export type SlateActionScopeValue = string;
5
+
6
+ export type SlateActionScopeClauseInput =
7
+ | SlateActionScopeValue
8
+ | readonly SlateActionScopeValue[]
9
+ | SlateActionScopeClause;
10
+
11
+ export type SlateActionScopesInput = SlateActionScopeClauseInput | SlateActionScopes;
12
+
13
+ export let scopeClause = (...scopes: SlateActionScopeValue[]): SlateActionScopeClause => {
14
+ assertScopeValues(scopes);
15
+ return {
16
+ OR: [...scopes]
17
+ };
18
+ };
19
+
20
+ export let anyOf = (...scopes: SlateActionScopeValue[]): SlateActionScopes => ({
21
+ AND: [scopeClause(...scopes)]
22
+ });
23
+
24
+ export let allOf = (...inputs: SlateActionScopesInput[]): SlateActionScopes => {
25
+ let AND = inputs.flatMap(input => normalizeScopes(input).AND);
26
+ return validateScopes({ AND });
27
+ };
28
+
29
+ export let mergeScopes = (
30
+ ...inputs: Array<SlateActionScopes | null | undefined | false>
31
+ ): SlateActionScopes | undefined => {
32
+ let AND = inputs.flatMap(input => (input ? input.AND : []));
33
+ if (AND.length === 0) {
34
+ return undefined;
35
+ }
36
+
37
+ return validateScopes({ AND });
38
+ };
39
+
40
+ export let validateScopes = (scopes: SlateActionScopes): SlateActionScopes => {
41
+ if (!Array.isArray(scopes.AND) || scopes.AND.length === 0) {
42
+ throw new SlateDeclarationError('Action scopes must include at least one AND clause');
43
+ }
44
+
45
+ return {
46
+ AND: scopes.AND.map(clause => normalizeClause(clause))
47
+ };
48
+ };
49
+
50
+ let normalizeScopes = (input: SlateActionScopesInput): SlateActionScopes => {
51
+ if (isScopes(input)) {
52
+ return validateScopes(input);
53
+ }
54
+
55
+ return {
56
+ AND: [normalizeClause(input)]
57
+ };
58
+ };
59
+
60
+ let normalizeClause = (input: SlateActionScopeClauseInput): SlateActionScopeClause => {
61
+ if (typeof input === 'string') {
62
+ return scopeClause(input);
63
+ }
64
+
65
+ if (Array.isArray(input)) {
66
+ return scopeClause(...input);
67
+ }
68
+
69
+ if (!isClause(input)) {
70
+ throw new SlateDeclarationError('Action scope clauses must be strings or OR clauses');
71
+ }
72
+
73
+ assertScopeValues(input.OR);
74
+ return {
75
+ OR: [...input.OR]
76
+ };
77
+ };
78
+
79
+ let assertScopeValues = (scopes: readonly SlateActionScopeValue[]) => {
80
+ if (scopes.length === 0) {
81
+ throw new SlateDeclarationError('Each action scope clause must include at least one OR scope');
82
+ }
83
+
84
+ for (let scope of scopes) {
85
+ if (typeof scope !== 'string' || scope.trim().length === 0) {
86
+ throw new SlateDeclarationError('Action scopes must be non-empty strings');
87
+ }
88
+ }
89
+ };
90
+
91
+ let isClause = (value: unknown): value is SlateActionScopeClause =>
92
+ typeof value === 'object' &&
93
+ value !== null &&
94
+ 'OR' in value &&
95
+ Array.isArray((value as SlateActionScopeClause).OR);
96
+
97
+ let isScopes = (value: unknown): value is SlateActionScopes =>
98
+ typeof value === 'object' &&
99
+ value !== null &&
100
+ 'AND' in value &&
101
+ Array.isArray((value as SlateActionScopes).AND);
@@ -1,6 +1,10 @@
1
- import z from 'zod';
2
- import { SlateSpecification } from '../specification/specification';
3
- import { SlateAction, SlateActionParameters, SlateToolInvocationHandler } from './action';
1
+ import type z from 'zod';
2
+ import type { SlateSpecification } from '../specification/specification';
3
+ import {
4
+ SlateAction,
5
+ type SlateActionParameters,
6
+ type SlateToolInvocationHandler
7
+ } from './action';
4
8
  import { SlateActionBuilder } from './builder';
5
9
 
6
10
  export interface SlateToolParameters<
@@ -36,7 +40,7 @@ export class SlateTool<
36
40
  params: SlateActionParameters
37
41
  ) {
38
42
  return new SlateActionBuilder('tool', spec, params, params => {
39
- if (params.type != 'tool') throw new Error('Invalid action type for tool');
43
+ if (params.type !== 'tool') throw new Error('Invalid action type for tool');
40
44
  return new SlateTool(spec, params.inputSchema, params.outputSchema, params);
41
45
  });
42
46
  }
@@ -1,18 +1,18 @@
1
- import z from 'zod';
2
- import { SlateSpecification } from '../specification/specification';
1
+ import type z from 'zod';
2
+ import type { SlateSpecification } from '../specification/specification';
3
3
  import {
4
4
  SlateAction,
5
- SlateActionParameters,
6
- SlatePollingOptions,
7
- SlateTriggerMappingHandler,
8
- SlateTriggerPollingHandler,
9
- SlateTriggerWebhookAutoRegistrationHandler,
10
- SlateTriggerWebhookAutoUnregistrationHandler,
11
- SlateTriggerWebhookRequestHandler
5
+ type SlateActionParameters,
6
+ type SlatePollingOptions,
7
+ type SlateTriggerMappingHandler,
8
+ type SlateTriggerPollingHandler,
9
+ type SlateTriggerWebhookAutoRegistrationHandler,
10
+ type SlateTriggerWebhookAutoUnregistrationHandler,
11
+ type SlateTriggerWebhookRequestHandler
12
12
  } from './action';
13
13
  import { SlateActionBuilder } from './builder';
14
14
 
15
- export const SlateDefaultPollingIntervalSeconds = 60 * 10;
15
+ export let SlateDefaultPollingIntervalSeconds = 60 * 10;
16
16
 
17
17
  export interface SlateTriggerParameters<
18
18
  ConfigType extends {},
@@ -72,7 +72,7 @@ export class SlateTrigger<
72
72
  params: SlateActionParameters
73
73
  ) {
74
74
  return new SlateActionBuilder('trigger', spec, params, params => {
75
- if (params.type != 'trigger') throw new Error('Invalid action type for trigger');
75
+ if (params.type !== 'trigger') throw new Error('Invalid action type for trigger');
76
76
  return new SlateTrigger(spec, params.inputSchema, params.outputSchema, params);
77
77
  });
78
78
  }
package/src/auth/auth.ts CHANGED
@@ -1,5 +1,5 @@
1
- import z from 'zod';
2
- import { SlateAuthType } from './types';
1
+ import type z from 'zod';
2
+ import type { SlateAuthType } from './types';
3
3
 
4
4
  export class SlateAuth<OutputType extends {} = {}> {
5
5
  #outputSchema: z.ZodType<OutputType> | null = null;
@@ -68,7 +68,7 @@ export class SlateAuth<OutputType extends {} = {}> {
68
68
  }
69
69
 
70
70
  get authStack() {
71
- return this.#authStack.filter(a => a.type != 'auth.none');
71
+ return this.#authStack.filter(a => a.type !== 'auth.none');
72
72
  }
73
73
 
74
74
  get outputSchema() {
package/src/auth/types.ts CHANGED
@@ -1,4 +1,4 @@
1
- import z from 'zod';
1
+ import type z from 'zod';
2
2
 
3
3
  export type SlateAuthWithOauth<
4
4
  InputType extends {},
@@ -16,6 +16,7 @@ export type SlateAuthWithOauth<
16
16
  scopes: {
17
17
  title: string;
18
18
  description?: string;
19
+ defaultChecked?: boolean;
19
20
  scope: string;
20
21
  }[];
21
22
 
@@ -24,7 +25,7 @@ export type SlateAuthWithOauth<
24
25
  onInputChanged?: (params: {
25
26
  previousInput: InputType | null;
26
27
  newInput: InputType;
27
- }) => Promise<{ input?: InputType } | void>;
28
+ }) => Promise<{ input?: InputType } | undefined>;
28
29
 
29
30
  getDefaultInput?: () => Promise<InputType>;
30
31
 
@@ -38,6 +39,7 @@ export type SlateAuthWithOauth<
38
39
  }) => Promise<{
39
40
  url: string;
40
41
  input?: InputType;
42
+ callbackState?: Record<string, any>;
41
43
  }>;
42
44
 
43
45
  handleCallback: (ctx: {
@@ -48,9 +50,11 @@ export type SlateAuthWithOauth<
48
50
  clientId: string;
49
51
  clientSecret: string;
50
52
  scopes: string[];
53
+ callbackState: Record<string, any>;
51
54
  }) => Promise<{
52
55
  output: OutputType;
53
56
  input?: InputType;
57
+ scopes?: string[];
54
58
  }>;
55
59
 
56
60
  handleTokenRefresh?: (ctx: {
@@ -82,7 +86,7 @@ export type SlateAuthWithToken<InputType extends {}, OutputType extends { token?
82
86
  onInputChanged?: (params: {
83
87
  previousInput: InputType;
84
88
  newInput: InputType;
85
- }) => Promise<{ input?: InputType } | void>;
89
+ }) => Promise<{ input?: InputType } | undefined>;
86
90
 
87
91
  getDefaultInput?: () => Promise<InputType>;
88
92
 
@@ -104,7 +108,7 @@ export type SlateAuthWithServiceAccount<InputType extends {}, OutputType extends
104
108
  onInputChanged?: (params: {
105
109
  previousInput: InputType;
106
110
  newInput: InputType;
107
- }) => Promise<{ input?: InputType } | void>;
111
+ }) => Promise<{ input?: InputType } | undefined>;
108
112
 
109
113
  getDefaultInput?: () => Promise<InputType>;
110
114
 
@@ -126,7 +130,7 @@ export type SlateAuthWithCustomData<InputType extends {}, OutputType extends {}>
126
130
  onInputChanged?: (params: {
127
131
  previousInput: InputType;
128
132
  newInput: InputType;
129
- }) => Promise<{ input?: InputType } | void>;
133
+ }) => Promise<{ input?: InputType } | undefined>;
130
134
 
131
135
  getDefaultInput?: () => Promise<InputType>;
132
136
 
@@ -135,7 +139,7 @@ export type SlateAuthWithCustomData<InputType extends {}, OutputType extends {}>
135
139
  }>;
136
140
  };
137
141
 
138
- export type SlateAuthWithNone<InputType extends {}, OutputType extends {}> = {
142
+ export type SlateAuthWithNone<_InputType extends {}, _OutputType extends {}> = {
139
143
  type: 'auth.none';
140
144
 
141
145
  name: string;
@@ -1,14 +1,22 @@
1
- import baseAxios, { CreateAxiosDefaults } from 'axios';
1
+ import type { AxiosInstance, CreateAxiosDefaults, InternalAxiosRequestConfig } from 'axios';
2
+ import baseAxios, { getAdapter, isAxiosError } from 'axios';
2
3
  import { getCurrentContext } from '../context/hook';
4
+ import type { SlateAxiosErrorOptions } from '../error';
5
+ import { SlateError } from '../error';
6
+ import {
7
+ attachHttpTraceDraft,
8
+ recordHttpTraceFromError,
9
+ recordHttpTraceFromResponse
10
+ } from './trace';
3
11
 
4
- export let createAxios = (config?: CreateAxiosDefaults) => {
5
- let instance = baseAxios.create({
6
- ...config,
7
- headers: {
8
- ...config?.headers
9
- }
10
- });
12
+ export interface SlateAxiosDefaults extends CreateAxiosDefaults {
13
+ errorMapping?: SlateAxiosErrorOptions;
14
+ }
11
15
 
16
+ let applySlateInterceptors = (
17
+ instance: AxiosInstance,
18
+ errorMapping?: SlateAxiosErrorOptions
19
+ ) => {
12
20
  instance.interceptors.request.use(
13
21
  request => {
14
22
  // Has to be called in the context of an action execution
@@ -16,12 +24,51 @@ export let createAxios = (config?: CreateAxiosDefaults) => {
16
24
  let spec = ctx.specification;
17
25
 
18
26
  request.headers.set('User-Agent', `slates.dev@1.0.0/${spec.key}`);
27
+ request.headers.set('X-Slates-Provider', spec.key);
19
28
 
20
- return request;
29
+ let tracedRequest = attachHttpTraceDraft(request, ctx) as InternalAxiosRequestConfig & {
30
+ __slatesTraceAdapterWrapped?: boolean;
31
+ };
32
+
33
+ if (!tracedRequest.__slatesTraceAdapterWrapped) {
34
+ let adapter = getAdapter(tracedRequest.adapter ?? baseAxios.defaults.adapter);
35
+ tracedRequest.adapter = async config => {
36
+ try {
37
+ let response = await adapter(config);
38
+ return recordHttpTraceFromResponse(response);
39
+ } catch (error) {
40
+ if (isAxiosError(error)) {
41
+ recordHttpTraceFromError(error);
42
+ }
43
+ throw error;
44
+ }
45
+ };
46
+ tracedRequest.__slatesTraceAdapterWrapped = true;
47
+ }
48
+
49
+ return tracedRequest;
21
50
  },
22
51
  error => Promise.reject(error)
23
52
  );
24
53
 
54
+ instance.interceptors.response.use(
55
+ response => response,
56
+ error => Promise.reject(SlateError.fromAxios(error, errorMapping))
57
+ );
58
+ };
59
+
60
+ applySlateInterceptors(baseAxios);
61
+
62
+ export let createAxios = (config?: SlateAxiosDefaults) => {
63
+ let { errorMapping, ...axiosConfig } = config ?? {};
64
+ let instance = baseAxios.create({
65
+ ...axiosConfig,
66
+ headers: {
67
+ ...axiosConfig.headers
68
+ }
69
+ });
70
+
71
+ applySlateInterceptors(instance, errorMapping);
25
72
  return instance;
26
73
  };
27
74