@depup/type-is 2.0.1-depup.0 → 3.0.0-depup.0

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/README.md CHANGED
@@ -13,16 +13,10 @@ npm install @depup/type-is
13
13
 
14
14
  | Field | Value |
15
15
  |-------|-------|
16
- | Original | [type-is](https://www.npmjs.com/package/type-is) @ 2.0.1 |
17
- | Processed | 2026-03-19 |
16
+ | Original | [type-is](https://www.npmjs.com/package/type-is) @ 3.0.0 |
17
+ | Processed | 2026-09-27 |
18
18
  | Smoke test | passed |
19
- | Deps updated | 1 |
20
-
21
- ## Dependency Changes
22
-
23
- | Dependency | From | To |
24
- |------------|------|-----|
25
- | mime-types | ^3.0.0 | ^3.0.2 |
19
+ | Deps updated | 0 |
26
20
 
27
21
  ---
28
22
 
package/changes.json CHANGED
@@ -1,10 +1,5 @@
1
1
  {
2
- "bumped": {
3
- "mime-types": {
4
- "from": "^3.0.0",
5
- "to": "^3.0.2"
6
- }
7
- },
8
- "timestamp": "2026-03-19T03:02:19.760Z",
9
- "totalUpdated": 1
2
+ "bumped": {},
3
+ "timestamp": "2026-09-27T01:04:19.786Z",
4
+ "totalUpdated": 0
10
5
  }
@@ -0,0 +1,63 @@
1
+ /*!
2
+ * type-is
3
+ * Copyright(c) 2014 Jonathan Ong
4
+ * Copyright(c) 2014-2015 Douglas Christopher Wilson
5
+ * MIT Licensed
6
+ */
7
+ import { ContentType } from "content-type";
8
+ /**
9
+ * Node.js HTTP request shape.
10
+ */
11
+ export interface RequestLike {
12
+ headers: Record<string, string | string[] | undefined>;
13
+ }
14
+ /**
15
+ * Check if a request has a request body. A request with a body must either have
16
+ * `transfer-encoding` or `content-length` headers set.
17
+ */
18
+ export declare function hasBody(req: RequestLike): boolean;
19
+ /**
20
+ * The default behavior of `lookup` handles only a few common shorthands.
21
+ */
22
+ export declare function DEFAULT_LOOKUP(value: string): string | string[] | undefined;
23
+ export interface NormalizeOptions {
24
+ lookup?: (value: string) => string | string[] | undefined;
25
+ }
26
+ /**
27
+ * Normalize MIME type by:
28
+ *
29
+ * - If the string contains a `/`, then it is returned as the type.
30
+ * - If the string starts with `+` (so it is a `+suffix` shorthand like `+json`), then it is expanded to contain the complete wildcard notation of `*\/*+suffix`.
31
+ * - Else the string is assumed to be a file extension and the mapped media type is returned, or the original input if there is no mapping.
32
+ */
33
+ export declare function normalize(value: string, options?: NormalizeOptions): string | string[];
34
+ /**
35
+ * Compile an expected mime type into a reusable matcher.
36
+ */
37
+ export declare function match(expected: string): (actual: string) => boolean;
38
+ export type ParameterValue = (key: string, value: string) => string;
39
+ /**
40
+ * Normalize a parameter value for comparison.
41
+ */
42
+ export declare function DEFAULT_PARAMETER_VALUE(key: string, value: string): string;
43
+ export interface TypeIsOptions extends NormalizeOptions {
44
+ parameterValue?: ParameterValue;
45
+ }
46
+ export declare class TypeIs {
47
+ private readonly hasParameters;
48
+ private readonly patterns;
49
+ private readonly parameterValue;
50
+ /**
51
+ * Compile a list of expected mime types into a reusable matcher.
52
+ */
53
+ constructor(types: readonly string[], options?: TypeIsOptions);
54
+ /**
55
+ * Check whether a content type matches one of the configured types.
56
+ */
57
+ is(value: string): string | undefined;
58
+ /**
59
+ * Check whether a request body matches one of the configured types.
60
+ */
61
+ request(req: RequestLike): string | undefined;
62
+ contentType(contentType: Pick<ContentType, "type" | "parameters">): string | undefined;
63
+ }
package/dist/index.js ADDED
@@ -0,0 +1,170 @@
1
+ /*!
2
+ * type-is
3
+ * Copyright(c) 2014 Jonathan Ong
4
+ * Copyright(c) 2014-2015 Douglas Christopher Wilson
5
+ * MIT Licensed
6
+ */
7
+ import { parse, isTypeValid, isTokenValid } from "content-type";
8
+ /**
9
+ * Check if a request has a request body. A request with a body must either have
10
+ * `transfer-encoding` or `content-length` headers set.
11
+ */
12
+ export function hasBody(req) {
13
+ return (req.headers["transfer-encoding"] !== undefined ||
14
+ !Number.isNaN(Number(req.headers["content-length"])));
15
+ }
16
+ /**
17
+ * The default behavior of `lookup` handles only a few common shorthands.
18
+ */
19
+ export function DEFAULT_LOOKUP(value) {
20
+ switch (value) {
21
+ case "urlencoded":
22
+ return "application/x-www-form-urlencoded";
23
+ case "multipart":
24
+ return "multipart/*";
25
+ case "json":
26
+ return "application/json";
27
+ default:
28
+ return undefined;
29
+ }
30
+ }
31
+ /**
32
+ * Normalize MIME type by:
33
+ *
34
+ * - If the string contains a `/`, then it is returned as the type.
35
+ * - If the string starts with `+` (so it is a `+suffix` shorthand like `+json`), then it is expanded to contain the complete wildcard notation of `*\/*+suffix`.
36
+ * - Else the string is assumed to be a file extension and the mapped media type is returned, or the original input if there is no mapping.
37
+ */
38
+ export function normalize(value, options) {
39
+ if (value.includes("/"))
40
+ return value;
41
+ if (value.startsWith("+"))
42
+ return `*/*${value}`;
43
+ const lookup = options?.lookup ?? DEFAULT_LOOKUP;
44
+ return lookup(value) ?? value;
45
+ }
46
+ /**
47
+ * Compile an expected mime type into a reusable matcher.
48
+ */
49
+ export function match(expected) {
50
+ const expectedSlash = expected.indexOf("/");
51
+ if (expectedSlash === -1 || !isTypeValid(expected)) {
52
+ throw new TypeError(`Invalid mime type: ${expected}`);
53
+ }
54
+ const type = expected.slice(0, expectedSlash);
55
+ let subtype = expected.slice(expectedSlash + 1);
56
+ let suffix = "";
57
+ if (subtype.startsWith("*+")) {
58
+ suffix = subtype.slice(1);
59
+ subtype = "*";
60
+ }
61
+ if (type === "*" && subtype === "*") {
62
+ if (!suffix)
63
+ return (actual) => isTypeValid(actual);
64
+ return (actual) => {
65
+ return (actual.charAt(actual.length - suffix.length - 1) !== "/" &&
66
+ actual.endsWith(suffix) &&
67
+ isTypeValid(actual));
68
+ };
69
+ }
70
+ if (type === "*") {
71
+ return (actual) => {
72
+ return (actual.charAt(actual.length - subtype.length - 1) === "/" &&
73
+ actual.endsWith(subtype) &&
74
+ isTokenValid(actual, 0, actual.length - subtype.length - 1));
75
+ };
76
+ }
77
+ if (subtype === "*") {
78
+ return (actual) => {
79
+ return (actual.charAt(type.length) === "/" &&
80
+ actual.startsWith(type) &&
81
+ actual.endsWith(suffix) &&
82
+ isTokenValid(actual, type.length + 1, actual.length - suffix.length));
83
+ };
84
+ }
85
+ return (actual) => actual === expected;
86
+ }
87
+ /**
88
+ * Normalize a parameter value for comparison.
89
+ */
90
+ export function DEFAULT_PARAMETER_VALUE(key, value) {
91
+ if (key === "charset")
92
+ return value.toLowerCase();
93
+ return value;
94
+ }
95
+ export class TypeIs {
96
+ hasParameters = false;
97
+ patterns = [];
98
+ parameterValue;
99
+ /**
100
+ * Compile a list of expected mime types into a reusable matcher.
101
+ */
102
+ constructor(types, options) {
103
+ this.parameterValue = options?.parameterValue ?? DEFAULT_PARAMETER_VALUE;
104
+ for (const key of types) {
105
+ const contentType = parse(key);
106
+ const hasParameters = Object.keys(contentType.parameters).length > 0;
107
+ const type = normalize(contentType.type, options);
108
+ const parameters = contentType.parameters;
109
+ // Normalize parameter values before comparison.
110
+ for (const key of Object.keys(parameters)) {
111
+ parameters[key] = this.parameterValue(key, parameters[key]);
112
+ }
113
+ this.hasParameters ||= hasParameters;
114
+ if (Array.isArray(type)) {
115
+ for (const t of type) {
116
+ this.patterns.push({
117
+ key,
118
+ match: match(t),
119
+ parameters,
120
+ hasParameters,
121
+ });
122
+ }
123
+ }
124
+ else {
125
+ this.patterns.push({
126
+ key,
127
+ match: match(type),
128
+ parameters,
129
+ hasParameters,
130
+ });
131
+ }
132
+ }
133
+ }
134
+ /**
135
+ * Check whether a content type matches one of the configured types.
136
+ */
137
+ is(value) {
138
+ const contentType = parse(value, { parameters: this.hasParameters });
139
+ return this.contentType(contentType);
140
+ }
141
+ /**
142
+ * Check whether a request body matches one of the configured types.
143
+ */
144
+ request(req) {
145
+ if (!hasBody(req))
146
+ return;
147
+ const header = req.headers["content-type"];
148
+ if (!header)
149
+ return;
150
+ const value = Array.isArray(header) ? header[0] : header;
151
+ return this.is(value);
152
+ }
153
+ contentType(contentType) {
154
+ for (const pattern of this.patterns) {
155
+ if (pattern.match(contentType.type)) {
156
+ const parametersMatch = !pattern.hasParameters ||
157
+ Object.keys(pattern.parameters).every((key) => {
158
+ const actual = contentType.parameters[key];
159
+ if (actual === undefined)
160
+ return false;
161
+ const expected = pattern.parameters[key];
162
+ return expected === this.parameterValue(key, actual);
163
+ });
164
+ if (parametersMatch)
165
+ return pattern.key;
166
+ }
167
+ }
168
+ }
169
+ }
170
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * type-is\n * Copyright(c) 2014 Jonathan Ong\n * Copyright(c) 2014-2015 Douglas Christopher Wilson\n * MIT Licensed\n */\n\nimport { parse, isTypeValid, isTokenValid, ContentType } from \"content-type\";\n\n/**\n * Node.js HTTP request shape.\n */\nexport interface RequestLike {\n headers: Record<string, string | string[] | undefined>;\n}\n\n/**\n * Check if a request has a request body. A request with a body must either have\n * `transfer-encoding` or `content-length` headers set.\n */\nexport function hasBody(req: RequestLike): boolean {\n return (\n req.headers[\"transfer-encoding\"] !== undefined ||\n !Number.isNaN(Number(req.headers[\"content-length\"]))\n );\n}\n\n/**\n * The default behavior of `lookup` handles only a few common shorthands.\n */\nexport function DEFAULT_LOOKUP(value: string): string | string[] | undefined {\n switch (value) {\n case \"urlencoded\":\n return \"application/x-www-form-urlencoded\";\n case \"multipart\":\n return \"multipart/*\";\n case \"json\":\n return \"application/json\";\n default:\n return undefined;\n }\n}\n\nexport interface NormalizeOptions {\n lookup?: (value: string) => string | string[] | undefined;\n}\n\n/**\n * Normalize MIME type by:\n *\n * - If the string contains a `/`, then it is returned as the type.\n * - If the string starts with `+` (so it is a `+suffix` shorthand like `+json`), then it is expanded to contain the complete wildcard notation of `*\\/*+suffix`.\n * - Else the string is assumed to be a file extension and the mapped media type is returned, or the original input if there is no mapping.\n */\nexport function normalize(\n value: string,\n options?: NormalizeOptions,\n): string | string[] {\n if (value.includes(\"/\")) return value;\n if (value.startsWith(\"+\")) return `*/*${value}`;\n const lookup = options?.lookup ?? DEFAULT_LOOKUP;\n return lookup(value) ?? value;\n}\n\n/**\n * Compile an expected mime type into a reusable matcher.\n */\nexport function match(expected: string): (actual: string) => boolean {\n const expectedSlash = expected.indexOf(\"/\");\n\n if (expectedSlash === -1 || !isTypeValid(expected)) {\n throw new TypeError(`Invalid mime type: ${expected}`);\n }\n\n const type = expected.slice(0, expectedSlash);\n let subtype = expected.slice(expectedSlash + 1);\n let suffix = \"\";\n\n if (subtype.startsWith(\"*+\")) {\n suffix = subtype.slice(1);\n subtype = \"*\";\n }\n\n if (type === \"*\" && subtype === \"*\") {\n if (!suffix) return (actual: string) => isTypeValid(actual);\n\n return (actual: string) => {\n return (\n actual.charAt(actual.length - suffix.length - 1) !== \"/\" &&\n actual.endsWith(suffix) &&\n isTypeValid(actual)\n );\n };\n }\n\n if (type === \"*\") {\n return (actual: string) => {\n return (\n actual.charAt(actual.length - subtype.length - 1) === \"/\" &&\n actual.endsWith(subtype) &&\n isTokenValid(actual, 0, actual.length - subtype.length - 1)\n );\n };\n }\n\n if (subtype === \"*\") {\n return (actual: string) => {\n return (\n actual.charAt(type.length) === \"/\" &&\n actual.startsWith(type) &&\n actual.endsWith(suffix) &&\n isTokenValid(actual, type.length + 1, actual.length - suffix.length)\n );\n };\n }\n\n return (actual: string): boolean => actual === expected;\n}\n\ninterface Pattern {\n key: string;\n match: (value: string) => boolean;\n parameters: Record<string, string>;\n hasParameters: boolean;\n}\n\nexport type ParameterValue = (key: string, value: string) => string;\n\n/**\n * Normalize a parameter value for comparison.\n */\nexport function DEFAULT_PARAMETER_VALUE(key: string, value: string): string {\n if (key === \"charset\") return value.toLowerCase();\n return value;\n}\n\nexport interface TypeIsOptions extends NormalizeOptions {\n parameterValue?: ParameterValue;\n}\n\nexport class TypeIs {\n private readonly hasParameters: boolean = false;\n private readonly patterns: Pattern[] = [];\n private readonly parameterValue: ParameterValue;\n\n /**\n * Compile a list of expected mime types into a reusable matcher.\n */\n constructor(types: readonly string[], options?: TypeIsOptions) {\n this.parameterValue = options?.parameterValue ?? DEFAULT_PARAMETER_VALUE;\n\n for (const key of types) {\n const contentType = parse(key);\n const hasParameters = Object.keys(contentType.parameters).length > 0;\n const type = normalize(contentType.type, options);\n const parameters = contentType.parameters;\n\n // Normalize parameter values before comparison.\n for (const key of Object.keys(parameters)) {\n parameters[key] = this.parameterValue(key, parameters[key]);\n }\n\n this.hasParameters ||= hasParameters;\n\n if (Array.isArray(type)) {\n for (const t of type) {\n this.patterns.push({\n key,\n match: match(t),\n parameters,\n hasParameters,\n });\n }\n } else {\n this.patterns.push({\n key,\n match: match(type),\n parameters,\n hasParameters,\n });\n }\n }\n }\n\n /**\n * Check whether a content type matches one of the configured types.\n */\n is(value: string): string | undefined {\n const contentType = parse(value, { parameters: this.hasParameters });\n return this.contentType(contentType);\n }\n\n /**\n * Check whether a request body matches one of the configured types.\n */\n request(req: RequestLike): string | undefined {\n if (!hasBody(req)) return;\n const header = req.headers[\"content-type\"];\n if (!header) return;\n const value = Array.isArray(header) ? header[0] : header;\n return this.is(value);\n }\n\n contentType(\n contentType: Pick<ContentType, \"type\" | \"parameters\">,\n ): string | undefined {\n for (const pattern of this.patterns) {\n if (pattern.match(contentType.type)) {\n const parametersMatch =\n !pattern.hasParameters ||\n Object.keys(pattern.parameters).every((key) => {\n const actual = contentType.parameters[key];\n if (actual === undefined) return false;\n const expected = pattern.parameters[key];\n return expected === this.parameterValue(key, actual);\n });\n\n if (parametersMatch) return pattern.key;\n }\n }\n }\n}\n"]}
package/package.json CHANGED
@@ -1,46 +1,7 @@
1
1
  {
2
2
  "name": "@depup/type-is",
3
+ "version": "3.0.0-depup.0",
3
4
  "description": "Infer the content-type of a request. (with updated dependencies)",
4
- "version": "2.0.1-depup.0",
5
- "contributors": [
6
- "Douglas Christopher Wilson <doug@somethingdoug.com>",
7
- "Jonathan Ong <me@jongleberry.com> (http://jongleberry.com)"
8
- ],
9
- "license": "MIT",
10
- "repository": "jshttp/type-is",
11
- "dependencies": {
12
- "content-type": "^1.0.5",
13
- "media-typer": "^1.1.0",
14
- "mime-types": "^3.0.2"
15
- },
16
- "devDependencies": {
17
- "eslint": "7.32.0",
18
- "eslint-config-standard": "14.1.1",
19
- "eslint-plugin-import": "2.25.4",
20
- "eslint-plugin-markdown": "2.2.1",
21
- "eslint-plugin-node": "11.1.0",
22
- "eslint-plugin-promise": "5.2.0",
23
- "eslint-plugin-standard": "4.1.0",
24
- "mocha": "9.2.1",
25
- "nyc": "15.1.0"
26
- },
27
- "engines": {
28
- "node": ">= 0.6"
29
- },
30
- "files": [
31
- "LICENSE",
32
- "HISTORY.md",
33
- "index.js",
34
- "changes.json",
35
- "README.md"
36
- ],
37
- "scripts": {
38
- "lint": "eslint .",
39
- "test": "mocha --reporter spec --check-leaks --bail test/",
40
- "test:debug": "mocha --reporter spec --check-leaks --inspect --inspect-brk test/",
41
- "test-ci": "nyc --reporter=lcovonly --reporter=text npm test",
42
- "test-cov": "nyc --reporter=html --reporter=text npm test"
43
- },
44
5
  "keywords": [
45
6
  "type-is",
46
7
  "depup",
@@ -52,17 +13,59 @@
52
13
  "type",
53
14
  "checking"
54
15
  ],
16
+ "repository": "jshttp/type-is",
17
+ "funding": {
18
+ "type": "opencollective",
19
+ "url": "https://opencollective.com/express"
20
+ },
21
+ "license": "MIT",
22
+ "contributors": [
23
+ "Douglas Christopher Wilson <doug@somethingdoug.com>",
24
+ "Jonathan Ong <me@jongleberry.com> (http://jongleberry.com)"
25
+ ],
26
+ "type": "module",
27
+ "exports": "./dist/index.js",
28
+ "main": "./dist/index.js",
29
+ "typings": "./dist/index.d.ts",
30
+ "files": [
31
+ "dist/",
32
+ "changes.json",
33
+ "README.md"
34
+ ],
35
+ "scripts": {
36
+ "bench": "vitest bench",
37
+ "build": "ts-scripts build",
38
+ "format": "ts-scripts format",
39
+ "specs": "ts-scripts specs",
40
+ "test": "ts-scripts test"
41
+ },
42
+ "dependencies": {
43
+ "content-type": "^3.1.1"
44
+ },
45
+ "devDependencies": {
46
+ "@borderless/ts-scripts": "^0.15.0",
47
+ "@types/node": "^22.13.10",
48
+ "@vitest/coverage-v8": "^5.0.1",
49
+ "typescript": "^7.0.2",
50
+ "vitest": "^5.0.1"
51
+ },
52
+ "engines": {
53
+ "node": ">= 22"
54
+ },
55
+ "ts-scripts": {
56
+ "dist": [
57
+ "dist"
58
+ ],
59
+ "project": [
60
+ "tsconfig.build.json"
61
+ ]
62
+ },
55
63
  "depup": {
56
- "changes": {
57
- "mime-types": {
58
- "from": "^3.0.0",
59
- "to": "^3.0.2"
60
- }
61
- },
62
- "depsUpdated": 1,
64
+ "changes": {},
65
+ "depsUpdated": 0,
63
66
  "originalPackage": "type-is",
64
- "originalVersion": "2.0.1",
65
- "processedAt": "2026-03-19T03:02:27.156Z",
67
+ "originalVersion": "3.0.0",
68
+ "processedAt": "2026-09-27T01:04:22.945Z",
66
69
  "smokeTest": "passed"
67
70
  }
68
71
  }
package/HISTORY.md DELETED
@@ -1,292 +0,0 @@
1
- 2.0.1 / 2025-03-27
2
- ==========
3
-
4
- 2.0.0 / 2024-08-31
5
- ==========
6
-
7
- * Drop node <18
8
- * Use `content-type@^1.0.5` and `media-typer@^1.0.0` for type validation
9
- - No behavior changes, upgrades `media-typer`
10
- * deps: mime-types@^3.0.0
11
- - Add `application/toml` with extension `.toml`
12
- - Add `application/ubjson` with extension `.ubj`
13
- - Add `application/x-keepass2` with extension `.kdbx`
14
- - Add deprecated iWorks mime types and extensions
15
- - Add extension `.amr` to `audio/amr`
16
- - Add extension `.cjs` to `application/node`
17
- - Add extension `.dbf` to `application/vnd.dbf`
18
- - Add extension `.m4s` to `video/iso.segment`
19
- - Add extension `.mvt` to `application/vnd.mapbox-vector-tile`
20
- - Add extension `.mxmf` to `audio/mobile-xmf`
21
- - Add extension `.opus` to `audio/ogg`
22
- - Add extension `.rar` to `application/vnd.rar`
23
- - Add extension `.td` to `application/urc-targetdesc+xml`
24
- - Add extension `.trig` to `application/trig`
25
- - Add extensions from IANA for `application/*+xml` types
26
- - Add `image/avif` with extension `.avif`
27
- - Add `image/ktx2` with extension `.ktx2`
28
- - Add `image/vnd.ms-dds` with extension `.dds`
29
- - Add new upstream MIME types
30
- - Fix extension of `application/vnd.apple.keynote` to be `.key`
31
- - Remove ambigious extensions from IANA for `application/*+xml` types
32
- - Update primary extension to `.es` for `application/ecmascript`
33
-
34
- 1.6.18 / 2019-04-26
35
- ===================
36
-
37
- * Fix regression passing request object to `typeis.is`
38
-
39
- 1.6.17 / 2019-04-25
40
- ===================
41
-
42
- * deps: mime-types@~2.1.24
43
- - Add Apple file extensions from IANA
44
- - Add extension `.csl` to `application/vnd.citationstyles.style+xml`
45
- - Add extension `.es` to `application/ecmascript`
46
- - Add extension `.nq` to `application/n-quads`
47
- - Add extension `.nt` to `application/n-triples`
48
- - Add extension `.owl` to `application/rdf+xml`
49
- - Add extensions `.siv` and `.sieve` to `application/sieve`
50
- - Add extensions from IANA for `image/*` types
51
- - Add extensions from IANA for `model/*` types
52
- - Add extensions to HEIC image types
53
- - Add new mime types
54
- - Add `text/mdx` with extension `.mdx`
55
- * perf: prevent internal `throw` on invalid type
56
-
57
- 1.6.16 / 2018-02-16
58
- ===================
59
-
60
- * deps: mime-types@~2.1.18
61
- - Add `application/raml+yaml` with extension `.raml`
62
- - Add `application/wasm` with extension `.wasm`
63
- - Add `text/shex` with extension `.shex`
64
- - Add extensions for JPEG-2000 images
65
- - Add extensions from IANA for `message/*` types
66
- - Add extension `.mjs` to `application/javascript`
67
- - Add extension `.wadl` to `application/vnd.sun.wadl+xml`
68
- - Add extension `.gz` to `application/gzip`
69
- - Add glTF types and extensions
70
- - Add new mime types
71
- - Update extensions `.md` and `.markdown` to be `text/markdown`
72
- - Update font MIME types
73
- - Update `text/hjson` to registered `application/hjson`
74
-
75
- 1.6.15 / 2017-03-31
76
- ===================
77
-
78
- * deps: mime-types@~2.1.15
79
- - Add new mime types
80
-
81
- 1.6.14 / 2016-11-18
82
- ===================
83
-
84
- * deps: mime-types@~2.1.13
85
- - Add new mime types
86
-
87
- 1.6.13 / 2016-05-18
88
- ===================
89
-
90
- * deps: mime-types@~2.1.11
91
- - Add new mime types
92
-
93
- 1.6.12 / 2016-02-28
94
- ===================
95
-
96
- * deps: mime-types@~2.1.10
97
- - Add new mime types
98
- - Fix extension of `application/dash+xml`
99
- - Update primary extension for `audio/mp4`
100
-
101
- 1.6.11 / 2016-01-29
102
- ===================
103
-
104
- * deps: mime-types@~2.1.9
105
- - Add new mime types
106
-
107
- 1.6.10 / 2015-12-01
108
- ===================
109
-
110
- * deps: mime-types@~2.1.8
111
- - Add new mime types
112
-
113
- 1.6.9 / 2015-09-27
114
- ==================
115
-
116
- * deps: mime-types@~2.1.7
117
- - Add new mime types
118
-
119
- 1.6.8 / 2015-09-04
120
- ==================
121
-
122
- * deps: mime-types@~2.1.6
123
- - Add new mime types
124
-
125
- 1.6.7 / 2015-08-20
126
- ==================
127
-
128
- * Fix type error when given invalid type to match against
129
- * deps: mime-types@~2.1.5
130
- - Add new mime types
131
-
132
- 1.6.6 / 2015-07-31
133
- ==================
134
-
135
- * deps: mime-types@~2.1.4
136
- - Add new mime types
137
-
138
- 1.6.5 / 2015-07-16
139
- ==================
140
-
141
- * deps: mime-types@~2.1.3
142
- - Add new mime types
143
-
144
- 1.6.4 / 2015-07-01
145
- ==================
146
-
147
- * deps: mime-types@~2.1.2
148
- - Add new mime types
149
- * perf: enable strict mode
150
- * perf: remove argument reassignment
151
-
152
- 1.6.3 / 2015-06-08
153
- ==================
154
-
155
- * deps: mime-types@~2.1.1
156
- - Add new mime types
157
- * perf: reduce try block size
158
- * perf: remove bitwise operations
159
-
160
- 1.6.2 / 2015-05-10
161
- ==================
162
-
163
- * deps: mime-types@~2.0.11
164
- - Add new mime types
165
-
166
- 1.6.1 / 2015-03-13
167
- ==================
168
-
169
- * deps: mime-types@~2.0.10
170
- - Add new mime types
171
-
172
- 1.6.0 / 2015-02-12
173
- ==================
174
-
175
- * fix false-positives in `hasBody` `Transfer-Encoding` check
176
- * support wildcard for both type and subtype (`*/*`)
177
-
178
- 1.5.7 / 2015-02-09
179
- ==================
180
-
181
- * fix argument reassignment
182
- * deps: mime-types@~2.0.9
183
- - Add new mime types
184
-
185
- 1.5.6 / 2015-01-29
186
- ==================
187
-
188
- * deps: mime-types@~2.0.8
189
- - Add new mime types
190
-
191
- 1.5.5 / 2014-12-30
192
- ==================
193
-
194
- * deps: mime-types@~2.0.7
195
- - Add new mime types
196
- - Fix missing extensions
197
- - Fix various invalid MIME type entries
198
- - Remove example template MIME types
199
- - deps: mime-db@~1.5.0
200
-
201
- 1.5.4 / 2014-12-10
202
- ==================
203
-
204
- * deps: mime-types@~2.0.4
205
- - Add new mime types
206
- - deps: mime-db@~1.3.0
207
-
208
- 1.5.3 / 2014-11-09
209
- ==================
210
-
211
- * deps: mime-types@~2.0.3
212
- - Add new mime types
213
- - deps: mime-db@~1.2.0
214
-
215
- 1.5.2 / 2014-09-28
216
- ==================
217
-
218
- * deps: mime-types@~2.0.2
219
- - Add new mime types
220
- - deps: mime-db@~1.1.0
221
-
222
- 1.5.1 / 2014-09-07
223
- ==================
224
-
225
- * Support Node.js 0.6
226
- * deps: media-typer@0.3.0
227
- * deps: mime-types@~2.0.1
228
- - Support Node.js 0.6
229
-
230
- 1.5.0 / 2014-09-05
231
- ==================
232
-
233
- * fix `hasbody` to be true for `content-length: 0`
234
-
235
- 1.4.0 / 2014-09-02
236
- ==================
237
-
238
- * update mime-types
239
-
240
- 1.3.2 / 2014-06-24
241
- ==================
242
-
243
- * use `~` range on mime-types
244
-
245
- 1.3.1 / 2014-06-19
246
- ==================
247
-
248
- * fix global variable leak
249
-
250
- 1.3.0 / 2014-06-19
251
- ==================
252
-
253
- * improve type parsing
254
-
255
- - invalid media type never matches
256
- - media type not case-sensitive
257
- - extra LWS does not affect results
258
-
259
- 1.2.2 / 2014-06-19
260
- ==================
261
-
262
- * fix behavior on unknown type argument
263
-
264
- 1.2.1 / 2014-06-03
265
- ==================
266
-
267
- * switch dependency from `mime` to `mime-types@1.0.0`
268
-
269
- 1.2.0 / 2014-05-11
270
- ==================
271
-
272
- * support suffix matching:
273
-
274
- - `+json` matches `application/vnd+json`
275
- - `*/vnd+json` matches `application/vnd+json`
276
- - `application/*+json` matches `application/vnd+json`
277
-
278
- 1.1.0 / 2014-04-12
279
- ==================
280
-
281
- * add non-array values support
282
- * expose internal utilities:
283
-
284
- - `.is()`
285
- - `.hasBody()`
286
- - `.normalize()`
287
- - `.match()`
288
-
289
- 1.0.1 / 2014-03-30
290
- ==================
291
-
292
- * add `multipart` as a shorthand
package/index.js DELETED
@@ -1,250 +0,0 @@
1
- /*!
2
- * type-is
3
- * Copyright(c) 2014 Jonathan Ong
4
- * Copyright(c) 2014-2015 Douglas Christopher Wilson
5
- * MIT Licensed
6
- */
7
-
8
- 'use strict'
9
-
10
- /**
11
- * Module dependencies.
12
- * @private
13
- */
14
-
15
- var contentType = require('content-type')
16
- var mime = require('mime-types')
17
- var typer = require('media-typer')
18
-
19
- /**
20
- * Module exports.
21
- * @public
22
- */
23
-
24
- module.exports = typeofrequest
25
- module.exports.is = typeis
26
- module.exports.hasBody = hasbody
27
- module.exports.normalize = normalize
28
- module.exports.match = mimeMatch
29
-
30
- /**
31
- * Compare a `value` content-type with `types`.
32
- * Each `type` can be an extension like `html`,
33
- * a special shortcut like `multipart` or `urlencoded`,
34
- * or a mime type.
35
- *
36
- * If no types match, `false` is returned.
37
- * Otherwise, the first `type` that matches is returned.
38
- *
39
- * @param {String} value
40
- * @param {Array} types
41
- * @public
42
- */
43
-
44
- function typeis (value, types_) {
45
- var i
46
- var types = types_
47
-
48
- // remove parameters and normalize
49
- var val = tryNormalizeType(value)
50
-
51
- // no type or invalid
52
- if (!val) {
53
- return false
54
- }
55
-
56
- // support flattened arguments
57
- if (types && !Array.isArray(types)) {
58
- types = new Array(arguments.length - 1)
59
- for (i = 0; i < types.length; i++) {
60
- types[i] = arguments[i + 1]
61
- }
62
- }
63
-
64
- // no types, return the content type
65
- if (!types || !types.length) {
66
- return val
67
- }
68
-
69
- var type
70
- for (i = 0; i < types.length; i++) {
71
- if (mimeMatch(normalize(type = types[i]), val)) {
72
- return type[0] === '+' || type.indexOf('*') !== -1
73
- ? val
74
- : type
75
- }
76
- }
77
-
78
- // no matches
79
- return false
80
- }
81
-
82
- /**
83
- * Check if a request has a request body.
84
- * A request with a body __must__ either have `transfer-encoding`
85
- * or `content-length` headers set.
86
- * http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3
87
- *
88
- * @param {Object} request
89
- * @return {Boolean}
90
- * @public
91
- */
92
-
93
- function hasbody (req) {
94
- return req.headers['transfer-encoding'] !== undefined ||
95
- !isNaN(req.headers['content-length'])
96
- }
97
-
98
- /**
99
- * Check if the incoming request contains the "Content-Type"
100
- * header field, and it contains any of the give mime `type`s.
101
- * If there is no request body, `null` is returned.
102
- * If there is no content type, `false` is returned.
103
- * Otherwise, it returns the first `type` that matches.
104
- *
105
- * Examples:
106
- *
107
- * // With Content-Type: text/html; charset=utf-8
108
- * this.is('html'); // => 'html'
109
- * this.is('text/html'); // => 'text/html'
110
- * this.is('text/*', 'application/json'); // => 'text/html'
111
- *
112
- * // When Content-Type is application/json
113
- * this.is('json', 'urlencoded'); // => 'json'
114
- * this.is('application/json'); // => 'application/json'
115
- * this.is('html', 'application/*'); // => 'application/json'
116
- *
117
- * this.is('html'); // => false
118
- *
119
- * @param {Object} req
120
- * @param {(String|Array)} types...
121
- * @return {(String|false|null)}
122
- * @public
123
- */
124
-
125
- function typeofrequest (req, types_) {
126
- // no body
127
- if (!hasbody(req)) return null
128
- // support flattened arguments
129
- var types = arguments.length > 2
130
- ? Array.prototype.slice.call(arguments, 1)
131
- : types_
132
- // request content type
133
- var value = req.headers['content-type']
134
-
135
- return typeis(value, types)
136
- }
137
-
138
- /**
139
- * Normalize a mime type.
140
- * If it's a shorthand, expand it to a valid mime type.
141
- *
142
- * In general, you probably want:
143
- *
144
- * var type = is(req, ['urlencoded', 'json', 'multipart']);
145
- *
146
- * Then use the appropriate body parsers.
147
- * These three are the most common request body types
148
- * and are thus ensured to work.
149
- *
150
- * @param {String} type
151
- * @return {String|false|null}
152
- * @public
153
- */
154
-
155
- function normalize (type) {
156
- if (typeof type !== 'string') {
157
- // invalid type
158
- return false
159
- }
160
-
161
- switch (type) {
162
- case 'urlencoded':
163
- return 'application/x-www-form-urlencoded'
164
- case 'multipart':
165
- return 'multipart/*'
166
- }
167
-
168
- if (type[0] === '+') {
169
- // "+json" -> "*/*+json" expando
170
- return '*/*' + type
171
- }
172
-
173
- return type.indexOf('/') === -1
174
- ? mime.lookup(type)
175
- : type
176
- }
177
-
178
- /**
179
- * Check if `expected` mime type
180
- * matches `actual` mime type with
181
- * wildcard and +suffix support.
182
- *
183
- * @param {String} expected
184
- * @param {String} actual
185
- * @return {Boolean}
186
- * @public
187
- */
188
-
189
- function mimeMatch (expected, actual) {
190
- // invalid type
191
- if (expected === false) {
192
- return false
193
- }
194
-
195
- // split types
196
- var actualParts = actual.split('/')
197
- var expectedParts = expected.split('/')
198
-
199
- // invalid format
200
- if (actualParts.length !== 2 || expectedParts.length !== 2) {
201
- return false
202
- }
203
-
204
- // validate type
205
- if (expectedParts[0] !== '*' && expectedParts[0] !== actualParts[0]) {
206
- return false
207
- }
208
-
209
- // validate suffix wildcard
210
- if (expectedParts[1].slice(0, 2) === '*+') {
211
- return expectedParts[1].length <= actualParts[1].length + 1 &&
212
- expectedParts[1].slice(1) === actualParts[1].slice(1 - expectedParts[1].length)
213
- }
214
-
215
- // validate subtype
216
- if (expectedParts[1] !== '*' && expectedParts[1] !== actualParts[1]) {
217
- return false
218
- }
219
-
220
- return true
221
- }
222
-
223
- /**
224
- * Normalize a type and remove parameters.
225
- *
226
- * @param {string} value
227
- * @return {(string|null)}
228
- * @private
229
- */
230
- function normalizeType (value) {
231
- // Parse the type
232
- var type = contentType.parse(value).type
233
-
234
- return typer.test(type) ? type : null
235
- }
236
-
237
- /**
238
- * Try to normalize a type and remove parameters.
239
- *
240
- * @param {string} value
241
- * @return {(string|null)}
242
- * @private
243
- */
244
- function tryNormalizeType (value) {
245
- try {
246
- return value ? normalizeType(value) : null
247
- } catch (err) {
248
- return null
249
- }
250
- }