@loopbacktools/server 0.0.0-stage → 0.4.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/LICENSE +21 -0
- package/README.md +26 -2
- package/dist/package.json +57 -0
- package/dist/src/domain/ask.d.ts +78 -0
- package/dist/src/domain/ask.js +161 -0
- package/dist/src/domain/errors.d.ts +70 -0
- package/dist/src/domain/errors.js +57 -0
- package/dist/src/generated/app.gen.d.ts +2311 -0
- package/dist/src/generated/app.gen.js +400 -0
- package/dist/src/generated/runtime.gen.d.ts +357 -0
- package/dist/src/generated/runtime.gen.js +298 -0
- package/dist/src/generated/schemas.gen.d.ts +6416 -0
- package/dist/src/generated/schemas.gen.js +306 -0
- package/dist/src/generated/wire-contract.gen.d.ts +77 -0
- package/dist/src/generated/wire-contract.gen.js +3 -0
- package/dist/src/index.d.ts +11 -0
- package/dist/src/index.js +8 -0
- package/dist/src/loopback.d.ts +27 -0
- package/dist/src/loopback.js +16 -0
- package/dist/src/space/arguments.d.ts +8 -0
- package/dist/src/space/arguments.js +52 -0
- package/dist/src/space/migrations.d.ts +10 -0
- package/dist/src/space/migrations.js +106 -0
- package/dist/src/space/object.d.ts +30 -0
- package/dist/src/space/object.js +169 -0
- package/dist/src/space/operations.d.ts +149 -0
- package/dist/src/space/operations.js +568 -0
- package/dist/src/space/read.d.ts +8 -0
- package/dist/src/space/read.js +33 -0
- package/dist/src/space/rpc.d.ts +61 -0
- package/dist/src/space/rpc.js +96 -0
- package/dist/src/space/services.d.ts +41 -0
- package/dist/src/space/services.js +58 -0
- package/dist/src/space/store.d.ts +87 -0
- package/dist/src/space/store.js +276 -0
- package/dist/src/version.d.ts +2 -0
- package/dist/src/version.js +3 -0
- package/dist/src/worker/env.d.ts +19 -0
- package/dist/src/worker/env.js +3 -0
- package/dist/src/worker/files.d.ts +21 -0
- package/dist/src/worker/files.js +42 -0
- package/dist/src/worker/gate.d.ts +55 -0
- package/dist/src/worker/gate.js +83 -0
- package/dist/src/worker/http.d.ts +2092 -0
- package/dist/src/worker/http.js +291 -0
- package/dist/src/worker/jwt.d.ts +49 -0
- package/dist/src/worker/jwt.js +142 -0
- package/dist/src/worker/mcp.d.ts +15 -0
- package/dist/src/worker/mcp.js +401 -0
- package/dist/src/worker/run.d.ts +45 -0
- package/dist/src/worker/run.js +71 -0
- package/dist/src/worker/spaces.d.ts +24 -0
- package/dist/src/worker/spaces.js +64 -0
- package/package.json +51 -3
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
// GENERATED by typespec-hono from the TypeSpec service definition. DO NOT EDIT.
|
|
2
|
+
// Regenerate with: pnpm generate
|
|
3
|
+
import { zValidator } from "@hono/zod-validator";
|
|
4
|
+
import { Hono } from "hono";
|
|
5
|
+
import { parse as parseJson } from "secure-json-parse";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { UndeclaredStatusError, headersOf, servedBody, servedBytes } from "./runtime.gen.js";
|
|
8
|
+
import { Asks_listQuery, Asks_readPath, Asks_replyPath, Files_readPath, Uploads_storeHeader, Uploads_storePath, askPageSchema, askSchema, eventTicketSchema, problemSchema, replySchema, snapshotSchema, uploadReceiptSchema, whoamiSchema, } from "./schemas.gen.js";
|
|
9
|
+
/**
|
|
10
|
+
* Parse, and treat input nested deeper than this runtime's stack as a refusal rather than a crash.
|
|
11
|
+
*
|
|
12
|
+
* **`safeParse` not throwing is the contract everything here rests on, and a deep enough value
|
|
13
|
+
* breaks it.** Zod recurses once per level, so a recursive model meets a `RangeError` that is not a
|
|
14
|
+
* validation failure and escapes to `app.onError` indistinguishable from a bug in the application's
|
|
15
|
+
* own code. Measured on `workerd`: a 40.5 KB body, about 1,925 levels, which Ajv on the published
|
|
16
|
+
* document calls VALID.
|
|
17
|
+
*
|
|
18
|
+
* It cannot be served, so it is refused - through `deps.invalid` like every other bad request, with
|
|
19
|
+
* an issue that says which limit was met rather than a generic failure. Anything that is not a
|
|
20
|
+
* `RangeError` is rethrown: a bug here must still look like one.
|
|
21
|
+
*/
|
|
22
|
+
function parsed(schema, value) {
|
|
23
|
+
try {
|
|
24
|
+
return schema.safeParse(value);
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
if (!(error instanceof RangeError))
|
|
28
|
+
throw error;
|
|
29
|
+
return {
|
|
30
|
+
success: false,
|
|
31
|
+
error: new z.ZodError([
|
|
32
|
+
{
|
|
33
|
+
code: "custom",
|
|
34
|
+
path: [],
|
|
35
|
+
message: "input is nested too deeply for this runtime to validate",
|
|
36
|
+
},
|
|
37
|
+
]),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** Parse synchronously: nothing emitted here is async, and the async path costs 3.4x. */
|
|
42
|
+
const SYNC = { validationFunction: (schema, value) => parsed(schema, value) };
|
|
43
|
+
/**
|
|
44
|
+
* A body that is not what its content type claims.
|
|
45
|
+
*
|
|
46
|
+
* **BOTH readers can fail.** Hono's own validator catches in both branches and throws
|
|
47
|
+
* `HTTPException` - which is what escapes the app's envelope. Catching here is what lets the failure
|
|
48
|
+
* be reported like any other. Measured: an unreadable multipart body answered 500 while the JSON case
|
|
49
|
+
* answered 400, from the same missing `try`.
|
|
50
|
+
*/
|
|
51
|
+
const UNREADABLE = Symbol("a body that is not what its content type claims");
|
|
52
|
+
/**
|
|
53
|
+
* Reads a body in the form its target names.
|
|
54
|
+
*
|
|
55
|
+
* **JSON naming the object prototype is unreadable.** Zod strips a `__proto__` key unread
|
|
56
|
+
* (colinhacks/zod#6386), so `Record<boolean>` accepted `{"__proto__": 1}`, which the document
|
|
57
|
+
* refuses. Fastify and hapi refuse such a body by default, at the parser, through
|
|
58
|
+
* `secure-json-parse` - a `__proto__` key, or `constructor.prototype`, anywhere in it - and so
|
|
59
|
+
* does this reader. A body the document would accept is refused with it, as theirs is.
|
|
60
|
+
*/
|
|
61
|
+
async function readBody(c, target, parts = []) {
|
|
62
|
+
try {
|
|
63
|
+
if (target === "form")
|
|
64
|
+
return await readForm(c, parts);
|
|
65
|
+
// A text body IS the text: it is validated as the string the caller sent, not parsed first.
|
|
66
|
+
if (target === "text")
|
|
67
|
+
return await c.req.text();
|
|
68
|
+
return parseJson(await c.req.text());
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return UNREADABLE;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* **A form, each part the document reads from text handed over as its text.** A client may send such
|
|
76
|
+
* a part with a filename - `curl -F 'r=@data.json;type=application/json'` - and `parseBody` then
|
|
77
|
+
* hands it over as a file, which the part's schema, reading text, refused: the part's media type says
|
|
78
|
+
* what it is, not the filename. A file part and raw bytes are left as they arrive.
|
|
79
|
+
*
|
|
80
|
+
* **A JSON part naming the object prototype is unreadable**, as a JSON body is - see `readBody`. Its
|
|
81
|
+
* JSON is parsed by the part's schema, which `secure-json-parse` never saw, so `{"__proto__": 1}`
|
|
82
|
+
* reached a `Record<boolean>` part and was accepted, the key dropped. A part that may be text or
|
|
83
|
+
* JSON is read as either by its schema, and its text stays text.
|
|
84
|
+
*/
|
|
85
|
+
async function readForm(c, parts) {
|
|
86
|
+
const form = await c.req.parseBody({ all: true });
|
|
87
|
+
for (const [name, json] of parts) {
|
|
88
|
+
const value = form[name];
|
|
89
|
+
if (value === undefined)
|
|
90
|
+
continue;
|
|
91
|
+
const texts = await Promise.all((Array.isArray(value) ? value : [value]).map((each) => typeof each === "string" ? each : each.text()));
|
|
92
|
+
if (json && texts.some(namesPrototype))
|
|
93
|
+
return UNREADABLE;
|
|
94
|
+
form[name] = Array.isArray(value) ? texts : (texts[0] ?? "");
|
|
95
|
+
}
|
|
96
|
+
return form;
|
|
97
|
+
}
|
|
98
|
+
/** JSON that `secure-json-parse` refuses where `JSON.parse` does not: the prototype named. */
|
|
99
|
+
function namesPrototype(text) {
|
|
100
|
+
try {
|
|
101
|
+
JSON.parse(text);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// No JSON at all, which the part's schema refuses as such.
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
parseJson(text);
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* The failure an unreadable body produces, in the shape every other rejection has.
|
|
117
|
+
*
|
|
118
|
+
* Parsing `undefined` against the body's own schema is what makes a real Zod failure, so
|
|
119
|
+
* `deps.invalid` receives what it receives for a failed parse rather than a special case it has to
|
|
120
|
+
* know about. A schema that somehow accepts `undefined` still fails: a body that could not be read
|
|
121
|
+
* is not a body that validated.
|
|
122
|
+
*/
|
|
123
|
+
function unreadableResult(schema) {
|
|
124
|
+
const result = parsed(schema, undefined);
|
|
125
|
+
return result.success ? { success: false } : result;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Which reader parses the media type the request actually carries.
|
|
129
|
+
*
|
|
130
|
+
* A route may declare several request media types needing different parsers, and which one applies is
|
|
131
|
+
* decided by the caller's `Content-Type` when the request arrives - not when this file was
|
|
132
|
+
* generated. Parameters (`; charset=utf-8`, `; boundary=...`) are not part of the match, which
|
|
133
|
+
* matters because a multipart request always carries a boundary.
|
|
134
|
+
*
|
|
135
|
+
* **A `Content-Type` matching nothing declared is REFUSED, and used to be parsed anyway.** It fell
|
|
136
|
+
* through to the first branch, and the comment here claimed the body would then "simply fail to
|
|
137
|
+
* parse" - which is not what happened: `c.req.json()` reads the bytes whatever the header says, so a
|
|
138
|
+
* route publishing `application/json` alone answered 200 to the same body sent as `text/plain`, as
|
|
139
|
+
* `multipart/form-data`, and with no `Content-Type` at all. The document says which media types an
|
|
140
|
+
* operation accepts, and a server that accepts others is not serving that document.
|
|
141
|
+
*
|
|
142
|
+
* `undefined` means "nothing declared covers this", and the caller refuses it through
|
|
143
|
+
* `deps.invalid` like any other bad request. No status is invented that the document does not
|
|
144
|
+
* describe, which is also what `@typespec/http-server-js` does with the identical case.
|
|
145
|
+
*/
|
|
146
|
+
function bodyBranch(c, branches) {
|
|
147
|
+
const declared = (c.req.header("content-type") ?? "").split(";")[0]?.trim().toLowerCase() ?? "";
|
|
148
|
+
if (declared === "")
|
|
149
|
+
return undefined;
|
|
150
|
+
/**
|
|
151
|
+
* A declared media RANGE matches the types inside it, which a string comparison cannot do.
|
|
152
|
+
* `@typespec/http` reports a bare `string`-typed `contentType` as the wildcard range, and an author
|
|
153
|
+
* may write a subtype wildcard such as text-slash-star outright. Comparing the range TEXT refuses
|
|
154
|
+
* every real request, because no caller sends the range itself as its `Content-Type`. This is the
|
|
155
|
+
* request-side counterpart of `mediaTypeWithin` in the runtime module, inlined because the branch
|
|
156
|
+
* list is emitted here.
|
|
157
|
+
*/
|
|
158
|
+
const covers = (range) => {
|
|
159
|
+
if (range === "*/*")
|
|
160
|
+
return true;
|
|
161
|
+
if (!range.endsWith("/*"))
|
|
162
|
+
return false;
|
|
163
|
+
const slash = declared.indexOf("/");
|
|
164
|
+
return slash > 0 && declared.slice(0, slash) === range.slice(0, -2);
|
|
165
|
+
};
|
|
166
|
+
return branches.find(([mediaType]) => {
|
|
167
|
+
const lowered = mediaType.toLowerCase();
|
|
168
|
+
return lowered === declared || covers(lowered);
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* The failure an undeclared media type produces, in the shape every other rejection has.
|
|
173
|
+
*
|
|
174
|
+
* Reported as an issue on the body rather than a bare `{ success: false }`, so an application's
|
|
175
|
+
* `invalid` hook can tell a caller WHICH thing was wrong - the same reason `unreadableResult` parses
|
|
176
|
+
* `undefined` rather than inventing a result.
|
|
177
|
+
*/
|
|
178
|
+
function unsupportedMediaTypeResult(branches) {
|
|
179
|
+
return {
|
|
180
|
+
success: false,
|
|
181
|
+
error: new z.ZodError([
|
|
182
|
+
{
|
|
183
|
+
code: "custom",
|
|
184
|
+
path: ["content-type"],
|
|
185
|
+
message: `this operation accepts ${branches.map(([type]) => type).join(", ")}`,
|
|
186
|
+
},
|
|
187
|
+
]),
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Validate a REQUIRED request body, whatever media type it arrives as.
|
|
192
|
+
*
|
|
193
|
+
* The validated value is published under `"json"` whichever reader produced it: `ValidationTargets`
|
|
194
|
+
* is a closed union in Hono, so there is no name to coin for "the body", and using one slot is what
|
|
195
|
+
* makes every route the same shape downstream.
|
|
196
|
+
*/
|
|
197
|
+
function validateBody(schema, invalid, branches) {
|
|
198
|
+
return async (c, next) => {
|
|
199
|
+
/**
|
|
200
|
+
* Annotated rather than inlined, and that is what removes a CAST from this file. `Context` is
|
|
201
|
+
* invariant in its environment and in its `Input`, so passing the outer `c` to a hook typed
|
|
202
|
+
* against the route's own input needs either an annotation here or an `as never` there.
|
|
203
|
+
*/
|
|
204
|
+
const parse = async (ctx, proceed) => {
|
|
205
|
+
const branch = bodyBranch(ctx, branches);
|
|
206
|
+
const reading = branch?.[2] ?? schema;
|
|
207
|
+
const raw = branch === undefined ? UNREADABLE : await readBody(ctx, branch[1], branch[3]);
|
|
208
|
+
const result = branch === undefined
|
|
209
|
+
? unsupportedMediaTypeResult(branches)
|
|
210
|
+
: raw === UNREADABLE
|
|
211
|
+
? unreadableResult(reading)
|
|
212
|
+
: parsed(reading, raw);
|
|
213
|
+
const response = invalid(result, ctx);
|
|
214
|
+
if (response !== undefined)
|
|
215
|
+
return response;
|
|
216
|
+
if (!result.success)
|
|
217
|
+
return ctx.json(result, 400);
|
|
218
|
+
ctx.req.addValidatedData("json", ("data" in result ? result.data : undefined) ?? {});
|
|
219
|
+
await proceed();
|
|
220
|
+
return undefined;
|
|
221
|
+
};
|
|
222
|
+
return parse(c, next);
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
/** Mount every operation the service declares. */
|
|
226
|
+
export function registerRoutes(app, handlersFor, deps) {
|
|
227
|
+
const contexts = new WeakMap();
|
|
228
|
+
const contextFor = (authentication) => async (c, next) => {
|
|
229
|
+
const ctx = deps.context(c, authentication);
|
|
230
|
+
if (ctx === null)
|
|
231
|
+
return deps.noContext(c);
|
|
232
|
+
contexts.set(c, { value: ctx });
|
|
233
|
+
await next();
|
|
234
|
+
return undefined;
|
|
235
|
+
};
|
|
236
|
+
const contextOf = (c) => {
|
|
237
|
+
const held = contexts.get(c);
|
|
238
|
+
if (held === undefined)
|
|
239
|
+
throw new Error("typespec-hono: no caller context was established for this request");
|
|
240
|
+
return held.value;
|
|
241
|
+
};
|
|
242
|
+
const asksRoutes = new Hono()
|
|
243
|
+
.get("/", deps.authorize([{ "BearerAuth": [] }]), zValidator("query", Asks_listQuery, deps.invalid, SYNC), contextFor("required"), async (c) => {
|
|
244
|
+
const result = await handlersFor(c).Asks_list(contextOf(c), {
|
|
245
|
+
...c.req.valid("query"),
|
|
246
|
+
});
|
|
247
|
+
switch (result.status) {
|
|
248
|
+
case 200: {
|
|
249
|
+
return c.json(servedBody(askPageSchema, result.body, "Asks_list", 200), 200);
|
|
250
|
+
}
|
|
251
|
+
case 401: {
|
|
252
|
+
return c.json(servedBody(problemSchema, result.body, "Asks_list", 401), 401);
|
|
253
|
+
}
|
|
254
|
+
default:
|
|
255
|
+
throw new UndeclaredStatusError("Asks_list", result);
|
|
256
|
+
}
|
|
257
|
+
})
|
|
258
|
+
.get("/:id", deps.authorize([{ "BearerAuth": [] }]), zValidator("param", Asks_readPath, deps.invalid, SYNC), contextFor("required"), async (c) => {
|
|
259
|
+
const result = await handlersFor(c).Asks_read(contextOf(c), {
|
|
260
|
+
...c.req.valid("param"),
|
|
261
|
+
});
|
|
262
|
+
switch (result.status) {
|
|
263
|
+
case 200: {
|
|
264
|
+
return c.json(servedBody(askSchema, result.body, "Asks_read", 200), 200);
|
|
265
|
+
}
|
|
266
|
+
case 401: {
|
|
267
|
+
return c.json(servedBody(problemSchema, result.body, "Asks_read", 401), 401);
|
|
268
|
+
}
|
|
269
|
+
case 404: {
|
|
270
|
+
return c.json(servedBody(problemSchema, result.body, "Asks_read", 404), 404);
|
|
271
|
+
}
|
|
272
|
+
default:
|
|
273
|
+
throw new UndeclaredStatusError("Asks_read", result);
|
|
274
|
+
}
|
|
275
|
+
})
|
|
276
|
+
.post("/:id/reply", deps.authorize([{ "BearerAuth": [] }]), zValidator("param", Asks_replyPath, deps.invalid, SYNC), validateBody(replySchema, deps.invalid, [
|
|
277
|
+
["application/json", "json"],
|
|
278
|
+
]), contextFor("required"), async (c) => {
|
|
279
|
+
const result = await handlersFor(c).Asks_reply(contextOf(c), {
|
|
280
|
+
...c.req.valid("param"),
|
|
281
|
+
reply: c.req.valid("json"),
|
|
282
|
+
});
|
|
283
|
+
switch (result.status) {
|
|
284
|
+
case 200: {
|
|
285
|
+
return c.json(servedBody(askSchema, result.body, "Asks_reply", 200), 200);
|
|
286
|
+
}
|
|
287
|
+
case 401: {
|
|
288
|
+
return c.json(servedBody(problemSchema, result.body, "Asks_reply", 401), 401);
|
|
289
|
+
}
|
|
290
|
+
case 404: {
|
|
291
|
+
return c.json(servedBody(problemSchema, result.body, "Asks_reply", 404), 404);
|
|
292
|
+
}
|
|
293
|
+
case 409: {
|
|
294
|
+
return c.json(servedBody(problemSchema, result.body, "Asks_reply", 409), 409);
|
|
295
|
+
}
|
|
296
|
+
case 422: {
|
|
297
|
+
return c.json(servedBody(problemSchema, result.body, "Asks_reply", 422), 422);
|
|
298
|
+
}
|
|
299
|
+
default:
|
|
300
|
+
throw new UndeclaredStatusError("Asks_reply", result);
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
const basePathRoutes = new Hono()
|
|
304
|
+
.get("/whoami", deps.authorize([{ "BearerAuth": [] }]), contextFor("required"), async (c) => {
|
|
305
|
+
const result = await handlersFor(c).Session_whoami(contextOf(c), {});
|
|
306
|
+
switch (result.status) {
|
|
307
|
+
case 200: {
|
|
308
|
+
return c.json(servedBody(whoamiSchema, result.body, "Session_whoami", 200), 200);
|
|
309
|
+
}
|
|
310
|
+
case 401: {
|
|
311
|
+
return c.json(servedBody(problemSchema, result.body, "Session_whoami", 401), 401);
|
|
312
|
+
}
|
|
313
|
+
default:
|
|
314
|
+
throw new UndeclaredStatusError("Session_whoami", result);
|
|
315
|
+
}
|
|
316
|
+
})
|
|
317
|
+
.post("/events/tickets", deps.authorize([{ "BearerAuth": [] }]), contextFor("required"), async (c) => {
|
|
318
|
+
const result = await handlersFor(c).EventTickets_issue(contextOf(c), {});
|
|
319
|
+
switch (result.status) {
|
|
320
|
+
case 201: {
|
|
321
|
+
return c.json(servedBody(eventTicketSchema, result.body, "EventTickets_issue", 201), 201);
|
|
322
|
+
}
|
|
323
|
+
case 401: {
|
|
324
|
+
return c.json(servedBody(problemSchema, result.body, "EventTickets_issue", 401), 401);
|
|
325
|
+
}
|
|
326
|
+
default:
|
|
327
|
+
throw new UndeclaredStatusError("EventTickets_issue", result);
|
|
328
|
+
}
|
|
329
|
+
})
|
|
330
|
+
.get("/snapshot", deps.authorize([{ "BearerAuth": [] }]), contextFor("required"), async (c) => {
|
|
331
|
+
const result = await handlersFor(c).Snapshots_read(contextOf(c), {});
|
|
332
|
+
switch (result.status) {
|
|
333
|
+
case 200: {
|
|
334
|
+
return c.json(servedBody(snapshotSchema, result.body, "Snapshots_read", 200), 200);
|
|
335
|
+
}
|
|
336
|
+
case 401: {
|
|
337
|
+
return c.json(servedBody(problemSchema, result.body, "Snapshots_read", 401), 401);
|
|
338
|
+
}
|
|
339
|
+
default:
|
|
340
|
+
throw new UndeclaredStatusError("Snapshots_read", result);
|
|
341
|
+
}
|
|
342
|
+
})
|
|
343
|
+
.get("/files/:uploadId", deps.authorize([{ "BearerAuth": [] }]), zValidator("param", Files_readPath, deps.invalid, SYNC), contextFor("required"), async (c) => {
|
|
344
|
+
const result = await handlersFor(c).Files_read(contextOf(c), {
|
|
345
|
+
...c.req.valid("param"),
|
|
346
|
+
});
|
|
347
|
+
switch (result.status) {
|
|
348
|
+
case 200: {
|
|
349
|
+
switch (result.contentType) {
|
|
350
|
+
case "image/png":
|
|
351
|
+
return c.body(servedBytes(result.body), 200, headersOf({ "Content-Type": result.contentType }));
|
|
352
|
+
case "image/jpeg":
|
|
353
|
+
return c.body(servedBytes(result.body), 200, headersOf({ "Content-Type": result.contentType }));
|
|
354
|
+
case "image/webp":
|
|
355
|
+
return c.body(servedBytes(result.body), 200, headersOf({ "Content-Type": result.contentType }));
|
|
356
|
+
case "image/gif":
|
|
357
|
+
return c.body(servedBytes(result.body), 200, headersOf({ "Content-Type": result.contentType }));
|
|
358
|
+
}
|
|
359
|
+
throw new UndeclaredStatusError("Files_read", result);
|
|
360
|
+
}
|
|
361
|
+
case 401: {
|
|
362
|
+
return c.json(servedBody(problemSchema, result.body, "Files_read", 401), 401);
|
|
363
|
+
}
|
|
364
|
+
case 404: {
|
|
365
|
+
return c.json(servedBody(problemSchema, result.body, "Files_read", 404), 404);
|
|
366
|
+
}
|
|
367
|
+
default:
|
|
368
|
+
throw new UndeclaredStatusError("Files_read", result);
|
|
369
|
+
}
|
|
370
|
+
})
|
|
371
|
+
.put("/uploads/:spaceId/:token", zValidator("param", Uploads_storePath, deps.invalid, SYNC), zValidator("header", Uploads_storeHeader, deps.invalid, SYNC), contextFor("none"), async (c) => {
|
|
372
|
+
const result = await handlersFor(c).Uploads_store(contextOf(c), {
|
|
373
|
+
...c.req.valid("param"),
|
|
374
|
+
...c.req.valid("header"),
|
|
375
|
+
body: c.req.raw.body,
|
|
376
|
+
});
|
|
377
|
+
switch (result.status) {
|
|
378
|
+
case 201: {
|
|
379
|
+
return c.json(servedBody(uploadReceiptSchema, result.body, "Uploads_store", 201), 201);
|
|
380
|
+
}
|
|
381
|
+
case 404: {
|
|
382
|
+
return c.json(servedBody(problemSchema, result.body, "Uploads_store", 404), 404);
|
|
383
|
+
}
|
|
384
|
+
case 410: {
|
|
385
|
+
return c.json(servedBody(problemSchema, result.body, "Uploads_store", 410), 410);
|
|
386
|
+
}
|
|
387
|
+
case 413: {
|
|
388
|
+
return c.json(servedBody(problemSchema, result.body, "Uploads_store", 413), 413);
|
|
389
|
+
}
|
|
390
|
+
case 422: {
|
|
391
|
+
return c.json(servedBody(problemSchema, result.body, "Uploads_store", 422), 422);
|
|
392
|
+
}
|
|
393
|
+
default:
|
|
394
|
+
throw new UndeclaredStatusError("Uploads_store", result);
|
|
395
|
+
}
|
|
396
|
+
})
|
|
397
|
+
.route("/asks", asksRoutes);
|
|
398
|
+
return app
|
|
399
|
+
.route("/api/v1", basePathRoutes);
|
|
400
|
+
}
|