@edge-base/shared 0.1.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/src/errors.ts ADDED
@@ -0,0 +1,228 @@
1
+ // ─── Error Response Format ───
2
+
3
+ export interface FieldError {
4
+ code: string;
5
+ message: string;
6
+ }
7
+
8
+ export interface ErrorResponse {
9
+ code: number;
10
+ message: string;
11
+ /** Semantic error slug for programmatic error handling (e.g. 'token-expired', 'email-already-exists'). */
12
+ slug?: string;
13
+ data?: Record<string, FieldError>;
14
+ }
15
+
16
+ // ─── Well-known Error Slugs ───
17
+
18
+ /**
19
+ * Well-known semantic error slugs for EdgeBase core errors.
20
+ * SDKs can match on `slug` instead of parsing error messages.
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * try { await client.auth.signIn({ email, password }); }
25
+ * catch (err) {
26
+ * if (err.slug === 'invalid-credentials') { ... }
27
+ * if (err.slug === 'account-disabled') { ... }
28
+ * if (err.slug === 'token-expired') { ... }
29
+ * }
30
+ * ```
31
+ */
32
+ export const ErrorSlug = {
33
+ // ── 400 Validation ──
34
+ 'validation-failed': 400,
35
+ 'invalid-input': 400,
36
+ 'invalid-json': 400,
37
+ 'invalid-email': 400,
38
+ 'password-too-short': 400,
39
+ 'password-too-long': 400,
40
+ 'password-policy': 400,
41
+ 'display-name-too-long': 400,
42
+ 'invalid-locale': 400,
43
+ 'invalid-token': 400,
44
+ 'token-expired': 400,
45
+ 'challenge-expired': 400,
46
+ 'invalid-otp': 400,
47
+ 'no-fields-to-update': 400,
48
+ 'mfa-already-enrolled': 400,
49
+ 'invalid-phone': 400,
50
+ 'foreign-key-failed': 400,
51
+ 'constraint-failed': 400,
52
+
53
+ // ── 401 Unauthorized ──
54
+ 'unauthenticated': 401,
55
+ 'invalid-credentials': 401,
56
+ 'invalid-refresh-token': 401,
57
+ 'refresh-token-expired': 401,
58
+ 'refresh-token-reused': 401,
59
+ 'invalid-password': 401,
60
+ 'invalid-totp': 401,
61
+ 'invalid-recovery-code': 401,
62
+
63
+ // ── 403 Forbidden ──
64
+ 'forbidden': 403,
65
+ 'access-denied': 403,
66
+ 'account-disabled': 403,
67
+ 'action-not-allowed': 403,
68
+ 'hook-rejected': 403,
69
+ 'oauth-only': 403,
70
+ 'anonymous-not-allowed': 403,
71
+
72
+ // ── 404 Not Found ──
73
+ 'not-found': 404,
74
+ 'user-not-found': 404,
75
+ 'feature-not-enabled': 404,
76
+
77
+ // ── 405 Method Not Allowed ──
78
+ 'method-not-allowed': 405,
79
+
80
+ // ── 409 Conflict ──
81
+ 'already-exists': 409,
82
+ 'email-already-exists': 409,
83
+ 'phone-already-exists': 409,
84
+ 'record-already-exists': 409,
85
+
86
+ // ── 429 Rate Limited ──
87
+ 'rate-limited': 429,
88
+
89
+ // ── 500 Internal ──
90
+ 'internal-error': 500,
91
+ } as const;
92
+
93
+ export type ErrorSlugType = keyof typeof ErrorSlug;
94
+
95
+ /**
96
+ * EdgeBase error class extending standard Error.
97
+ * Used by both server and SDK for consistent error handling.
98
+ *
99
+ * @example
100
+ * ```ts
101
+ * // With slug (preferred — enables programmatic error handling):
102
+ * throw new EdgeBaseError(400, 'Invalid email format.', undefined, 'invalid-email');
103
+ *
104
+ * // Legacy (still supported):
105
+ * throw new EdgeBaseError(400, 'Invalid email format.');
106
+ * ```
107
+ */
108
+ export class EdgeBaseError extends Error {
109
+ public readonly code: number;
110
+ public readonly data?: Record<string, FieldError>;
111
+ /** Semantic error slug for programmatic matching. */
112
+ public readonly slug?: string;
113
+
114
+ constructor(code: number, message: string, data?: Record<string, FieldError>, slug?: string) {
115
+ super(message);
116
+ this.name = 'EdgeBaseError';
117
+ this.code = code;
118
+ this.data = data;
119
+ this.slug = slug;
120
+ }
121
+
122
+ /** Alias for `code` — HTTP status code of the error. */
123
+ get status(): number {
124
+ return this.code;
125
+ }
126
+
127
+ toJSON(): ErrorResponse {
128
+ const response: ErrorResponse = {
129
+ code: this.code,
130
+ message: this.message,
131
+ };
132
+ if (this.slug) {
133
+ response.slug = this.slug;
134
+ }
135
+ if (this.data) {
136
+ response.data = this.data;
137
+ }
138
+ return response;
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Create a standard error response object.
144
+ */
145
+ export function createErrorResponse(
146
+ code: number,
147
+ message: string,
148
+ data?: Record<string, FieldError>,
149
+ slug?: string,
150
+ ): ErrorResponse {
151
+ const response: ErrorResponse = { code, message };
152
+ if (slug) {
153
+ response.slug = slug;
154
+ }
155
+ if (data) {
156
+ response.data = data;
157
+ }
158
+ return response;
159
+ }
160
+
161
+ // ─── Function Error ───
162
+
163
+ /**
164
+ * Well-known error codes for App Functions.
165
+ * Maps semantic codes to default HTTP status codes.
166
+ */
167
+ export const FunctionErrorCode = {
168
+ 'not-found': 404,
169
+ 'permission-denied': 403,
170
+ 'unauthenticated': 401,
171
+ 'invalid-argument': 400,
172
+ 'already-exists': 409,
173
+ 'resource-exhausted': 429,
174
+ 'failed-precondition': 412,
175
+ 'internal': 500,
176
+ 'unavailable': 503,
177
+ } as const;
178
+
179
+ export type FunctionErrorCodeType = keyof typeof FunctionErrorCode;
180
+
181
+ /**
182
+ * Structured error thrown from App Functions.
183
+ * Caught by the functions route handler and returned as a JSON response
184
+ * with the appropriate HTTP status code.
185
+ *
186
+ * @example
187
+ * throw new FunctionError('not-found', 'User not found');
188
+ * throw new FunctionError('permission-denied', 'Admin only');
189
+ * throw new FunctionError('invalid-argument', 'Email is required', { field: 'email' });
190
+ */
191
+ export class FunctionError extends Error {
192
+ public readonly code: FunctionErrorCodeType | string;
193
+ public readonly httpStatus: number;
194
+ public readonly details?: Record<string, unknown>;
195
+
196
+ constructor(
197
+ code: FunctionErrorCodeType | string,
198
+ message: string,
199
+ details?: Record<string, unknown>,
200
+ ) {
201
+ super(message);
202
+ this.name = 'FunctionError';
203
+ this.code = code;
204
+ this.httpStatus =
205
+ (FunctionErrorCode as Record<string, number>)[code] ?? 400;
206
+ this.details = details;
207
+ }
208
+
209
+ toJSON(): {
210
+ code: string;
211
+ message: string;
212
+ status: number;
213
+ details?: Record<string, unknown>;
214
+ } {
215
+ const result: {
216
+ code: string;
217
+ message: string;
218
+ status: number;
219
+ details?: Record<string, unknown>;
220
+ } = {
221
+ code: this.code,
222
+ message: this.message,
223
+ status: this.httpStatus,
224
+ };
225
+ if (this.details) result.details = this.details;
226
+ return result;
227
+ }
228
+ }
package/src/index.ts ADDED
@@ -0,0 +1,164 @@
1
+ export {
2
+ CURRENT_PLUGIN_API_VERSION,
3
+ defineConfig,
4
+ defineFunction,
5
+ getDbAccess,
6
+ getTableAccess,
7
+ getTableHooks,
8
+ getStorageBucketAccess,
9
+ getStorageHooks,
10
+ getPushAccess,
11
+ getPushHandlers,
12
+ getAuthAccess,
13
+ getAuthHandlers,
14
+ getAuthEnrichHandler,
15
+ getMailHooks,
16
+ getRoomAccess,
17
+ getRoomStateConfig,
18
+ getRoomHooks,
19
+ getRoomHandlers,
20
+ getRoomLifecycleHandlers,
21
+ getRoomActionHandlers,
22
+ getRoomTimerHandlers,
23
+ materializeConfig,
24
+ } from './config.js';
25
+ export type {
26
+ // ─── Core Config ───
27
+ EdgeBaseConfig,
28
+ // ─── Database-first (§1,) ───
29
+ DbBlock,
30
+ DbAdminConfig,
31
+ DbProvider,
32
+ DbAccess,
33
+ DbLevelRules,
34
+ DbRuleCtx,
35
+ AdminInstanceDiscovery,
36
+ AdminInstanceDiscoveryContext,
37
+ AdminInstanceDiscoveryOption,
38
+ ManualAdminInstanceDiscovery,
39
+ TableAdminInstanceDiscovery,
40
+ FunctionAdminInstanceDiscovery,
41
+ TableConfig,
42
+ TableAccess,
43
+ TableRules,
44
+ TableHandlers,
45
+ TableHooks,
46
+ // ─── Auth Context ───
47
+ AuthContext,
48
+ // ─── Hook Context ───
49
+ HookCtx,
50
+ // ─── Schema ───
51
+ FieldType,
52
+ SchemaField,
53
+ FkReference,
54
+ IndexConfig,
55
+ MigrationConfig,
56
+ // ─── Auth Config ───
57
+ AuthConfig,
58
+ AuthAccess,
59
+ AuthAccessCtx,
60
+ AuthAccessRule,
61
+ AuthHandlers,
62
+ AuthHandlerHooks,
63
+ EmailOtpConfig,
64
+ MagicLinkConfig,
65
+ MfaConfig,
66
+ OAuthProviderCredentialsConfig,
67
+ OidcProviderCredentialsConfig,
68
+ OAuthProvidersConfig,
69
+ PasskeysConfig,
70
+ PasswordPolicyConfig,
71
+ SmsConfig,
72
+ // ─── Email Config ───
73
+ EmailConfig,
74
+ EmailTemplateOverrides,
75
+ EmailSubjectOverrides,
76
+ MailHooks,
77
+ MailHookCtx,
78
+ MailType,
79
+ SmsHooks,
80
+ SmsHookCtx,
81
+ SmsType,
82
+ // ─── Storage (§5) ───
83
+ StorageConfig,
84
+ StorageBucketConfig,
85
+ StorageBucketAccess,
86
+ StorageBucketRules,
87
+ StorageHandlers,
88
+ StorageHooks,
89
+ StorageHookCtx,
90
+ WriteFileMeta,
91
+ R2FileMeta,
92
+ // ─── CORS / Rate Limiting ───
93
+ CorsConfig,
94
+ RateLimitingConfig,
95
+ // ─── Functions ───
96
+ FunctionsConfig,
97
+ CloudflareConfig,
98
+ FunctionDefinition,
99
+ FunctionTrigger,
100
+ FunctionTriggerType,
101
+ DbTrigger,
102
+ AuthTrigger,
103
+ StorageTrigger,
104
+ ScheduleTrigger,
105
+ HttpTrigger,
106
+ // ─── Plugin ───
107
+ PluginManifest,
108
+ PluginInstance,
109
+ // ─── Service Key ───
110
+ ServiceKeyEntry,
111
+ ServiceKeysConfig,
112
+ ServiceKeyConstraints,
113
+ ScopeString,
114
+ // ─── Captcha ───
115
+ CaptchaConfig,
116
+ // ─── Push ───
117
+ PushConfig,
118
+ PushAccess,
119
+ PushFcmConfig,
120
+ PushHandlers,
121
+ PushHookCtx,
122
+ PushRules,
123
+ PushSendInput,
124
+ PushSendOutput,
125
+ // ─── Database Live ───
126
+ DatabaseLiveConfig,
127
+ // ─── KV / D1 / Vectorize ───
128
+ KvNamespaceConfig,
129
+ KvNamespaceRules,
130
+ D1DatabaseConfig,
131
+ VectorizeConfig,
132
+ // ─── Room v2 ───
133
+ RoomNamespaceConfig,
134
+ RoomAccess,
135
+ RoomMediaAccess,
136
+ RoomRuntimeConfig,
137
+ RoomRuntimeTarget,
138
+ RoomStateConfig,
139
+ RoomHooks,
140
+ RoomMemberHooks,
141
+ RoomStateHooks,
142
+ RoomSignalHooks,
143
+ RoomMediaHooks,
144
+ RoomSessionHooks,
145
+ RoomHandlers,
146
+ RoomLifecycleHandlers,
147
+ RoomCreateHandler,
148
+ RoomJoinHandler,
149
+ RoomLeaveHandler,
150
+ RoomDestroyHandler,
151
+ RoomActionHandlers,
152
+ RoomTimerHandlers,
153
+ RoomSender,
154
+ RoomMemberInfo,
155
+ RoomServerAPI,
156
+ RoomHandlerContext,
157
+ RoomTableProxy,
158
+ RoomDbProxy,
159
+ } from './config.js';
160
+
161
+ export { EdgeBaseError, createErrorResponse, FunctionError, FunctionErrorCode } from './errors.js';
162
+ export type { ErrorResponse, FieldError, FunctionErrorCodeType } from './errors.js';
163
+
164
+ export type { FilterOperator, SortDirection } from './types.js';
package/src/types.ts ADDED
@@ -0,0 +1,16 @@
1
+ // ─── Common Utility Types ───
2
+
3
+ export type FilterOperator =
4
+ | '=='
5
+ | '!='
6
+ | '>'
7
+ | '<'
8
+ | '>='
9
+ | '<='
10
+ | 'contains'
11
+ | 'contains-any'
12
+ | 'in'
13
+ | 'not in'
14
+ | 'not-in';
15
+
16
+ export type SortDirection = 'asc' | 'desc';