@e22m4u/js-http-static-router 0.1.2 → 0.2.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.
Files changed (43) hide show
  1. package/.mocharc.json +2 -1
  2. package/README.md +265 -17
  3. package/build-cjs.js +1 -1
  4. package/dist/cjs/index.cjs +114 -76
  5. package/example/server.js +23 -13
  6. package/mocha.setup.js +4 -0
  7. package/package.json +10 -8
  8. package/src/http-static-router.d.ts +7 -2
  9. package/src/http-static-router.js +73 -61
  10. package/src/http-static-router.spec.js +899 -0
  11. package/src/static-route.js +18 -8
  12. package/src/types.d.ts +7 -0
  13. package/src/utils/create-cookie-string.d.ts +6 -0
  14. package/src/utils/create-cookie-string.js +28 -0
  15. package/src/utils/create-cookie-string.spec.js +32 -0
  16. package/src/utils/create-error.d.ts +14 -0
  17. package/src/utils/create-error.js +29 -0
  18. package/src/utils/create-error.spec.js +42 -0
  19. package/src/utils/create-request-mock.d.ts +35 -0
  20. package/src/utils/create-request-mock.js +483 -0
  21. package/src/utils/create-request-mock.spec.js +646 -0
  22. package/src/utils/create-response-mock.d.ts +18 -0
  23. package/src/utils/create-response-mock.js +131 -0
  24. package/src/utils/create-response-mock.spec.js +150 -0
  25. package/src/utils/fetch-request-body.d.ts +26 -0
  26. package/src/utils/fetch-request-body.js +148 -0
  27. package/src/utils/fetch-request-body.spec.js +209 -0
  28. package/src/utils/get-pathname-from-url.d.ts +1 -1
  29. package/src/utils/{get-request-pathname.spec.js → get-pathname-from-url.spec.js} +1 -1
  30. package/src/utils/index.d.ts +8 -0
  31. package/src/utils/index.js +8 -0
  32. package/src/utils/is-readable-stream.d.ts +9 -0
  33. package/src/utils/is-readable-stream.js +12 -0
  34. package/src/utils/is-readable-stream.spec.js +23 -0
  35. package/src/utils/parse-content-type.d.ts +15 -0
  36. package/src/utils/parse-content-type.js +34 -0
  37. package/src/utils/parse-content-type.spec.js +79 -0
  38. package/src/utils/parse-cookie-string.d.ts +19 -0
  39. package/src/utils/parse-cookie-string.js +36 -0
  40. package/src/utils/parse-cookie-string.spec.js +45 -0
  41. package/{example/static → static}/index.html +2 -2
  42. /package/{example/static/nested/file.txt → static/assets/nested/heart.txt} +0 -0
  43. /package/{example/static/file.txt → static/assets/rabbit.txt} +0 -0
@@ -56,7 +56,7 @@ export class StaticRoute {
56
56
  }
57
57
  if (!routeDef.remotePath.startsWith('/')) {
58
58
  throw new InvalidArgumentError(
59
- 'Option "remotePath" must starts with "/", but %v was given.',
59
+ 'Option "remotePath" must start with "/", but %v was given.',
60
60
  routeDef.remotePath,
61
61
  );
62
62
  }
@@ -67,24 +67,34 @@ export class StaticRoute {
67
67
  routeDef.resourcePath,
68
68
  );
69
69
  }
70
- const resourcePath = path.resolve(routeDef.resourcePath);
70
+ if (!path.isAbsolute(routeDef.resourcePath)) {
71
+ throw new InvalidArgumentError(
72
+ 'Option "resourcePath" must be an absolute path, but %v was given.',
73
+ routeDef.resourcePath,
74
+ );
75
+ }
71
76
  let stats;
72
77
  try {
73
- stats = fs.statSync(resourcePath);
78
+ stats = fs.statSync(routeDef.resourcePath);
74
79
  } catch (error) {
75
80
  console.error(error);
76
81
  throw new InvalidArgumentError(
77
82
  'Resource path %v does not exist.',
78
- resourcePath,
83
+ routeDef.resourcePath,
79
84
  );
80
85
  }
81
86
  const isFile = stats.isFile();
82
87
  const escapedRemotePath = escapeRegexp(routeDef.remotePath);
83
- const regexp = isFile
84
- ? new RegExp(`^${escapedRemotePath}$`)
85
- : new RegExp(`^${escapedRemotePath}(?:$|\\/)`);
88
+ let regexp;
89
+ if (isFile) {
90
+ regexp = new RegExp(`^${escapedRemotePath}$`);
91
+ } else if (escapedRemotePath === '/') {
92
+ regexp = new RegExp(`^(?:$|\\/)`);
93
+ } else {
94
+ regexp = new RegExp(`^${escapedRemotePath}(?:$|\\/)`);
95
+ }
86
96
  this.remotePath = routeDef.remotePath;
87
- this.resourcePath = resourcePath;
97
+ this.resourcePath = routeDef.resourcePath;
88
98
  this.regexp = regexp;
89
99
  this.isFile = isFile;
90
100
  }
package/src/types.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * A callable type with the "new" operator
3
+ * allows class and constructor.
4
+ */
5
+ export interface Constructor<T = unknown> {
6
+ new (...args: any[]): T;
7
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Create cookie string.
3
+ *
4
+ * @param data
5
+ */
6
+ export declare function createCookieString(data: object): string;
@@ -0,0 +1,28 @@
1
+ import {InvalidArgumentError} from '@e22m4u/js-format';
2
+
3
+ /**
4
+ * Create cookie string.
5
+ *
6
+ * @param {object} data
7
+ * @returns {string}
8
+ */
9
+ export function createCookieString(data) {
10
+ if (!data || typeof data !== 'object' || Array.isArray(data)) {
11
+ throw new InvalidArgumentError(
12
+ 'Cookie data must be an Object, but %v was given.',
13
+ data,
14
+ );
15
+ }
16
+ let cookies = '';
17
+ for (const key in data) {
18
+ if (!Object.prototype.hasOwnProperty.call(data, key)) {
19
+ continue;
20
+ }
21
+ const val = data[key];
22
+ if (val == null) {
23
+ continue;
24
+ }
25
+ cookies += `${key}=${val}; `;
26
+ }
27
+ return cookies.trim().replace(/;$/, '');
28
+ }
@@ -0,0 +1,32 @@
1
+ import {expect} from 'chai';
2
+ import {format} from '@e22m4u/js-format';
3
+ import {createCookieString} from './create-cookie-string.js';
4
+
5
+ describe('createCookieString', function () {
6
+ it('should require the parameter "data" to be an object', function () {
7
+ const throwable = v => () => createCookieString(v);
8
+ const error = v =>
9
+ format('Cookie data must be an Object, but %s was given.', v);
10
+ expect(throwable('str')).to.throw(error('"str"'));
11
+ expect(throwable('')).to.throw(error('""'));
12
+ expect(throwable(10)).to.throw(error('10'));
13
+ expect(throwable(0)).to.throw(error('0'));
14
+ expect(throwable(true)).to.throw(error('true'));
15
+ expect(throwable(false)).to.throw(error('false'));
16
+ expect(throwable(null)).to.throw(error('null'));
17
+ expect(throwable([])).to.throw(error('Array'));
18
+ expect(throwable(undefined)).to.throw(error('undefined'));
19
+ throwable({key: 'value'})();
20
+ throwable({})();
21
+ });
22
+
23
+ it('should return an empty string for an empty object', function () {
24
+ expect(createCookieString({})).to.be.eq('');
25
+ });
26
+
27
+ it('should return the cookie string for the given object', function () {
28
+ const data = {foo: 'bar', baz: 'quz'};
29
+ const result = createCookieString(data);
30
+ expect(result).to.be.eq('foo=bar; baz=quz');
31
+ });
32
+ });
@@ -0,0 +1,14 @@
1
+ import {Constructor} from '../types.js';
2
+
3
+ /**
4
+ * Create error.
5
+ *
6
+ * @param errorCtor
7
+ * @param message
8
+ * @param args
9
+ */
10
+ export declare function createError<T>(
11
+ errorCtor: Constructor<T>,
12
+ message: string,
13
+ ...args: unknown[]
14
+ ): T;
@@ -0,0 +1,29 @@
1
+ import {format, InvalidArgumentError} from '@e22m4u/js-format';
2
+
3
+ /**
4
+ * Create error.
5
+ *
6
+ * @param {Function} errorCtor
7
+ * @param {string} message
8
+ * @param {*[]|undefined} args
9
+ * @returns {object}
10
+ */
11
+ export function createError(errorCtor, message, ...args) {
12
+ if (typeof errorCtor !== 'function') {
13
+ throw new InvalidArgumentError(
14
+ 'Parameter "errorCtor" must be a Function, but %v was given.',
15
+ errorCtor,
16
+ );
17
+ }
18
+ if (message != null && typeof message !== 'string') {
19
+ throw new InvalidArgumentError(
20
+ 'Parameter "message" must be a String, but %v was given.',
21
+ message,
22
+ );
23
+ }
24
+ if (message == null) {
25
+ return new errorCtor();
26
+ }
27
+ const interpolatedMessage = format(message, ...args);
28
+ return new errorCtor(interpolatedMessage);
29
+ }
@@ -0,0 +1,42 @@
1
+ import {expect} from 'chai';
2
+ import {format} from '@e22m4u/js-format';
3
+ import {createError} from './create-error.js';
4
+
5
+ describe('createError', function () {
6
+ it('should require the parameter "errorCtor" to be a Function', function () {
7
+ const throwable = v => () => createError(v);
8
+ const error = v =>
9
+ format('Parameter "errorCtor" must be a Function, but %s was given.', v);
10
+ expect(throwable('str')).to.throw(error('"str"'));
11
+ expect(throwable('')).to.throw(error('""'));
12
+ expect(throwable(10)).to.throw(error('10'));
13
+ expect(throwable(0)).to.throw(error('0'));
14
+ expect(throwable(true)).to.throw(error('true'));
15
+ expect(throwable(false)).to.throw(error('false'));
16
+ expect(throwable(null)).to.throw(error('null'));
17
+ expect(throwable({})).to.throw(error('Object'));
18
+ expect(throwable([])).to.throw(error('Array'));
19
+ expect(throwable(undefined)).to.throw(error('undefined'));
20
+ throwable(Error)();
21
+ });
22
+
23
+ it('should require the parameter "message" to be a String', function () {
24
+ const throwable = v => () => createError(Error, v);
25
+ const error = v =>
26
+ format('Parameter "message" must be a String, but %s was given.', v);
27
+ expect(throwable(10)).to.throw(error('10'));
28
+ expect(throwable(true)).to.throw(error('true'));
29
+ expect(throwable(false)).to.throw(error('false'));
30
+ expect(throwable({})).to.throw(error('Object'));
31
+ expect(throwable([])).to.throw(error('Array'));
32
+ throwable('str')();
33
+ throwable('')();
34
+ throwable(null)();
35
+ throwable(undefined)();
36
+ });
37
+
38
+ it('should interpolate the given message with arguments', function () {
39
+ const res = createError(Error, 'My %s', 'message');
40
+ expect(res.message).to.be.eq('My message');
41
+ });
42
+ });
@@ -0,0 +1,35 @@
1
+ import {Readable} from 'stream';
2
+ import {IncomingMessage} from 'http';
3
+
4
+ /**
5
+ * Request headers input.
6
+ */
7
+ type RequestHeadersInput = {
8
+ [name: string]: string | string[];
9
+ };
10
+
11
+ /**
12
+ * Request options.
13
+ */
14
+ type RequestOptions = {
15
+ host?: string;
16
+ method?: string;
17
+ secure?: boolean;
18
+ url?: string;
19
+ path?: string;
20
+ query?: string | object;
21
+ cookies?: object;
22
+ headers?: RequestHeadersInput;
23
+ body?: unknown;
24
+ stream?: Readable;
25
+ encoding?: BufferEncoding;
26
+ };
27
+
28
+ /**
29
+ * Create request mock.
30
+ *
31
+ * @param options
32
+ */
33
+ export declare function createRequestMock(
34
+ options?: RequestOptions,
35
+ ): IncomingMessage;