@server/next 0.37.0 → 0.37.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/index.d.ts +8 -6
- package/index.js +118 -99
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -10,10 +10,8 @@ declare class UploadPipeline {
|
|
|
10
10
|
private _limits;
|
|
11
11
|
constructor(bucket?: Bucket | string | null);
|
|
12
12
|
limit(options: LimitOptions): this;
|
|
13
|
-
store(bucket: Bucket | string): this;
|
|
14
13
|
processFile(originalName: string, data: Buffer, contentType: string): Promise<UploadedFile>;
|
|
15
14
|
}
|
|
16
|
-
declare function upload(bucket?: Bucket | string | null): UploadPipeline;
|
|
17
15
|
|
|
18
16
|
type CookieOptions = string | string[] | Cookie | Cookie[] | null;
|
|
19
17
|
interface ResponseData {
|
|
@@ -31,7 +29,7 @@ declare class Reply$1 {
|
|
|
31
29
|
cookies(key: string | Record<string, CookieOptions>, value?: CookieOptions): this;
|
|
32
30
|
json(body: unknown): Response;
|
|
33
31
|
redirect(path: string): Response;
|
|
34
|
-
file(path: string): Promise<Response>;
|
|
32
|
+
file(path: string | BucketFile): Promise<Response>;
|
|
35
33
|
send(body?: string | Buffer | ReadableStream | any): Response;
|
|
36
34
|
}
|
|
37
35
|
type Params<K extends keyof Reply$1> = Reply$1[K] extends (...args: infer A) => any ? A : never;
|
|
@@ -99,6 +97,7 @@ type BucketFile = {
|
|
|
99
97
|
readonly path: string;
|
|
100
98
|
readonly id: string;
|
|
101
99
|
readonly name: string;
|
|
100
|
+
readonly type?: string;
|
|
102
101
|
exists(): Promise<boolean>;
|
|
103
102
|
info?(): Promise<FileInfo>;
|
|
104
103
|
write(content: string | Buffer | ReadableStream, options?: {
|
|
@@ -120,6 +119,9 @@ type UploadedFile = {
|
|
|
120
119
|
type: string;
|
|
121
120
|
size: number;
|
|
122
121
|
};
|
|
122
|
+
type UploadOptions = LimitOptions & {
|
|
123
|
+
bucket: string | Bucket;
|
|
124
|
+
};
|
|
123
125
|
type CorsSettings = {
|
|
124
126
|
origin: string | boolean;
|
|
125
127
|
methods: string;
|
|
@@ -209,7 +211,7 @@ type Options = {
|
|
|
209
211
|
port?: number;
|
|
210
212
|
secret?: string;
|
|
211
213
|
public?: string | Bucket;
|
|
212
|
-
uploads?: string | Bucket |
|
|
214
|
+
uploads?: string | Bucket | UploadOptions;
|
|
213
215
|
store?: KVStore;
|
|
214
216
|
cookies?: KVStore;
|
|
215
217
|
session?: KVStore | {
|
|
@@ -301,7 +303,7 @@ type Context<Params extends Record<string, string | undefined> = Record<string,
|
|
|
301
303
|
};
|
|
302
304
|
app: Server;
|
|
303
305
|
};
|
|
304
|
-
type InlineReply = Response | Reply | {
|
|
306
|
+
type InlineReply = Response | Reply | BucketFile | {
|
|
305
307
|
body: string;
|
|
306
308
|
headers?: Headers;
|
|
307
309
|
} | SerializableValue | JSX.Element | Buffer | ReadableStream;
|
|
@@ -504,4 +506,4 @@ declare class Server<O extends ServerConfig = {}> extends Router<O> {
|
|
|
504
506
|
}
|
|
505
507
|
declare function server<Session extends Record<string, any> = {}, User extends Record<string, any> = {}>(options?: Options): Server<ServerConfig<Session, User>>;
|
|
506
508
|
|
|
507
|
-
export { type AuthOption, type AuthSession, type AuthSettings, type AuthUser, type BasicValue, type Body, type BodyMode, type BodyOption, type Bucket, type BucketFile, type BunEnv, type CacheOption, type Context, type Cookie, type CorsSettings, type ExtractPathParams, type FileInfo, type InferParamType, type InlineReply, type KVStore, type
|
|
509
|
+
export { type AuthOption, type AuthSession, type AuthSettings, type AuthUser, type BasicValue, type Body, type BodyMode, type BodyOption, type Bucket, type BucketFile, type BunEnv, type CacheOption, type Context, type Cookie, type CorsSettings, type ExtractPathParams, type FileInfo, type InferParamType, type InlineReply, type KVStore, type LogLevel, type Logger, type Method, type Middleware, type Options, type ParamTypeMap, type ParamsToObject, type PathToParams, type Platform, type Provider, type Route, type RouteOptions, type RouterMethod, type SecurityOptions, type SecuritySettings, type SerializableValue, Server, type ServerConfig, TypedServerError as ServerError, type Settings, type Strategy, type Time, type UploadOptions, type UploadedFile, cache, cookies, server as default, download, file, headers, json, redirect, router, send, status, type };
|
package/index.js
CHANGED
|
@@ -102,6 +102,90 @@ var StatusError = class extends Error {
|
|
|
102
102
|
import * as fs from "fs";
|
|
103
103
|
import * as fsp from "fs/promises";
|
|
104
104
|
import * as path from "path";
|
|
105
|
+
|
|
106
|
+
// src/helpers/mimes.ts
|
|
107
|
+
var mimes_default = {
|
|
108
|
+
aac: "audio/aac",
|
|
109
|
+
abw: "application/x-abiword",
|
|
110
|
+
arc: "application/x-freearc",
|
|
111
|
+
avif: "image/avif",
|
|
112
|
+
avi: "video/x-msvideo",
|
|
113
|
+
azw: "application/vnd.amazon.ebook",
|
|
114
|
+
bin: "application/octet-stream",
|
|
115
|
+
bmp: "image/bmp",
|
|
116
|
+
bz: "application/x-bzip",
|
|
117
|
+
bz2: "application/x-bzip2",
|
|
118
|
+
cda: "application/x-cdf",
|
|
119
|
+
csh: "application/x-csh",
|
|
120
|
+
css: "text/css",
|
|
121
|
+
csv: "text/csv",
|
|
122
|
+
doc: "application/msword",
|
|
123
|
+
docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
124
|
+
eot: "application/vnd.ms-fontobject",
|
|
125
|
+
epub: "application/epub+zip",
|
|
126
|
+
gz: "application/gzip",
|
|
127
|
+
gif: "image/gif",
|
|
128
|
+
htm: "text/html",
|
|
129
|
+
html: "text/html",
|
|
130
|
+
ico: "image/vnd.microsoft.icon",
|
|
131
|
+
ics: "text/calendar",
|
|
132
|
+
jar: "application/java-archive",
|
|
133
|
+
jpeg: "image/jpeg",
|
|
134
|
+
jpg: "image/jpeg",
|
|
135
|
+
js: "text/javascript",
|
|
136
|
+
json: "application/json",
|
|
137
|
+
jsonld: "application/ld+json",
|
|
138
|
+
md: "text/markdown",
|
|
139
|
+
mid: "audio/midi",
|
|
140
|
+
midi: "audio/midi",
|
|
141
|
+
mjs: "text/javascript",
|
|
142
|
+
mp3: "audio/mpeg",
|
|
143
|
+
mp4: "video/mp4",
|
|
144
|
+
mpeg: "video/mpeg",
|
|
145
|
+
mpkg: "application/vnd.apple.installer+xml",
|
|
146
|
+
odp: "application/vnd.oasis.opendocument.presentation",
|
|
147
|
+
ods: "application/vnd.oasis.opendocument.spreadsheet",
|
|
148
|
+
odt: "application/vnd.oasis.opendocument.text",
|
|
149
|
+
oga: "audio/ogg",
|
|
150
|
+
ogv: "video/ogg",
|
|
151
|
+
ogx: "application/ogg",
|
|
152
|
+
opus: "audio/opus",
|
|
153
|
+
otf: "font/otf",
|
|
154
|
+
png: "image/png",
|
|
155
|
+
pdf: "application/pdf",
|
|
156
|
+
php: "application/x-httpd-php",
|
|
157
|
+
ppt: "application/vnd.ms-powerpoint",
|
|
158
|
+
pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
159
|
+
rar: "application/vnd.rar",
|
|
160
|
+
rtf: "application/rtf",
|
|
161
|
+
sh: "application/x-sh",
|
|
162
|
+
svg: "image/svg+xml",
|
|
163
|
+
tar: "application/x-tar",
|
|
164
|
+
text: "text/plain",
|
|
165
|
+
tif: "image/tiff",
|
|
166
|
+
tiff: "image/tiff",
|
|
167
|
+
ts: "video/mp2t",
|
|
168
|
+
ttf: "font/ttf",
|
|
169
|
+
txt: "text/plain",
|
|
170
|
+
vsd: "application/vnd.visio",
|
|
171
|
+
wav: "audio/wav",
|
|
172
|
+
weba: "audio/webm",
|
|
173
|
+
webm: "video/webm",
|
|
174
|
+
webp: "image/webp",
|
|
175
|
+
woff: "font/woff",
|
|
176
|
+
woff2: "font/woff2",
|
|
177
|
+
xhtml: "application/xhtml+xml",
|
|
178
|
+
xls: "application/vnd.ms-excel",
|
|
179
|
+
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
180
|
+
xml: "application/xml",
|
|
181
|
+
xul: "application/vnd.mozilla.xul+xml",
|
|
182
|
+
zip: "application/zip",
|
|
183
|
+
"3gp": "video/3gpp",
|
|
184
|
+
"3g2": "video/3gpp2",
|
|
185
|
+
"7z": "application/x-7z-compressed"
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
// src/helpers/bucket.ts
|
|
105
189
|
function localBucket(root) {
|
|
106
190
|
const base = path.resolve(root);
|
|
107
191
|
const resolveKey = (name) => {
|
|
@@ -114,6 +198,7 @@ function localBucket(root) {
|
|
|
114
198
|
};
|
|
115
199
|
const file2 = (name, win) => {
|
|
116
200
|
const full = resolveKey(name);
|
|
201
|
+
const type2 = mimes_default[path.extname(name).slice(1).toLowerCase()];
|
|
117
202
|
const read = () => {
|
|
118
203
|
let opts;
|
|
119
204
|
if (win) {
|
|
@@ -136,6 +221,7 @@ function localBucket(root) {
|
|
|
136
221
|
path: full,
|
|
137
222
|
id: name.replace(/^\/+/, ""),
|
|
138
223
|
name: path.basename(name),
|
|
224
|
+
type: type2,
|
|
139
225
|
async exists() {
|
|
140
226
|
const stats = await fsp.stat(full).catch(() => null);
|
|
141
227
|
return !!stats?.isFile();
|
|
@@ -145,7 +231,7 @@ function localBucket(root) {
|
|
|
145
231
|
const exists = !!stats?.isFile();
|
|
146
232
|
const total = stats?.size ?? 0;
|
|
147
233
|
const size = win ? Math.max(0, Math.min(win.end, total) - win.start) : total;
|
|
148
|
-
return { exists, size, date: stats?.mtime ?? null };
|
|
234
|
+
return { exists, size, date: stats?.mtime ?? null, type: type2 };
|
|
149
235
|
},
|
|
150
236
|
// Read-only view of [start, end), composed relative to the current window.
|
|
151
237
|
slice(start, end) {
|
|
@@ -279,10 +365,6 @@ var UploadPipeline = class {
|
|
|
279
365
|
this._limits = { ...this._limits, ...options };
|
|
280
366
|
return this;
|
|
281
367
|
}
|
|
282
|
-
store(bucket2) {
|
|
283
|
-
this._bucket = bucket(bucket2);
|
|
284
|
-
return this;
|
|
285
|
-
}
|
|
286
368
|
async processFile(originalName, data, contentType) {
|
|
287
369
|
const { maxSize, minSize, fileType } = this._limits;
|
|
288
370
|
if (maxSize !== void 0 && data.length > parseBytes(maxSize)) {
|
|
@@ -308,16 +390,11 @@ var UploadPipeline = class {
|
|
|
308
390
|
}
|
|
309
391
|
}
|
|
310
392
|
if (!this._bucket) {
|
|
311
|
-
throw new Error(
|
|
312
|
-
`No destination configured. Pass a bucket to upload() or call .store()`
|
|
313
|
-
);
|
|
393
|
+
throw new Error(`No upload destination configured (missing bucket)`);
|
|
314
394
|
}
|
|
315
395
|
return saveFileToBucket(originalName, data, this._bucket, contentType);
|
|
316
396
|
}
|
|
317
397
|
};
|
|
318
|
-
function upload(bucket2) {
|
|
319
|
-
return new UploadPipeline(bucket2);
|
|
320
|
-
}
|
|
321
398
|
|
|
322
399
|
// src/helpers/bodyLimit.ts
|
|
323
400
|
var INF = Number.POSITIVE_INFINITY;
|
|
@@ -339,88 +416,6 @@ var tooLarge = (max) => new StatusError(
|
|
|
339
416
|
413
|
|
340
417
|
);
|
|
341
418
|
|
|
342
|
-
// src/helpers/mimes.ts
|
|
343
|
-
var mimes_default = {
|
|
344
|
-
aac: "audio/aac",
|
|
345
|
-
abw: "application/x-abiword",
|
|
346
|
-
arc: "application/x-freearc",
|
|
347
|
-
avif: "image/avif",
|
|
348
|
-
avi: "video/x-msvideo",
|
|
349
|
-
azw: "application/vnd.amazon.ebook",
|
|
350
|
-
bin: "application/octet-stream",
|
|
351
|
-
bmp: "image/bmp",
|
|
352
|
-
bz: "application/x-bzip",
|
|
353
|
-
bz2: "application/x-bzip2",
|
|
354
|
-
cda: "application/x-cdf",
|
|
355
|
-
csh: "application/x-csh",
|
|
356
|
-
css: "text/css",
|
|
357
|
-
csv: "text/csv",
|
|
358
|
-
doc: "application/msword",
|
|
359
|
-
docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
360
|
-
eot: "application/vnd.ms-fontobject",
|
|
361
|
-
epub: "application/epub+zip",
|
|
362
|
-
gz: "application/gzip",
|
|
363
|
-
gif: "image/gif",
|
|
364
|
-
htm: "text/html",
|
|
365
|
-
html: "text/html",
|
|
366
|
-
ico: "image/vnd.microsoft.icon",
|
|
367
|
-
ics: "text/calendar",
|
|
368
|
-
jar: "application/java-archive",
|
|
369
|
-
jpeg: "image/jpeg",
|
|
370
|
-
jpg: "image/jpeg",
|
|
371
|
-
js: "text/javascript",
|
|
372
|
-
json: "application/json",
|
|
373
|
-
jsonld: "application/ld+json",
|
|
374
|
-
md: "text/markdown",
|
|
375
|
-
mid: "audio/midi",
|
|
376
|
-
midi: "audio/midi",
|
|
377
|
-
mjs: "text/javascript",
|
|
378
|
-
mp3: "audio/mpeg",
|
|
379
|
-
mp4: "video/mp4",
|
|
380
|
-
mpeg: "video/mpeg",
|
|
381
|
-
mpkg: "application/vnd.apple.installer+xml",
|
|
382
|
-
odp: "application/vnd.oasis.opendocument.presentation",
|
|
383
|
-
ods: "application/vnd.oasis.opendocument.spreadsheet",
|
|
384
|
-
odt: "application/vnd.oasis.opendocument.text",
|
|
385
|
-
oga: "audio/ogg",
|
|
386
|
-
ogv: "video/ogg",
|
|
387
|
-
ogx: "application/ogg",
|
|
388
|
-
opus: "audio/opus",
|
|
389
|
-
otf: "font/otf",
|
|
390
|
-
png: "image/png",
|
|
391
|
-
pdf: "application/pdf",
|
|
392
|
-
php: "application/x-httpd-php",
|
|
393
|
-
ppt: "application/vnd.ms-powerpoint",
|
|
394
|
-
pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
395
|
-
rar: "application/vnd.rar",
|
|
396
|
-
rtf: "application/rtf",
|
|
397
|
-
sh: "application/x-sh",
|
|
398
|
-
svg: "image/svg+xml",
|
|
399
|
-
tar: "application/x-tar",
|
|
400
|
-
text: "text/plain",
|
|
401
|
-
tif: "image/tiff",
|
|
402
|
-
tiff: "image/tiff",
|
|
403
|
-
ts: "video/mp2t",
|
|
404
|
-
ttf: "font/ttf",
|
|
405
|
-
txt: "text/plain",
|
|
406
|
-
vsd: "application/vnd.visio",
|
|
407
|
-
wav: "audio/wav",
|
|
408
|
-
weba: "audio/webm",
|
|
409
|
-
webm: "video/webm",
|
|
410
|
-
webp: "image/webp",
|
|
411
|
-
woff: "font/woff",
|
|
412
|
-
woff2: "font/woff2",
|
|
413
|
-
xhtml: "application/xhtml+xml",
|
|
414
|
-
xls: "application/vnd.ms-excel",
|
|
415
|
-
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
416
|
-
xml: "application/xml",
|
|
417
|
-
xul: "application/vnd.mozilla.xul+xml",
|
|
418
|
-
zip: "application/zip",
|
|
419
|
-
"3gp": "video/3gpp",
|
|
420
|
-
"3g2": "video/3gpp2",
|
|
421
|
-
"7z": "application/x-7z-compressed"
|
|
422
|
-
};
|
|
423
|
-
|
|
424
419
|
// src/helpers/parseBody.ts
|
|
425
420
|
function getBoundary(header) {
|
|
426
421
|
if (!header) return null;
|
|
@@ -897,6 +892,10 @@ var Reply = class {
|
|
|
897
892
|
return this.headers("location", path2).status(302).send();
|
|
898
893
|
}
|
|
899
894
|
async file(path2) {
|
|
895
|
+
if (typeof path2 !== "string") {
|
|
896
|
+
if (!await path2.exists()) return this.status(404).send();
|
|
897
|
+
return this.type(path2.type).send(path2.stream());
|
|
898
|
+
}
|
|
900
899
|
try {
|
|
901
900
|
const fs2 = await import("fs");
|
|
902
901
|
const ext2 = path2.split(".").pop();
|
|
@@ -925,7 +924,7 @@ var Reply = class {
|
|
|
925
924
|
return new Response(body, { status: status2, headers: headers2 });
|
|
926
925
|
}
|
|
927
926
|
const name = body?.constructor?.name;
|
|
928
|
-
if (
|
|
927
|
+
if (body instanceof Uint8Array) {
|
|
929
928
|
if (!headers2.has("content-length")) {
|
|
930
929
|
headers2.set("content-length", String(body.length));
|
|
931
930
|
}
|
|
@@ -1721,9 +1720,20 @@ function config(options = {}) {
|
|
|
1721
1720
|
}
|
|
1722
1721
|
settings.cors = cors2;
|
|
1723
1722
|
}
|
|
1724
|
-
|
|
1725
|
-
settings.
|
|
1726
|
-
|
|
1723
|
+
const publicDir = options.public || env2.PUBLIC;
|
|
1724
|
+
settings.public = publicDir ? bucket(publicDir) : null;
|
|
1725
|
+
const up = options.uploads;
|
|
1726
|
+
if (!up) {
|
|
1727
|
+
settings.uploads = null;
|
|
1728
|
+
} else if (typeof up === "object" && "bucket" in up) {
|
|
1729
|
+
const { bucket: bucket2, maxSize, minSize, fileType } = up;
|
|
1730
|
+
const hasLimits = maxSize != null || minSize != null || fileType != null;
|
|
1731
|
+
settings.uploads = hasLimits ? new UploadPipeline(bucket2).limit({ maxSize, minSize, fileType }) : bucket(bucket2);
|
|
1732
|
+
} else {
|
|
1733
|
+
settings.uploads = bucket(up);
|
|
1734
|
+
}
|
|
1735
|
+
const favicon2 = options.favicon || env2.FAVICON;
|
|
1736
|
+
if (favicon2) settings.favicon = favicon2;
|
|
1727
1737
|
settings.store = options.store ?? null;
|
|
1728
1738
|
settings.cookies = options.cookies ?? null;
|
|
1729
1739
|
if (options.session) {
|
|
@@ -1879,6 +1889,16 @@ async function parseResponse(out, ctx) {
|
|
|
1879
1889
|
if (out instanceof Blob) {
|
|
1880
1890
|
out = new Response(out, { headers: { "Content-Type": out.type } });
|
|
1881
1891
|
}
|
|
1892
|
+
if (out && typeof out.stream === "function" && typeof out.bytes === "function" && typeof out.exists === "function" && typeof out.name === "string") {
|
|
1893
|
+
if (!await out.exists()) {
|
|
1894
|
+
out = new Response(null, { status: 404 });
|
|
1895
|
+
} else {
|
|
1896
|
+
out = new Response(
|
|
1897
|
+
out.stream(),
|
|
1898
|
+
out.type ? { headers: { "content-type": out.type } } : void 0
|
|
1899
|
+
);
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1882
1902
|
if (out instanceof ReadableStream) {
|
|
1883
1903
|
out = new Response(out);
|
|
1884
1904
|
}
|
|
@@ -3264,6 +3284,5 @@ export {
|
|
|
3264
3284
|
router,
|
|
3265
3285
|
send,
|
|
3266
3286
|
status,
|
|
3267
|
-
type
|
|
3268
|
-
upload
|
|
3287
|
+
type
|
|
3269
3288
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@server/next",
|
|
3
|
-
"version": "0.37.
|
|
3
|
+
"version": "0.37.1",
|
|
4
4
|
"description": "A fully-fledged web server with routing, file uploads, sessions, static files, schema validation, websockets, testing, etc.",
|
|
5
5
|
"homepage": "https://server-js.com/",
|
|
6
6
|
"repository": "github:franciscop/server-next",
|