@slates/provider 1.0.0-rc.6 → 1.0.0-rc.8

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 (87) hide show
  1. package/dist/index.cjs +1588 -2
  2. package/dist/index.d.cts +602 -0
  3. package/dist/index.d.ts +602 -9
  4. package/dist/index.module.js +1519 -2
  5. package/package.json +8 -6
  6. package/src/action/action.ts +16 -3
  7. package/src/action/builder.ts +21 -4
  8. package/src/action/index.ts +2 -2
  9. package/src/action/scopes.test.ts +77 -0
  10. package/src/action/scopes.ts +101 -0
  11. package/src/action/tool.ts +8 -4
  12. package/src/action/trigger.ts +11 -11
  13. package/src/auth/auth.ts +3 -3
  14. package/src/auth/types.ts +7 -6
  15. package/src/axios/index.ts +56 -9
  16. package/src/axios/trace.ts +443 -0
  17. package/src/config/config.ts +3 -3
  18. package/src/context/context.ts +29 -2
  19. package/src/context/hook.ts +1 -1
  20. package/src/error/axios.ts +219 -0
  21. package/src/error/base.test.ts +178 -0
  22. package/src/error/base.ts +108 -2
  23. package/src/error/declaration.ts +7 -2
  24. package/src/error/defaults.ts +50 -0
  25. package/src/error/index.ts +3 -0
  26. package/src/error/service.ts +160 -0
  27. package/src/error/types.ts +73 -0
  28. package/src/error/utils.ts +155 -0
  29. package/src/logger/logger.test.ts +57 -0
  30. package/src/logger/logger.ts +72 -11
  31. package/src/specification/slate.ts +2 -2
  32. package/src/specification/specification.ts +2 -2
  33. package/dist/action/action.d.ts +0 -98
  34. package/dist/action/action.d.ts.map +0 -1
  35. package/dist/action/builder.d.ts +0 -27
  36. package/dist/action/builder.d.ts.map +0 -1
  37. package/dist/action/index.d.ts +0 -5
  38. package/dist/action/index.d.ts.map +0 -1
  39. package/dist/action/tool.d.ts +0 -14
  40. package/dist/action/tool.d.ts.map +0 -1
  41. package/dist/action/trigger.d.ts +0 -32
  42. package/dist/action/trigger.d.ts.map +0 -1
  43. package/dist/auth/auth.d.ts +0 -30
  44. package/dist/auth/auth.d.ts.map +0 -1
  45. package/dist/auth/index.d.ts +0 -3
  46. package/dist/auth/index.d.ts.map +0 -1
  47. package/dist/auth/types.d.ts +0 -150
  48. package/dist/auth/types.d.ts.map +0 -1
  49. package/dist/axios/index.d.ts +0 -4
  50. package/dist/axios/index.d.ts.map +0 -1
  51. package/dist/config/config.d.ts +0 -26
  52. package/dist/config/config.d.ts.map +0 -1
  53. package/dist/config/index.d.ts +0 -2
  54. package/dist/config/index.d.ts.map +0 -1
  55. package/dist/context/context.d.ts +0 -20
  56. package/dist/context/context.d.ts.map +0 -1
  57. package/dist/context/hook.d.ts +0 -4
  58. package/dist/context/hook.d.ts.map +0 -1
  59. package/dist/context/index.d.ts +0 -3
  60. package/dist/context/index.d.ts.map +0 -1
  61. package/dist/error/base.d.ts +0 -5
  62. package/dist/error/base.d.ts.map +0 -1
  63. package/dist/error/declaration.d.ts +0 -6
  64. package/dist/error/declaration.d.ts.map +0 -1
  65. package/dist/error/index.d.ts +0 -3
  66. package/dist/error/index.d.ts.map +0 -1
  67. package/dist/index.cjs.map +0 -1
  68. package/dist/index.d.ts.map +0 -1
  69. package/dist/index.modern.js +0 -2
  70. package/dist/index.modern.js.map +0 -1
  71. package/dist/index.module.js.map +0 -1
  72. package/dist/index.umd.js +0 -2
  73. package/dist/index.umd.js.map +0 -1
  74. package/dist/logger/index.d.ts +0 -2
  75. package/dist/logger/index.d.ts.map +0 -1
  76. package/dist/logger/logger.d.ts +0 -20
  77. package/dist/logger/logger.d.ts.map +0 -1
  78. package/dist/specification/index.d.ts +0 -3
  79. package/dist/specification/index.d.ts.map +0 -1
  80. package/dist/specification/slate.d.ts +0 -15
  81. package/dist/specification/slate.d.ts.map +0 -1
  82. package/dist/specification/specification.d.ts +0 -30
  83. package/dist/specification/specification.d.ts.map +0 -1
  84. package/dist/specification/zero.d.ts +0 -13
  85. package/dist/specification/zero.d.ts.map +0 -1
  86. package/dist/tokens.d.ts +0 -34
  87. package/dist/tokens.d.ts.map +0 -1
@@ -0,0 +1,219 @@
1
+ import type { AxiosError } from 'axios';
2
+ import { isAxiosError } from 'axios';
3
+ import { getCurrentContext } from '../context/hook';
4
+ import type { SlateAxiosErrorOptions, SlateErrorResponse } from './types';
5
+ import {
6
+ getDefaultMessage,
7
+ isRecord,
8
+ mergeRecords,
9
+ normalizeKind,
10
+ normalizeRetryable,
11
+ normalizeSlateErrorInput,
12
+ sanitizeForBaggage
13
+ } from './utils';
14
+
15
+ let getResponseField = (value: unknown, key: string): unknown => {
16
+ if (!isRecord(value)) return undefined;
17
+ return value[key];
18
+ };
19
+
20
+ let getNestedMessage = (value: unknown): string | undefined => {
21
+ if (typeof value === 'string') return value;
22
+ if (!isRecord(value)) return undefined;
23
+
24
+ let message = getResponseField(value, 'message');
25
+ if (typeof message === 'string' && message.trim()) return message;
26
+
27
+ let description = getResponseField(value, 'description');
28
+ if (typeof description === 'string' && description.trim()) return description;
29
+
30
+ let error = getResponseField(value, 'error');
31
+ if (typeof error === 'string' && error.trim()) return error;
32
+ if (isRecord(error)) {
33
+ let nested = getNestedMessage(error);
34
+ if (nested) return nested;
35
+ }
36
+
37
+ let errorDescription = getResponseField(value, 'error_description');
38
+ if (typeof errorDescription === 'string' && errorDescription.trim()) {
39
+ return errorDescription;
40
+ }
41
+
42
+ return undefined;
43
+ };
44
+
45
+ let getNestedCode = (value: unknown): string | undefined => {
46
+ if (!isRecord(value)) return undefined;
47
+
48
+ let directCode = getResponseField(value, 'code');
49
+ if (typeof directCode === 'string' && directCode.trim()) return directCode;
50
+
51
+ let errorCode = getResponseField(value, 'error_code');
52
+ if (typeof errorCode === 'string' && errorCode.trim()) return errorCode;
53
+
54
+ let type = getResponseField(value, 'type');
55
+ if (typeof type === 'string' && type.trim()) return type;
56
+
57
+ let error = getResponseField(value, 'error');
58
+ if (typeof error === 'string' && error.trim()) return error;
59
+ if (isRecord(error)) return getNestedCode(error);
60
+
61
+ return undefined;
62
+ };
63
+
64
+ let getNestedType = (value: unknown): string | undefined => {
65
+ if (!isRecord(value)) return undefined;
66
+
67
+ let type = getResponseField(value, 'type');
68
+ if (typeof type === 'string' && type.trim()) return type;
69
+
70
+ let error = getResponseField(value, 'error');
71
+ if (isRecord(error)) {
72
+ let nestedType = getNestedType(error);
73
+ if (nestedType) return nestedType;
74
+ }
75
+
76
+ return undefined;
77
+ };
78
+
79
+ let getHeaderValue = (headers: unknown, key: string): string | undefined => {
80
+ if (!headers) return undefined;
81
+
82
+ if (typeof (headers as { get?: unknown }).get === 'function') {
83
+ let value = (headers as { get(name: string): unknown }).get(key);
84
+ if (typeof value === 'string' && value.trim()) return value;
85
+ }
86
+
87
+ if (isRecord(headers)) {
88
+ for (let [headerKey, headerValue] of Object.entries(headers)) {
89
+ if (headerKey.toLowerCase() !== key.toLowerCase()) continue;
90
+ if (typeof headerValue === 'string' && headerValue.trim()) return headerValue;
91
+ if (Array.isArray(headerValue)) {
92
+ let first = headerValue.find(item => typeof item === 'string' && item.trim());
93
+ if (typeof first === 'string') return first;
94
+ }
95
+ }
96
+ }
97
+
98
+ return undefined;
99
+ };
100
+
101
+ let buildRequestUrl = (error: AxiosError) => {
102
+ let baseURL = error.config?.baseURL;
103
+ let url = error.config?.url;
104
+
105
+ if (!url) return undefined;
106
+ if (!baseURL) return url;
107
+
108
+ try {
109
+ return new URL(url, baseURL).toString();
110
+ } catch {
111
+ return url;
112
+ }
113
+ };
114
+
115
+ let getProviderDefaults = (): Partial<SlateErrorResponse> => {
116
+ try {
117
+ let ctx = getCurrentContext();
118
+ return {
119
+ provider: {
120
+ key: ctx.specification.key
121
+ }
122
+ };
123
+ } catch {
124
+ return {};
125
+ }
126
+ };
127
+
128
+ let inferAxiosCode = (error: AxiosError, data: unknown) => {
129
+ let status = error.response?.status;
130
+ let axiosCode = error.code?.toUpperCase();
131
+ let remoteCode = getNestedCode(data)?.toLowerCase();
132
+
133
+ if (
134
+ axiosCode === 'ECONNABORTED' ||
135
+ axiosCode === 'ETIMEDOUT' ||
136
+ status === 408 ||
137
+ remoteCode?.includes('timeout')
138
+ ) {
139
+ return 'upstream.timeout';
140
+ }
141
+
142
+ if (!error.response) {
143
+ return 'upstream.network_error';
144
+ }
145
+
146
+ if (status === 401) return 'auth.invalid';
147
+ if (status === 403) {
148
+ return remoteCode?.includes('rate') ? 'upstream.rate_limited' : 'permission.denied';
149
+ }
150
+ if (status === 404) return 'resource.not_found';
151
+ if (status === 409) return 'resource.conflict';
152
+ if (status === 422 || status === 400) return 'upstream.invalid_request';
153
+ if (status === 429) return 'upstream.rate_limited';
154
+ if (status === 502 || status === 503 || status === 504) return 'upstream.unavailable';
155
+ if (status && status >= 500) return 'upstream.error';
156
+
157
+ return 'upstream.error';
158
+ };
159
+
160
+ let inferAxiosMessage = (error: AxiosError, data: unknown, code: string) => {
161
+ return (
162
+ getNestedMessage(data) ??
163
+ error.response?.statusText ??
164
+ error.message ??
165
+ getDefaultMessage(code)
166
+ );
167
+ };
168
+
169
+ let inferAxiosRetryable = (error: AxiosError, code: string) => {
170
+ let headerValue = getHeaderValue(error.response?.headers, 'retry-after');
171
+ if (headerValue) return true;
172
+ return normalizeRetryable(code, undefined);
173
+ };
174
+
175
+ export let isAxiosErrorLike = (error: unknown): error is AxiosError => isAxiosError(error);
176
+
177
+ export let inferSlateErrorFromAxios = (
178
+ error: AxiosError,
179
+ options: SlateAxiosErrorOptions = {}
180
+ ): SlateErrorResponse => {
181
+ let responseData = error.response
182
+ ? (options.extractResponseData?.(error.response) ?? error.response.data)
183
+ : undefined;
184
+
185
+ let code = inferAxiosCode(error, responseData);
186
+
187
+ return normalizeSlateErrorInput({
188
+ ...getProviderDefaults(),
189
+ ...options.defaults,
190
+ code: options.defaults?.code ?? code,
191
+ message: options.defaults?.message ?? inferAxiosMessage(error, responseData, code),
192
+ kind: options.defaults?.kind ?? normalizeKind(options.defaults?.code ?? code),
193
+ retryable:
194
+ options.defaults?.retryable ??
195
+ inferAxiosRetryable(error, options.defaults?.code ?? code),
196
+ status: options.defaults?.status ?? error.response?.status,
197
+ provider: {
198
+ ...getProviderDefaults().provider,
199
+ ...(options.defaults?.provider ?? {})
200
+ },
201
+ upstream: {
202
+ ...(options.defaults?.upstream ?? {}),
203
+ status: error.response?.status ?? options.defaults?.upstream?.status,
204
+ code: getNestedCode(responseData) ?? options.defaults?.upstream?.code,
205
+ type: getNestedType(responseData) ?? options.defaults?.upstream?.type,
206
+ requestId:
207
+ getHeaderValue(error.response?.headers, 'x-request-id') ??
208
+ getHeaderValue(error.response?.headers, 'request-id') ??
209
+ getHeaderValue(error.response?.headers, 'x-correlation-id') ??
210
+ options.defaults?.upstream?.requestId,
211
+ method: error.config?.method?.toUpperCase() ?? options.defaults?.upstream?.method,
212
+ url: buildRequestUrl(error) ?? options.defaults?.upstream?.url
213
+ },
214
+ baggage: mergeRecords(options.defaults?.baggage, {
215
+ axiosCode: error.code,
216
+ response: sanitizeForBaggage(responseData)
217
+ })
218
+ });
219
+ };
@@ -0,0 +1,178 @@
1
+ import {
2
+ badRequestError,
3
+ conflictError,
4
+ forbiddenError,
5
+ goneError,
6
+ internalServerError,
7
+ invalidVersion,
8
+ notAcceptableError,
9
+ notFoundError,
10
+ notImplementedError,
11
+ paymentRequiredError,
12
+ preconditionFailedError,
13
+ timeoutError,
14
+ tooManyRequestsError,
15
+ unauthorizedError,
16
+ validationError
17
+ } from '@lowerdeck/error';
18
+ import { AxiosError, type AxiosResponse, type InternalAxiosRequestConfig } from 'axios';
19
+ import { describe, expect, it } from 'vitest';
20
+ import { SlateError } from './base';
21
+
22
+ let createConfig = (overrides: Partial<InternalAxiosRequestConfig> = {}) =>
23
+ ({
24
+ url: '/issues',
25
+ method: 'get',
26
+ headers: {},
27
+ ...overrides
28
+ }) as InternalAxiosRequestConfig;
29
+
30
+ let createResponse = (overrides: Partial<AxiosResponse> = {}) =>
31
+ ({
32
+ status: 429,
33
+ statusText: 'Too Many Requests',
34
+ headers: {
35
+ 'x-request-id': 'req_123'
36
+ },
37
+ config: createConfig(),
38
+ data: {
39
+ error: {
40
+ code: 'rate_limited',
41
+ message: 'GitHub API rate limit exceeded',
42
+ type: 'rate_limit'
43
+ }
44
+ },
45
+ ...overrides
46
+ }) as AxiosResponse;
47
+
48
+ describe('SlateError', () => {
49
+ it('maps axios responses to structured slate errors', () => {
50
+ let axiosError = new AxiosError(
51
+ 'Request failed with status code 429',
52
+ 'ERR_BAD_REQUEST',
53
+ createConfig(),
54
+ undefined,
55
+ createResponse()
56
+ );
57
+
58
+ let error = SlateError.fromAxios(axiosError, {
59
+ defaults: {
60
+ provider: {
61
+ service: 'github',
62
+ operation: 'issues.list'
63
+ }
64
+ }
65
+ });
66
+
67
+ expect(error).toBeInstanceOf(SlateError);
68
+ expect(error.code).toBe('upstream.rate_limited');
69
+ expect(error.status).toBe(429);
70
+ expect(error.retryable).toBe(true);
71
+ expect(error.data.provider).toEqual({
72
+ service: 'github',
73
+ operation: 'issues.list'
74
+ });
75
+ expect(error.data.upstream).toMatchObject({
76
+ status: 429,
77
+ code: 'rate_limited',
78
+ type: 'rate_limit',
79
+ requestId: 'req_123',
80
+ method: 'GET',
81
+ url: '/issues'
82
+ });
83
+ expect(error.data.baggage?.response).toBeTruthy();
84
+ });
85
+
86
+ it('maps transport failures without responses', () => {
87
+ let axiosError = new AxiosError('socket hang up', 'ECONNRESET', createConfig());
88
+
89
+ let error = SlateError.fromAxios(axiosError);
90
+
91
+ expect(error.code).toBe('upstream.network_error');
92
+ expect(error.kind).toBe('upstream');
93
+ expect(error.retryable).toBe(true);
94
+ expect(error.data.upstream).toMatchObject({
95
+ method: 'GET',
96
+ url: '/issues'
97
+ });
98
+ });
99
+
100
+ it('lets providers override inferred axios mappings', () => {
101
+ let axiosError = new AxiosError(
102
+ 'Request failed with status code 404',
103
+ 'ERR_BAD_REQUEST',
104
+ createConfig({ method: 'post', url: '/contacts' }),
105
+ undefined,
106
+ createResponse({
107
+ status: 404,
108
+ statusText: 'Not Found',
109
+ data: {
110
+ error: {
111
+ code: 'contact_missing',
112
+ message: 'Contact does not exist'
113
+ }
114
+ }
115
+ })
116
+ );
117
+
118
+ let error = SlateError.fromAxios(axiosError, {
119
+ mapAxiosError: (_, inferred) => ({
120
+ ...inferred,
121
+ code: 'resource.not_found',
122
+ message: 'Salesforce contact was not found',
123
+ provider: {
124
+ ...inferred.provider,
125
+ service: 'salesforce',
126
+ operation: 'contacts.create'
127
+ },
128
+ baggage: {
129
+ ...inferred.baggage,
130
+ entity: 'contact'
131
+ }
132
+ })
133
+ });
134
+
135
+ expect(error.code).toBe('resource.not_found');
136
+ expect(error.message).toBe('Salesforce contact was not found');
137
+ expect(error.data.provider).toEqual({
138
+ service: 'salesforce',
139
+ operation: 'contacts.create'
140
+ });
141
+ expect(error.data.baggage?.entity).toBe('contact');
142
+ });
143
+
144
+ it('maps service errors to canonical slate errors', () => {
145
+ let serviceErrors = [
146
+ [
147
+ validationError({ entity: 'request', errors: [], message: 'Invalid request data' }),
148
+ 'input.invalid'
149
+ ],
150
+ [badRequestError({ message: 'Bad request' }), 'request.bad'],
151
+ [notFoundError('handler', 'missing'), 'resource.not_found'],
152
+ [unauthorizedError({ message: 'Please log in' }), 'auth.required'],
153
+ [forbiddenError({ message: 'Forbidden' }), 'permission.denied'],
154
+ [invalidVersion({ message: 'Invalid version' }), 'request.invalid_version'],
155
+ [conflictError({ message: 'Conflict' }), 'resource.conflict'],
156
+ [goneError({ message: 'Gone' }), 'resource.gone'],
157
+ [paymentRequiredError({ message: 'Payment required' }), 'payment.required'],
158
+ [
159
+ preconditionFailedError({ message: 'Precondition failed' }),
160
+ 'request.precondition_failed'
161
+ ],
162
+ [notAcceptableError({ message: 'Not acceptable' }), 'request.not_acceptable'],
163
+ [notImplementedError({ message: 'Not implemented' }), 'operation.not_implemented'],
164
+ [tooManyRequestsError({ message: 'Too many requests' }), 'request.rate_limited'],
165
+ [timeoutError({ message: 'Timed out' }), 'internal.timeout'],
166
+ [internalServerError({ message: 'Internal error' }), 'internal.unexpected']
167
+ ] as const;
168
+
169
+ for (let [serviceError, code] of serviceErrors) {
170
+ let error = SlateError.fromServiceError(serviceError);
171
+ expect(error.code).toBe(code);
172
+ expect(error.data.baggage?.serviceError).toMatchObject({
173
+ code: serviceError.data.code,
174
+ status: serviceError.data.status
175
+ });
176
+ }
177
+ });
178
+ });
package/src/error/base.ts CHANGED
@@ -1,10 +1,116 @@
1
+ import { inferSlateErrorFromAxios, isAxiosErrorLike } from './axios';
2
+ import { DEFAULT_CODE } from './defaults';
3
+ import { getServiceErrorData, mapServiceErrorToSlateErrorInput } from './service';
4
+ import type { SlateAxiosErrorOptions, SlateErrorInput, SlateErrorResponse } from './types';
5
+ import {
6
+ getDefaultMessage,
7
+ isSlateErrorResponse,
8
+ mergeRecords,
9
+ mergeSlateErrorData,
10
+ normalizeSlateErrorInput,
11
+ sanitizeForBaggage
12
+ } from './utils';
13
+
1
14
  export class SlateError extends Error {
2
- constructor(message: string) {
3
- super(message);
15
+ cause?: unknown;
16
+ data: SlateErrorResponse;
17
+
18
+ constructor(input: SlateErrorInput) {
19
+ let normalized = normalizeSlateErrorInput(input);
20
+ super(normalized.message);
4
21
  this.name = 'SlateError';
22
+ this.data = normalized;
23
+ this.cause = input.cause;
24
+ }
25
+
26
+ get code() {
27
+ return this.data.code;
28
+ }
29
+
30
+ get kind() {
31
+ return this.data.kind;
32
+ }
33
+
34
+ get status() {
35
+ return this.data.status;
36
+ }
37
+
38
+ get retryable() {
39
+ return this.data.retryable;
40
+ }
41
+
42
+ toResponse(): SlateErrorResponse {
43
+ return {
44
+ ...this.data
45
+ };
46
+ }
47
+
48
+ toJSON(): SlateErrorResponse {
49
+ return this.toResponse();
5
50
  }
6
51
 
7
52
  static is(error: unknown): error is SlateError {
8
53
  return error instanceof SlateError;
9
54
  }
55
+
56
+ static fromUnknown(error: unknown, defaults: Partial<SlateErrorResponse> = {}): SlateError {
57
+ if (SlateError.is(error)) return error;
58
+ if (isSlateErrorResponse(error)) return new SlateError({ ...defaults, ...error });
59
+ if (getServiceErrorData(error)) return SlateError.fromServiceError(error, defaults);
60
+ if (isAxiosErrorLike(error)) return SlateError.fromAxios(error, { defaults });
61
+
62
+ if (error instanceof Error) {
63
+ return new SlateError({
64
+ code: defaults.code ?? DEFAULT_CODE,
65
+ message: error.message,
66
+ kind: defaults.kind,
67
+ retryable: defaults.retryable,
68
+ status: defaults.status,
69
+ issues: defaults.issues,
70
+ provider: defaults.provider,
71
+ upstream: defaults.upstream,
72
+ baggage: mergeRecords(defaults.baggage, {
73
+ originalName: error.name
74
+ }),
75
+ cause: error
76
+ });
77
+ }
78
+
79
+ return new SlateError({
80
+ code: defaults.code ?? DEFAULT_CODE,
81
+ message: getDefaultMessage(defaults.code ?? DEFAULT_CODE, defaults.message),
82
+ kind: defaults.kind,
83
+ retryable: defaults.retryable,
84
+ status: defaults.status,
85
+ issues: defaults.issues,
86
+ provider: defaults.provider,
87
+ upstream: defaults.upstream,
88
+ baggage: mergeRecords(defaults.baggage, {
89
+ originalValue: sanitizeForBaggage(error)
90
+ })
91
+ });
92
+ }
93
+
94
+ static fromServiceError(
95
+ error: unknown,
96
+ defaults: Partial<SlateErrorInput> = {}
97
+ ): SlateError {
98
+ return new SlateError(mapServiceErrorToSlateErrorInput(error as any, defaults));
99
+ }
100
+
101
+ static fromAxios(error: unknown, options: SlateAxiosErrorOptions = {}): SlateError {
102
+ if (SlateError.is(error)) return error;
103
+ if (getServiceErrorData(error))
104
+ return SlateError.fromServiceError(error, options.defaults);
105
+ if (!isAxiosErrorLike(error)) return SlateError.fromUnknown(error, options.defaults);
106
+
107
+ let inferred = inferSlateErrorFromAxios(error, options);
108
+
109
+ let mapped = options.mapAxiosError?.(error, inferred);
110
+ if (SlateError.is(mapped)) return mapped;
111
+
112
+ return new SlateError(mergeSlateErrorData(inferred, mapped ?? undefined));
113
+ }
10
114
  }
115
+
116
+ export let createSlateError = (input: SlateErrorInput) => new SlateError(input);
@@ -1,8 +1,13 @@
1
1
  import { SlateError } from './base';
2
2
 
3
3
  export class SlateDeclarationError extends SlateError {
4
- constructor(message: string) {
5
- super(`[Declaration Error]: ${message}`);
4
+ constructor(message: string, input: Partial<SlateError['data']> = {}) {
5
+ super({
6
+ code: 'declaration.invalid_definition',
7
+ kind: 'declaration',
8
+ message,
9
+ ...input
10
+ });
6
11
  this.name = 'SlateError.DeclarationError';
7
12
  }
8
13
 
@@ -0,0 +1,50 @@
1
+ export let DEFAULT_CODE = 'internal.unexpected';
2
+
3
+ export let DEFAULT_MESSAGES: Record<string, string> = {
4
+ 'declaration.invalid_definition': 'The slate definition is invalid.',
5
+ 'context.missing': 'No Slate context is available.',
6
+ 'input.invalid': 'The provided input is invalid.',
7
+ 'request.bad': 'The request is invalid.',
8
+ 'request.invalid_version': 'The requested version is invalid.',
9
+ 'request.precondition_failed': 'The request precondition failed.',
10
+ 'request.not_acceptable': 'The request is not acceptable.',
11
+ 'request.rate_limited': 'Too many requests were made in a short period of time.',
12
+ 'config.invalid': 'The provided configuration is invalid.',
13
+ 'auth.required': 'Authentication is required.',
14
+ 'auth.invalid': 'Authentication failed.',
15
+ 'auth.expired': 'Authentication has expired.',
16
+ 'permission.denied': 'Permission was denied.',
17
+ 'resource.not_found': 'The requested resource was not found.',
18
+ 'resource.conflict': 'The requested resource is in conflict.',
19
+ 'resource.gone': 'The requested resource is no longer available.',
20
+ 'payment.required': 'Payment is required to continue.',
21
+ 'operation.not_implemented': 'The requested operation is not implemented.',
22
+ 'upstream.invalid_request': 'The upstream service rejected the request.',
23
+ 'upstream.rate_limited': 'The upstream service rate limited the request.',
24
+ 'upstream.timeout': 'The upstream service timed out.',
25
+ 'upstream.network_error': 'A network error occurred while contacting the upstream service.',
26
+ 'upstream.unavailable': 'The upstream service is unavailable.',
27
+ 'upstream.invalid_response': 'The upstream service returned an invalid response.',
28
+ 'upstream.error': 'The upstream service returned an error.',
29
+ 'transport.invoke_failed': 'The provider transport failed.',
30
+ 'internal.timeout': 'The operation timed out.',
31
+ 'internal.unexpected': 'An unexpected internal error occurred.'
32
+ };
33
+
34
+ export let SERVICE_ERROR_CODE_MAP: Record<string, string> = {
35
+ invalid_data: 'input.invalid',
36
+ bad_request: 'request.bad',
37
+ not_found: 'resource.not_found',
38
+ unauthorized: 'auth.required',
39
+ forbidden: 'permission.denied',
40
+ invalid_version: 'request.invalid_version',
41
+ conflict: 'resource.conflict',
42
+ gone: 'resource.gone',
43
+ payment_required: 'payment.required',
44
+ precondition_failed: 'request.precondition_failed',
45
+ not_acceptable: 'request.not_acceptable',
46
+ not_implemented: 'operation.not_implemented',
47
+ too_many_requests: 'request.rate_limited',
48
+ timeout: 'internal.timeout',
49
+ internal_server_error: 'internal.unexpected'
50
+ };
@@ -1,2 +1,5 @@
1
+ export * from './axios';
1
2
  export * from './base';
2
3
  export * from './declaration';
4
+ export * from './service';
5
+ export * from './types';