Skip to content

Commit 4cda075

Browse files
committed
Do errors better
1 parent 84f92e8 commit 4cda075

File tree

2 files changed

+134
-189
lines changed

2 files changed

+134
-189
lines changed

crates/bindings-typescript/src/server/errors.ts

Lines changed: 133 additions & 187 deletions
Original file line numberDiff line numberDiff line change
@@ -46,200 +46,146 @@ export class SenderError extends Error {
4646
}
4747
}
4848

49-
/**
50-
* A generic error class for unknown error codes.
51-
*/
52-
export class HostCallFailure extends SpacetimeHostError {
53-
static CODE = 1;
54-
static MESSAGE = 'ABI called by host returned an error';
55-
constructor() {
56-
super(HostCallFailure.CODE);
57-
}
58-
}
59-
60-
/**
61-
* Error indicating that an ABI call was made outside of a transaction.
62-
*/
63-
export class NotInTransaction extends SpacetimeHostError {
64-
static CODE = 2;
65-
static MESSAGE = 'ABI call can only be made while in a transaction';
66-
constructor() {
67-
super(NotInTransaction.CODE);
68-
}
69-
}
70-
71-
/**
72-
* Error indicating that BSATN decoding failed.
73-
* This typically means that the data could not be decoded to the expected type.
74-
*/
75-
export class BsatnDecodeError extends SpacetimeHostError {
76-
static CODE = 3;
77-
static MESSAGE = "Couldn't decode the BSATN to the expected type";
78-
constructor() {
79-
super(BsatnDecodeError.CODE);
80-
}
81-
}
82-
83-
/**
84-
* Error indicating that a specified table does not exist.
85-
*/
86-
export class NoSuchTable extends SpacetimeHostError {
87-
static CODE = 4;
88-
static MESSAGE = 'No such table';
89-
constructor() {
90-
super(NoSuchTable.CODE);
91-
}
92-
}
93-
94-
/**
95-
* Error indicating that a specified index does not exist.
96-
*/
97-
export class NoSuchIndex extends SpacetimeHostError {
98-
static CODE = 5;
99-
static MESSAGE = 'No such index';
100-
constructor() {
101-
super(NoSuchIndex.CODE);
102-
}
103-
}
104-
105-
/**
106-
* Error indicating that a specified row iterator is not valid.
107-
*/
108-
export class NoSuchIter extends SpacetimeHostError {
109-
static CODE = 6;
110-
static MESSAGE = 'The provided row iterator is not valid';
111-
constructor() {
112-
super(NoSuchIter.CODE);
113-
}
114-
}
115-
116-
/**
117-
* Error indicating that a specified console timer does not exist.
118-
*/
119-
export class NoSuchConsoleTimer extends SpacetimeHostError {
120-
static CODE = 7;
121-
static MESSAGE = 'The provided console timer does not exist';
122-
constructor() {
123-
super(NoSuchConsoleTimer.CODE);
124-
}
125-
}
126-
127-
/**
128-
* Error indicating that a specified bytes source or sink is not valid.
129-
*/
130-
export class NoSuchBytes extends SpacetimeHostError {
131-
static CODE = 8;
132-
static MESSAGE = 'The provided bytes source or sink is not valid';
133-
constructor() {
134-
super(NoSuchBytes.CODE);
135-
}
136-
}
137-
138-
/**
139-
* Error indicating that a provided sink has no more space left.
140-
*/
141-
export class NoSpace extends SpacetimeHostError {
142-
static CODE = 9;
143-
static MESSAGE = 'The provided sink has no more space left';
144-
constructor() {
145-
super(NoSpace.CODE);
146-
}
147-
}
148-
149-
/**
150-
* Error indicating that there is no more space in the database.
151-
*/
152-
export class BufferTooSmall extends SpacetimeHostError {
153-
static CODE = 11;
154-
static MESSAGE = 'The provided buffer is not large enough to store the data';
155-
constructor() {
156-
super(BufferTooSmall.CODE);
157-
}
158-
}
159-
160-
/**
161-
* Error indicating that a value with a given unique identifier already exists.
162-
*/
163-
export class UniqueAlreadyExists extends SpacetimeHostError {
164-
static CODE = 12;
165-
static MESSAGE = 'Value with given unique identifier already exists';
166-
constructor() {
167-
super(UniqueAlreadyExists.CODE);
168-
}
169-
}
170-
171-
/**
172-
* Error indicating that the specified delay in scheduling a row was too long.
173-
*/
174-
export class ScheduleAtDelayTooLong extends SpacetimeHostError {
175-
static CODE = 13;
176-
static MESSAGE = 'Specified delay in scheduling row was too long';
177-
constructor() {
178-
super(ScheduleAtDelayTooLong.CODE);
179-
}
180-
}
181-
182-
/**
183-
* Error indicating that an index was not unique when it was expected to be.
184-
*/
185-
export class IndexNotUnique extends SpacetimeHostError {
186-
static CODE = 14;
187-
static MESSAGE = 'The index was not unique';
188-
constructor() {
189-
super(IndexNotUnique.CODE);
190-
}
191-
}
192-
193-
/**
194-
* Error indicating that an index was not unique when it was expected to be.
195-
*/
196-
export class NoSuchRow extends SpacetimeHostError {
197-
static CODE = 15;
198-
static MESSAGE = 'The row was not found, e.g., in an update call';
199-
constructor() {
200-
super(NoSuchRow.CODE);
201-
}
202-
}
203-
204-
/**
205-
* Error indicating that an auto-increment sequence has overflowed.
206-
*/
207-
export class AutoIncOverflow extends SpacetimeHostError {
208-
static CODE = 16;
209-
static MESSAGE = 'The auto-increment sequence overflowed';
210-
constructor() {
211-
super(AutoIncOverflow.CODE);
212-
}
213-
}
214-
215-
/**
216-
* List of all SpacetimeError subclasses.
217-
*/
218-
const errorSubclasses = [
219-
HostCallFailure,
220-
NotInTransaction,
221-
BsatnDecodeError,
222-
NoSuchTable,
223-
NoSuchIndex,
224-
NoSuchIter,
225-
NoSuchConsoleTimer,
226-
NoSuchBytes,
227-
NoSpace,
228-
BufferTooSmall,
229-
UniqueAlreadyExists,
230-
ScheduleAtDelayTooLong,
231-
IndexNotUnique,
232-
NoSuchRow,
233-
];
49+
const errorData = {
50+
/**
51+
* A generic error class for unknown error codes.
52+
*/
53+
HostCallFailure: [1, 'ABI called by host returned an error'],
54+
55+
/**
56+
* Error indicating that an ABI call was made outside of a transaction.
57+
*/
58+
NotInTransaction: [2, 'ABI call can only be made while in a transaction'],
59+
60+
/**
61+
* Error indicating that BSATN decoding failed.
62+
* This typically means that the data could not be decoded to the expected type.
63+
*/
64+
BsatnDecodeError: [3, "Couldn't decode the BSATN to the expected type"],
65+
66+
/**
67+
* Error indicating that a specified table does not exist.
68+
*/
69+
NoSuchTable: [4, 'No such table'],
70+
71+
/**
72+
* Error indicating that a specified index does not exist.
73+
*/
74+
NoSuchIndex: [5, 'No such index'],
75+
76+
/**
77+
* Error indicating that a specified row iterator is not valid.
78+
*/
79+
NoSuchIter: [6, 'The provided row iterator is not valid'],
80+
81+
/**
82+
* Error indicating that a specified console timer does not exist.
83+
*/
84+
NoSuchConsoleTimer: [7, 'The provided console timer does not exist'],
85+
86+
/**
87+
* Error indicating that a specified bytes source or sink is not valid.
88+
*/
89+
NoSuchBytes: [8, 'The provided bytes source or sink is not valid'],
90+
91+
/**
92+
* Error indicating that a provided sink has no more space left.
93+
*/
94+
NoSpace: [9, 'The provided sink has no more space left'],
95+
96+
/**
97+
* Error indicating that there is no more space in the database.
98+
*/
99+
BufferTooSmall: [
100+
11,
101+
'The provided buffer is not large enough to store the data',
102+
],
103+
104+
/**
105+
* Error indicating that a value with a given unique identifier already exists.
106+
*/
107+
UniqueAlreadyExists: [
108+
12,
109+
'Value with given unique identifier already exists',
110+
],
111+
112+
/**
113+
* Error indicating that the specified delay in scheduling a row was too long.
114+
*/
115+
ScheduleAtDelayTooLong: [
116+
13,
117+
'Specified delay in scheduling row was too long',
118+
],
119+
120+
/**
121+
* Error indicating that an index was not unique when it was expected to be.
122+
*/
123+
IndexNotUnique: [14, 'The index was not unique'],
124+
125+
/**
126+
* Error indicating that an index was not unique when it was expected to be.
127+
*/
128+
NoSuchRow: [15, 'The row was not found, e.g., in an update call'],
129+
130+
/**
131+
* Error indicating that an auto-increment sequence has overflowed.
132+
*/
133+
AutoIncOverflow: [16, 'The auto-increment sequence overflowed'],
134+
135+
WouldBlockTransaction: [
136+
17,
137+
'Attempted async or blocking op while holding open a transaction',
138+
],
139+
140+
TransactionNotAnonymous: [
141+
18,
142+
'Not in an anonymous transaction. Called by a reducer?',
143+
],
144+
145+
TransactionIsReadOnly: [
146+
19,
147+
'ABI call can only be made while within a mutable transaction',
148+
],
149+
150+
TransactionIsMut: [
151+
20,
152+
'ABI call can only be made while within a read-only transaction',
153+
],
154+
} as const;
155+
156+
function mapEntries<const T extends Record<string, any>, U>(
157+
x: T,
158+
f: (key: keyof T, value: T[keyof T]) => U
159+
): { [k in keyof T]: U } {
160+
return Object.fromEntries(
161+
Object.entries(x).map(([k, v]) => [k, f(k, v)])
162+
) as any;
163+
}
164+
165+
export const errors = Object.freeze(
166+
mapEntries(errorData, (name, [code, message]) =>
167+
Object.defineProperty(
168+
class extends SpacetimeHostError {
169+
static CODE = code;
170+
static MESSAGE = message;
171+
constructor() {
172+
super(code);
173+
}
174+
},
175+
'name',
176+
{ value: name, writable: false }
177+
)
178+
)
179+
);
234180

235181
/**
236182
* Set of prototypes of all SpacetimeError subclasses for quick lookup.
237183
*/
238-
const errorProtoypes = new Set(errorSubclasses.map(cls => cls.prototype));
184+
const errorProtoypes = new Set(Object.values(errors).map(cls => cls.prototype));
239185

240186
/**
241187
* Map from error codes to their corresponding SpacetimeError subclass.
242188
*/
243189
const errnoToClass = new Map(
244-
errorSubclasses.map(cls => [cls.CODE as number, cls])
190+
Object.values(errors).map(cls => [cls.CODE as number, cls])
245191
);

crates/bindings-typescript/src/server/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ export * from '../lib/type_builders';
22
export { schema, type InferSchema } from '../lib/schema';
33
export { table } from '../lib/table';
44
export { reducers } from '../lib/reducers';
5-
export * as errors from './errors';
6-
export { SenderError } from './errors';
5+
export { SenderError, SpacetimeHostError, errors } from './errors';
76
export { type Reducer, type ReducerCtx } from '../lib/reducers';
87
export { type DbView } from './db_view';
98

0 commit comments

Comments
 (0)