Skip to content

Commit 19a075a

Browse files
authored
Toolshed common-memory cleanup (#317)
a bit of a refactor, adding new functions that don't have full http handlers in them, and moving http concerns up into hono
1 parent 403bc02 commit 19a075a

File tree

3 files changed

+83
-12
lines changed

3 files changed

+83
-12
lines changed

typescript/packages/common-memory/deno.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44
"test": "deno test --allow-read --allow-write --allow-net --allow-ffi --allow-env --no-check"
55
},
66
"test": {
7-
"include": [
8-
"test/*-test.ts"
9-
]
7+
"include": ["test/*-test.ts"]
108
},
119
"exports": {
1210
".": "./lib.ts"

typescript/packages/common-memory/lib.ts

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,12 @@ export interface MemoryService {
3232
close(): AsyncResult<{}, SystemError>;
3333
subscribe(socket: WebSocket): AsyncResult<{}, Error>;
3434
patch(request: { json(): Promise<any> }): Promise<Response>;
35+
patchJson(json: In<Transaction>): Promise<AsyncResult<any, Error>>;
3536
query(
3637
request: { json(): Promise<any> },
3738
selector: In<{ the?: string; of?: string }>,
3839
): Promise<Response>;
40+
queryJson(selector: object): Promise<AsyncResult<any, Error>>;
3941
}
4042

4143
interface MemoryServiceSession {
@@ -50,9 +52,15 @@ class Service implements MemoryService {
5052
patch(request: { json(): Promise<any> }): Promise<Response> {
5153
return patch(this, request);
5254
}
55+
patchJson(json: In<Transaction>): Promise<AsyncResult<any, Error>> {
56+
return patchJson(this.router, json);
57+
}
5358
query(request: { json(): Promise<any> }): Promise<Response> {
5459
return query(this, request);
5560
}
61+
queryJson(selector: object): Promise<AsyncResult<any, Error>> {
62+
return queryJson(this.router, selector as In<Partial<Selector>>);
63+
}
5664
transact(transaction: In<Transaction>) {
5765
return this.router.transact(transaction);
5866
}
@@ -154,6 +162,9 @@ export const query = async (session: MemoryServiceSession, request: { json(): Pr
154162

155163
const parseCommand = (source: string) => JSON.parse(source) as Command;
156164

165+
/**
166+
* Converts a raw JSON transaction object into a router transaction
167+
*/
157168
const asRouterTransaction = (json: In<Transaction>): In<Transaction> =>
158169
Object.fromEntries(Object.entries(json).map(([key, value]) => [key, asTransaction(value)]));
159170

@@ -166,14 +177,36 @@ const asStatement = <S extends Statement>(statement: S): S => {
166177
if (statement.cause && typeof statement.cause["/"] === "string") {
167178
statement.cause = Reference.fromJSON(statement.cause as unknown as { "/": string });
168179
}
169-
170180
if (statement.is && (statement.is as { "/"?: string })["/"]) {
171181
statement.is = Reference.fromJSON(statement.is as { "/": string });
172182
}
173-
174183
return statement;
175184
};
176185

186+
/**
187+
* New library-level patch function that accepts already-parsed JSON
188+
* and returns a plain result for consumers to build HTTP responses as needed.
189+
*/
190+
export const patchJson = async (
191+
session: Router.Router,
192+
json: In<Transaction>,
193+
): Promise<AsyncResult<any, Error>> => {
194+
try {
195+
const transaction = asRouterTransaction(json);
196+
const result = await session.transact(transaction);
197+
return result;
198+
} catch (cause) {
199+
const error = cause as Partial<Error>;
200+
return {
201+
error: {
202+
name: error?.name ?? "Error",
203+
message: error?.message ?? "Unable to process transaction",
204+
stack: error?.stack ?? "",
205+
},
206+
};
207+
}
208+
};
209+
177210
const pipeToSocket = async <T>(
178211
stream: ReadableStream<T>,
179212
socket: WebSocket,
@@ -188,3 +221,23 @@ const pipeToSocket = async <T>(
188221
return { error: error as Error };
189222
}
190223
};
224+
225+
export const queryJson = async (
226+
session: Router.Router,
227+
selector: object,
228+
): Promise<AsyncResult<any, Error>> => {
229+
try {
230+
const result = await session.query(selector as In<Partial<Selector>>);
231+
return result;
232+
} catch (cause) {
233+
console.error(cause);
234+
const error = cause as Partial<Error>;
235+
return {
236+
error: {
237+
name: error?.name ?? "Error",
238+
message: error?.message ?? "Unable to process query",
239+
stack: error?.stack ?? "",
240+
},
241+
};
242+
}
243+
};

typescript/packages/toolshed/routes/storage/memory/memory.handlers.ts

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,37 @@ if (error) {
1111
throw error;
1212
}
1313

14-
export const transact: AppRouteHandler<typeof Routes.transact> = (c) =>
15-
// @ts-expect-error - AppRouteHandler does not like Promise<Response> here as
16-
// it wants to know status code and not sure how to use my own response
17-
memory.patch(c.req);
14+
export const transact: AppRouteHandler<typeof Routes.transact> = async (c) => {
15+
try {
16+
const parsedBody = await c.req.json();
17+
const result = await memory.patchJson(parsedBody);
18+
19+
if ("error" in result) {
20+
const status = result.error?.name === "ConflictError" ? 409 : 500;
21+
return c.json({ error: result.error?.message }, status);
22+
}
23+
24+
return c.json({ ok: result.ok }, 200);
25+
} catch (err) {
26+
return c.json({ error: (err as Error).message }, 500);
27+
}
28+
};
1829

1930
export const subscribe: AppRouteHandler<typeof Routes.subscribe> = (c) => {
2031
const { socket, response } = Deno.upgradeWebSocket(c.req.raw);
2132
memory.subscribe(socket);
2233
return response;
2334
};
2435

25-
export const query: AppRouteHandler<typeof Routes.query> = (c) =>
26-
// @ts-expect-error - Same reason as transact handler
27-
memory.query(c.req);
36+
export const query: AppRouteHandler<typeof Routes.query> = async (c) => {
37+
try {
38+
const selector = await c.req.json();
39+
const result = await memory.queryJson(selector);
40+
if ("error" in result) {
41+
return c.json({ error: result.error?.message || "Unknown error" }, 500);
42+
}
43+
return c.json({ ok: result.ok }, 200);
44+
} catch (err) {
45+
return c.json({ error: (err as Error).message }, 500);
46+
}
47+
};

0 commit comments

Comments
 (0)