dx-server 0.0.1 → 0.0.3

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.
Files changed (50) hide show
  1. package/README.md +183 -0
  2. package/cjs/body.d.ts +30 -0
  3. package/cjs/body.js +91 -0
  4. package/cjs/contentType.d.ts +4 -0
  5. package/cjs/contentType.js +92 -0
  6. package/cjs/context.d.ts +15 -0
  7. package/cjs/context.js +27 -0
  8. package/cjs/error.js +42 -0
  9. package/cjs/etag.d.ts +7 -0
  10. package/cjs/etag.js +100 -0
  11. package/cjs/express.d.ts +49 -0
  12. package/cjs/express.js +168 -0
  13. package/cjs/expressApp.d.ts +4 -0
  14. package/cjs/expressApp.js +44 -0
  15. package/cjs/file.d.ts +3 -0
  16. package/cjs/file.js +12 -0
  17. package/cjs/index.d.ts +6 -0
  18. package/cjs/index.js +33 -0
  19. package/cjs/package.json +3 -0
  20. package/cjs/route.d.ts +38 -0
  21. package/cjs/route.js +86 -0
  22. package/cjs/static.d.ts +4 -0
  23. package/cjs/static.js +60 -0
  24. package/cjs/stream.d.ts +11 -0
  25. package/cjs/stream.js +100 -0
  26. package/esm/body.d.ts +30 -0
  27. package/esm/body.js +88 -0
  28. package/esm/contentType.d.ts +4 -0
  29. package/esm/contentType.js +88 -0
  30. package/esm/context.d.ts +15 -0
  31. package/esm/context.js +23 -0
  32. package/esm/error.js +37 -0
  33. package/esm/etag.d.ts +7 -0
  34. package/esm/etag.js +90 -0
  35. package/esm/express.d.ts +49 -0
  36. package/esm/express.js +156 -0
  37. package/esm/expressApp.d.ts +4 -0
  38. package/esm/expressApp.js +35 -0
  39. package/esm/file.d.ts +3 -0
  40. package/esm/file.js +8 -0
  41. package/esm/index.d.ts +6 -0
  42. package/esm/index.js +7 -0
  43. package/esm/route.d.ts +38 -0
  44. package/esm/route.js +82 -0
  45. package/esm/static.d.ts +4 -0
  46. package/esm/static.js +56 -0
  47. package/esm/stream.d.ts +11 -0
  48. package/esm/stream.js +92 -0
  49. package/package.json +32 -5
  50. package/index.js +0 -1
package/esm/file.js ADDED
@@ -0,0 +1,8 @@
1
+ import { requestContext, responseContext } from './context.js';
2
+ export const serveFile = ({ prefix = '' }) => next => {
3
+ const req = requestContext.value;
4
+ const res = responseContext.value;
5
+ if (req.method !== 'GET' && req.method !== 'HEAD')
6
+ return next();
7
+ };
8
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9maWxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBQyxjQUFjLEVBQUUsZUFBZSxFQUFDLE1BQU0sY0FBYyxDQUFBO0FBRzVELE1BQU0sQ0FBQyxNQUFNLFNBQVMsR0FBRyxDQUN4QixFQUFDLE1BQU0sR0FBRyxFQUFFLEVBRVgsRUFDWSxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUU7SUFDdkIsTUFBTSxHQUFHLEdBQUcsY0FBYyxDQUFDLEtBQUssQ0FBQTtJQUNoQyxNQUFNLEdBQUcsR0FBRyxlQUFlLENBQUMsS0FBSyxDQUFBO0lBQ2pDLElBQUksR0FBRyxDQUFDLE1BQU0sS0FBSyxLQUFLLElBQUksR0FBRyxDQUFDLE1BQU0sS0FBSyxNQUFNO1FBQUUsT0FBTyxJQUFJLEVBQUUsQ0FBQTtBQUNqRSxDQUFDLENBQUEifQ==
package/esm/index.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export { makeContext, requestContext, responseContext } from './context.js';
2
+ export { expressContext, setHtml, setJson, setBuffer, setRedirect, setText } from './express.js';
3
+ export { bufferBodyContext, jsonBodyContext, queryContext, rawBodyContext, textBodyContext, urlencodedBodyContext } from './body.js';
4
+ export { router } from './route.js';
5
+ export { catchApiError, catchError, notFound, notFoundApi } from './error.js';
6
+ export { expressApp, expressRouter, chainExpressMiddlewares } from './expressApp.js';
package/esm/index.js ADDED
@@ -0,0 +1,7 @@
1
+ export { makeContext, requestContext, responseContext } from './context.js';
2
+ export { expressContext, setHtml, setJson, setBuffer, setRedirect, setText } from './express.js';
3
+ export { bufferBodyContext, jsonBodyContext, queryContext, rawBodyContext, textBodyContext, urlencodedBodyContext } from './body.js';
4
+ export { router } from './route.js';
5
+ export { catchApiError, catchError, notFound, notFoundApi } from './error.js';
6
+ export { expressApp, expressRouter, chainExpressMiddlewares } from './expressApp.js';
7
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLFdBQVcsRUFBRSxjQUFjLEVBQUUsZUFBZSxFQUFDLE1BQU0sY0FBYyxDQUFBO0FBQ3pFLE9BQU8sRUFDTixjQUFjLEVBQ2QsT0FBTyxFQUNQLE9BQU8sRUFDUCxTQUFTLEVBQ1QsV0FBVyxFQUNYLE9BQU8sRUFDUCxNQUFNLGNBQWMsQ0FBQTtBQUNyQixPQUFPLEVBQ04saUJBQWlCLEVBQ2pCLGVBQWUsRUFDZixZQUFZLEVBQ1osY0FBYyxFQUNkLGVBQWUsRUFDZixxQkFBcUIsRUFDckIsTUFBTSxXQUFXLENBQUE7QUFDbEIsT0FBTyxFQUFDLE1BQU0sRUFBQyxNQUFNLFlBQVksQ0FBQTtBQUNqQyxPQUFPLEVBQUMsYUFBYSxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFDLE1BQU0sWUFBWSxDQUFBO0FBQzNFLE9BQU8sRUFBQyxVQUFVLEVBQUUsYUFBYSxFQUFFLHVCQUF1QixFQUFDLE1BQU0saUJBQWlCLENBQUEifQ==
package/esm/route.d.ts ADDED
@@ -0,0 +1,38 @@
1
+ import type { Key } from 'path-to-regexp';
2
+ interface RegexpToPathOptions {
3
+ end?: boolean;
4
+ strict?: boolean;
5
+ sensitive?: boolean;
6
+ start?: boolean;
7
+ delimiter?: string;
8
+ endsWith?: string;
9
+ encode?(value: string): string;
10
+ prefixes?: string;
11
+ }
12
+ export declare function matchPattern<Params extends Record<Key['name'], string>>(pathname: string, pattern: string, options?: RegexpToPathOptions): {
13
+ matched: any;
14
+ params: any;
15
+ } | undefined;
16
+ interface Chainable<P extends any[] = any[], R = any, Next = (...np: any[]) => any> {
17
+ (next: Next, ...p: P): R;
18
+ }
19
+ interface RouteContext {
20
+ matched: string;
21
+ next(): any;
22
+ params: Record<Key['name'], string>;
23
+ }
24
+ interface RouteDefinition {
25
+ [k: string]: (p: RouteContext) => any;
26
+ }
27
+ interface RouterOptions extends RegexpToPathOptions {
28
+ prefix?: string;
29
+ }
30
+ declare const allMethods: readonly ["get", "head", "post", "put", "delete", "connect", "options", "trace", "patch"];
31
+ type IRouter = {
32
+ [K in typeof allMethods[number]]: (definition: RouteDefinition, options?: RouterOptions) => Chainable;
33
+ } & {
34
+ all(definition: RouteDefinition, options?: RouterOptions): Chainable;
35
+ method(method: string, definition: RouteDefinition, options?: RouterOptions): Chainable;
36
+ };
37
+ export declare const router: IRouter;
38
+ export {};
package/esm/route.js ADDED
@@ -0,0 +1,82 @@
1
+ import { pathToRegexp } from 'path-to-regexp';
2
+ import { requestContext } from './context.js';
3
+ const cache = {};
4
+ const cacheLimit = 10000;
5
+ let cacheCount = 0;
6
+ function compilePath(path, options) {
7
+ const cacheKey = JSON.stringify(options);
8
+ const pathCache = cache[cacheKey] || (cache[cacheKey] = {});
9
+ if (pathCache[path])
10
+ return pathCache[path];
11
+ const keys = [];
12
+ const regexp = pathToRegexp(path, keys, options);
13
+ const result = {
14
+ regexp,
15
+ keys
16
+ };
17
+ if (cacheCount < cacheLimit) {
18
+ pathCache[path] = result;
19
+ cacheCount++;
20
+ }
21
+ return result;
22
+ }
23
+ export function matchPattern(pathname, pattern, options) {
24
+ options = { ...options };
25
+ options.end ??= true;
26
+ options.strict ??= false;
27
+ options.sensitive ??= false;
28
+ options.start ??= true;
29
+ if (!pattern && pattern !== '')
30
+ return;
31
+ const { regexp, keys } = compilePath(pattern, options);
32
+ const match = regexp.exec(pathname);
33
+ if (!match)
34
+ return;
35
+ const [matched, ...values] = match;
36
+ return {
37
+ matched,
38
+ params: keys.reduce((acc, key, index) => {
39
+ acc[key.name] = values[index];
40
+ return acc;
41
+ }, {})
42
+ };
43
+ }
44
+ // https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
45
+ const allMethods = [
46
+ 'get', 'head', 'post', 'put', 'delete', 'connect', 'options', 'trace', 'patch'
47
+ ];
48
+ export const router = {
49
+ method(method, router, { prefix = '', ...options } = {}) {
50
+ return next => {
51
+ const req = requestContext.value;
52
+ if (req.method !== method.toUpperCase())
53
+ return next();
54
+ for (const [pattern, handler] of Object.entries(router)) {
55
+ const match = matchPattern(req.url ?? '', `${prefix}${pattern}`, options);
56
+ if (match)
57
+ return handler({
58
+ ...match,
59
+ next,
60
+ });
61
+ }
62
+ return next();
63
+ };
64
+ },
65
+ all(router, { prefix = '', ...options } = {}) {
66
+ return next => {
67
+ const req = requestContext.value;
68
+ for (const [pattern, handler] of Object.entries(router)) {
69
+ const match = matchPattern(req.url ?? '', `${prefix}${pattern}`, options);
70
+ if (match)
71
+ return handler({
72
+ ...match,
73
+ next,
74
+ });
75
+ }
76
+ return next();
77
+ };
78
+ }
79
+ };
80
+ for (const method of allMethods)
81
+ router[method] = router.method.bind(router, method);
82
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFDLFlBQVksRUFBQyxNQUFNLGdCQUFnQixDQUFBO0FBQzNDLE9BQU8sRUFBQyxjQUFjLEVBQUMsTUFBTSxjQUFjLENBQUE7QUFFM0MsTUFBTSxLQUFLLEdBQXdCLEVBQUUsQ0FBQTtBQUNyQyxNQUFNLFVBQVUsR0FBRyxLQUFLLENBQUE7QUFDeEIsSUFBSSxVQUFVLEdBQUcsQ0FBQyxDQUFBO0FBY2xCLFNBQVMsV0FBVyxDQUFDLElBQVksRUFBRSxPQUE0QjtJQUM5RCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFBO0lBQ3hDLE1BQU0sU0FBUyxHQUFHLEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQTtJQUMzRCxJQUFJLFNBQVMsQ0FBQyxJQUFJLENBQUM7UUFBRSxPQUFPLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQTtJQUUzQyxNQUFNLElBQUksR0FBVSxFQUFFLENBQUE7SUFDdEIsTUFBTSxNQUFNLEdBQUcsWUFBWSxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUE7SUFDaEQsTUFBTSxNQUFNLEdBQUc7UUFDZCxNQUFNO1FBQ04sSUFBSTtLQUNKLENBQUE7SUFFRCxJQUFJLFVBQVUsR0FBRyxVQUFVLEVBQUU7UUFDNUIsU0FBUyxDQUFDLElBQUksQ0FBQyxHQUFHLE1BQU0sQ0FBQTtRQUN4QixVQUFVLEVBQUUsQ0FBQTtLQUNaO0lBQ0QsT0FBTyxNQUFNLENBQUE7QUFDZCxDQUFDO0FBRUQsTUFBTSxVQUFVLFlBQVksQ0FDM0IsUUFBZ0IsRUFDaEIsT0FBZSxFQUNmLE9BQTZCO0lBRTdCLE9BQU8sR0FBRyxFQUFDLEdBQUcsT0FBTyxFQUFDLENBQUE7SUFD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
@@ -0,0 +1,4 @@
1
+ export declare function staticMiddleware({ root }: {
2
+ root: string;
3
+ maxAge?: number;
4
+ }): (next: () => any) => Promise<any>;
package/esm/static.js ADDED
@@ -0,0 +1,56 @@
1
+ // @ts-nocheck
2
+ import { requestContext } from './context.js';
3
+ export function staticMiddleware({ root }) {
4
+ return async (next) => {
5
+ const req = requestContext.value;
6
+ if (req.method !== 'GET' && req.method !== 'HEAD')
7
+ return next();
8
+ var forwardError = !fallthrough;
9
+ var originalUrl = parseUrl.original(req);
10
+ var path = parseUrl(req).pathname;
11
+ // make sure redirect occurs at mount
12
+ if (path === '/' && originalUrl.pathname.substr(-1) !== '/') {
13
+ path = '';
14
+ }
15
+ // create send stream
16
+ var stream = send(req, path, opts);
17
+ // add directory handler
18
+ stream.on('directory', onDirectory);
19
+ // add headers listener
20
+ if (setHeaders) {
21
+ stream.on('headers', setHeaders);
22
+ }
23
+ // add file listener for fallthrough
24
+ if (fallthrough) {
25
+ stream.on('file', function onFile() {
26
+ // once file is determined, always forward error
27
+ forwardError = true;
28
+ });
29
+ }
30
+ // forward errors
31
+ stream.on('error', function error(err) {
32
+ if (forwardError || !(err.statusCode < 500)) {
33
+ next(err);
34
+ return;
35
+ }
36
+ next();
37
+ });
38
+ // pipe
39
+ stream.pipe(res);
40
+ };
41
+ }
42
+ /**
43
+ * Collapse all leading slashes into a single slash
44
+ * @private
45
+ */
46
+ function collapseLeadingSlashes(str) {
47
+ for (let i = 0; i < str.length; i++) {
48
+ if (str.charCodeAt(i) !== 0x2f /* / */) {
49
+ break;
50
+ }
51
+ }
52
+ return i > 1
53
+ ? '/' + str.slice(i)
54
+ : str;
55
+ }
56
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdGljLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3N0YXRpYy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjO0FBQ2QsT0FBTyxFQUFDLGNBQWMsRUFBQyxNQUFNLGNBQWMsQ0FBQTtBQUUzQyxNQUFNLFVBQVUsZ0JBQWdCLENBQy9CLEVBQUMsSUFBSSxFQUdKO0lBRUQsT0FBTyxLQUFLLEVBQUUsSUFBZSxFQUFFLEVBQUU7UUFDaEMsTUFBTSxHQUFHLEdBQUcsY0FBYyxDQUFDLEtBQUssQ0FBQTtRQUNoQyxJQUFJLEdBQUcsQ0FBQyxNQUFNLEtBQUssS0FBSyxJQUFJLEdBQUcsQ0FBQyxNQUFNLEtBQUssTUFBTTtZQUFFLE9BQU8sSUFBSSxFQUFFLENBQUE7UUFFaEUsSUFBSSxZQUFZLEdBQUcsQ0FBQyxXQUFXLENBQUE7UUFDL0IsSUFBSSxXQUFXLEdBQUcsUUFBUSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQTtRQUN4QyxJQUFJLElBQUksR0FBRyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFBO1FBRWpDLHFDQUFxQztRQUNyQyxJQUFJLElBQUksS0FBSyxHQUFHLElBQUksV0FBVyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLEVBQUU7WUFDNUQsSUFBSSxHQUFHLEVBQUUsQ0FBQTtTQUNUO1FBRUQscUJBQXFCO1FBQ3JCLElBQUksTUFBTSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFBO1FBRWxDLHdCQUF3QjtRQUN4QixNQUFNLENBQUMsRUFBRSxDQUFDLFdBQVcsRUFBRSxXQUFXLENBQUMsQ0FBQTtRQUVuQyx1QkFBdUI7UUFDdkIsSUFBSSxVQUFVLEVBQUU7WUFDZixNQUFNLENBQUMsRUFBRSxDQUFDLFNBQVMsRUFBRSxVQUFVLENBQUMsQ0FBQTtTQUNoQztRQUVELG9DQUFvQztRQUNwQyxJQUFJLFdBQVcsRUFBRTtZQUNoQixNQUFNLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxTQUFTLE1BQU07Z0JBQ2hDLGdEQUFnRDtnQkFDaEQsWUFBWSxHQUFHLElBQUksQ0FBQTtZQUNwQixDQUFDLENBQUMsQ0FBQTtTQUNGO1FBRUQsaUJBQWlCO1FBQ2pCLE1BQU0sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLFNBQVMsS0FBSyxDQUFDLEdBQUc7WUFDcEMsSUFBSSxZQUFZLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxVQUFVLEdBQUcsR0FBRyxDQUFDLEVBQUU7Z0JBQzVDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQTtnQkFDVCxPQUFNO2FBQ047WUFFRCxJQUFJLEVBQUUsQ0FBQTtRQUNQLENBQUMsQ0FBQyxDQUFBO1FBRUYsT0FBTztRQUNQLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUE7SUFDakIsQ0FBQyxDQUFBO0FBQ0YsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQVMsc0JBQXNCLENBQUUsR0FBVztJQUMzQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtRQUNwQyxJQUFJLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUN2QyxNQUFLO1NBQ0w7S0FDRDtJQUVELE9BQU8sQ0FBQyxHQUFHLENBQUM7UUFDWCxDQUFDLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQ3BCLENBQUMsQ0FBQyxHQUFHLENBQUE7QUFDUCxDQUFDIn0=
@@ -0,0 +1,11 @@
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ /// <reference types="node" resolution-mode="require"/>
3
+ /// <reference types="node" resolution-mode="require"/>
4
+ /// <reference types="node" resolution-mode="require"/>
5
+ import type { IncomingMessage } from 'node:http';
6
+ import type { Readable } from 'node:stream';
7
+ export declare function getContentStream(req: IncomingMessage, encoding: string, disableInflate?: boolean): IncomingMessage | import("zlib").Gunzip;
8
+ export declare function readStream(stream: Readable, { length, limit }: {
9
+ length?: number;
10
+ limit?: number;
11
+ }): Promise<Buffer>;
package/esm/stream.js ADDED
@@ -0,0 +1,92 @@
1
+ import { createInflate, createGunzip, createBrotliDecompress } from 'node:zlib';
2
+ import makeDefer from 'jdefer';
3
+ // note: there might be multiple encodings applied to the stream
4
+ // we only support one encoding
5
+ export function getContentStream(req, encoding, disableInflate) {
6
+ if (disableInflate && encoding !== 'identity')
7
+ throw new Error(`content-encoding ${encoding} is not supported`);
8
+ switch (encoding) {
9
+ case 'deflate': {
10
+ const stream = createInflate();
11
+ req.pipe(stream);
12
+ return stream;
13
+ }
14
+ case 'gzip': {
15
+ const stream = createGunzip();
16
+ req.pipe(stream);
17
+ return stream;
18
+ }
19
+ case 'br': {
20
+ const stream = createBrotliDecompress();
21
+ req.pipe(stream);
22
+ return stream;
23
+ }
24
+ case 'identity':
25
+ return req;
26
+ default:
27
+ throw new Error(`unsupported content-encoding ${encoding}`);
28
+ }
29
+ }
30
+ // https://github.com/stream-utils/raw-body/blob/191e4b6506dcf77198eed01c8feb4b6817008342/index.js#L155
31
+ export async function readStream(stream, { length, limit }) {
32
+ let completed = false;
33
+ // check the length and limit options.
34
+ // note: we intentionally leave the stream paused,
35
+ // so users should handle the stream themselves.
36
+ if (limit !== undefined && length !== undefined && length > limit)
37
+ throw new Error('request entity too large');
38
+ let received = 0;
39
+ const buffers = [];
40
+ const defer = makeDefer();
41
+ // attach listeners
42
+ stream.on('aborted', onAborted);
43
+ stream.on('close', onClose);
44
+ stream.on('data', onData);
45
+ stream.on('end', onEnd);
46
+ stream.on('error', onError);
47
+ function done(err, result) {
48
+ if (completed)
49
+ return;
50
+ completed = true;
51
+ onClose();
52
+ if (err) {
53
+ stream.unpipe?.();
54
+ stream.pause?.();
55
+ defer.reject(err);
56
+ }
57
+ else
58
+ defer.resolve(result);
59
+ }
60
+ function onData(chunk) {
61
+ if (completed)
62
+ return;
63
+ received += chunk.length;
64
+ if (limit !== undefined && received > limit) {
65
+ done(new Error('request entity too large'));
66
+ }
67
+ else
68
+ buffers.push(chunk);
69
+ }
70
+ function onError(err) {
71
+ done(err);
72
+ }
73
+ function onEnd() {
74
+ if (length !== undefined && received !== length)
75
+ done(new Error('request size did not match content length'));
76
+ else
77
+ done(undefined, Buffer.concat(buffers));
78
+ }
79
+ function onAborted() {
80
+ done(new Error('request aborted'));
81
+ }
82
+ function onClose() {
83
+ buffers.splice(0, buffers.length);
84
+ stream.off('aborted', onAborted);
85
+ stream.off('data', onData);
86
+ stream.off('end', onEnd);
87
+ stream.off('error', onEnd);
88
+ stream.off('close', onClose);
89
+ }
90
+ return await defer.promise;
91
+ }
92
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RyZWFtLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3N0cmVhbS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHQSxPQUFPLEVBQUMsYUFBYSxFQUFFLFlBQVksRUFBRSxzQkFBc0IsRUFBQyxNQUFNLFdBQVcsQ0FBQTtBQUM3RSxPQUFPLFNBQVMsTUFBTSxRQUFRLENBQUE7QUFFOUIsZ0VBQWdFO0FBQ2hFLCtCQUErQjtBQUMvQixNQUFNLFVBQVUsZ0JBQWdCLENBQUMsR0FBb0IsRUFBRSxRQUFnQixFQUFFLGNBQXdCO0lBQ2hHLElBQUksY0FBYyxJQUFJLFFBQVEsS0FBSyxVQUFVO1FBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyxvQkFBb0IsUUFBUSxtQkFBbUIsQ0FBQyxDQUFBO0lBRS9HLFFBQVEsUUFBUSxFQUFFO1FBQ2pCLEtBQUssU0FBUyxDQUFDLENBQUM7WUFDZixNQUFNLE1BQU0sR0FBRyxhQUFhLEVBQUUsQ0FBQTtZQUM5QixHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFBO1lBQ2hCLE9BQU8sTUFBTSxDQUFBO1NBQ2I7UUFDRCxLQUFLLE1BQU0sQ0FBQyxDQUFDO1lBQ1osTUFBTSxNQUFNLEdBQUcsWUFBWSxFQUFFLENBQUE7WUFDN0IsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQTtZQUNoQixPQUFPLE1BQU0sQ0FBQTtTQUNiO1FBQ0QsS0FBSyxJQUFJLENBQUMsQ0FBQztZQUNWLE1BQU0sTUFBTSxHQUFHLHNCQUFzQixFQUFFLENBQUE7WUFDdkMsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQTtZQUNoQixPQUFPLE1BQU0sQ0FBQTtTQUNiO1FBQ0QsS0FBSyxVQUFVO1lBQ2QsT0FBTyxHQUFHLENBQUE7UUFDWDtZQUNDLE1BQU0sSUFBSSxLQUFLLENBQUMsZ0NBQWdDLFFBQVEsRUFBRSxDQUFDLENBQUE7S0FDNUQ7QUFDRixDQUFDO0FBRUQsdUdBQXVHO0FBQ3ZHLE1B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
package/package.json CHANGED
@@ -1,9 +1,36 @@
1
1
  {
2
2
  "name": "dx-server",
3
- "version": "0.0.1",
4
- "main": "index.js",
5
- "repository": "git@github.com:tranvansang/dx-server.git",
3
+ "version": "0.0.3",
4
+ "main": "./cjs/index.js",
5
+ "repository": "https://github.com/tranvansang/dx-server",
6
6
  "author": "Sang Tran <t@sang.jp>",
7
+ "files": [
8
+ "cjs",
9
+ "esm"
10
+ ],
11
+ "exports": {
12
+ ".": {
13
+ "import": "./esm/index.js",
14
+ "require": "./cjs/index.js"
15
+ }
16
+ },
17
+ "type": "module",
18
+ "scripts": {
19
+ "prepublish": "./compile.sh"
20
+ },
7
21
  "license": "MIT",
8
- "private": false
9
- }
22
+ "packageManager": "yarn@3.6.1",
23
+ "devDependencies": {
24
+ "@types/node": "^20.4.9",
25
+ "@types/path-to-regexp": "^1.7.0",
26
+ "@types/qs": "^6.9.7",
27
+ "type-fest": "^4.2.0",
28
+ "typescript": "^5.1.6"
29
+ },
30
+ "dependencies": {
31
+ "jdefer": "^0.0.9",
32
+ "jmisc": "^0.0.9",
33
+ "path-to-regexp": "^6.2.1",
34
+ "qs": "^6.11.2"
35
+ }
36
+ }
package/index.js DELETED
@@ -1 +0,0 @@
1
- echo 'this is a placeholder for the upcoming package'