@comapeo/map-server 1.0.0-pre.0 → 1.0.0-pre.2

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 (146) hide show
  1. package/dist/context.d.ts +1 -1
  2. package/dist/context.js +1 -1
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +1 -0
  6. package/dist/lib/map-share.js +1 -1
  7. package/dist/routes/maps.js +1 -1
  8. package/dist/types.d.ts +5 -5
  9. package/dist/types.js +2 -2
  10. package/node_modules/@fastify/busboy/LICENSE +24 -0
  11. package/node_modules/@fastify/busboy/README.md +270 -0
  12. package/node_modules/@fastify/busboy/deps/dicer/LICENSE +19 -0
  13. package/node_modules/@fastify/busboy/deps/dicer/lib/Dicer.js +213 -0
  14. package/node_modules/@fastify/busboy/deps/dicer/lib/HeaderParser.js +100 -0
  15. package/node_modules/@fastify/busboy/deps/dicer/lib/PartStream.js +13 -0
  16. package/node_modules/@fastify/busboy/deps/dicer/lib/dicer.d.ts +164 -0
  17. package/node_modules/@fastify/busboy/deps/streamsearch/sbmh.js +230 -0
  18. package/node_modules/@fastify/busboy/lib/main.d.ts +196 -0
  19. package/node_modules/@fastify/busboy/lib/main.js +85 -0
  20. package/node_modules/@fastify/busboy/lib/types/multipart.js +306 -0
  21. package/node_modules/@fastify/busboy/lib/types/urlencoded.js +190 -0
  22. package/node_modules/@fastify/busboy/lib/utils/Decoder.js +54 -0
  23. package/node_modules/@fastify/busboy/lib/utils/basename.js +14 -0
  24. package/node_modules/@fastify/busboy/lib/utils/decodeText.js +114 -0
  25. package/node_modules/@fastify/busboy/lib/utils/getLimit.js +16 -0
  26. package/node_modules/@fastify/busboy/lib/utils/parseParams.js +201 -0
  27. package/node_modules/@fastify/busboy/package.json +81 -0
  28. package/node_modules/@whatwg-node/fetch/CHANGELOG.md +941 -0
  29. package/node_modules/@whatwg-node/fetch/README.md +141 -0
  30. package/node_modules/@whatwg-node/fetch/dist/create-node-ponyfill.js +100 -0
  31. package/node_modules/@whatwg-node/fetch/dist/esm-ponyfill.js +71 -0
  32. package/node_modules/@whatwg-node/fetch/dist/global-ponyfill.js +22 -0
  33. package/node_modules/@whatwg-node/fetch/dist/index.d.ts +73 -0
  34. package/node_modules/@whatwg-node/fetch/dist/node-ponyfill.js +35 -0
  35. package/node_modules/@whatwg-node/fetch/dist/shouldSkipPonyfill.js +17 -0
  36. package/node_modules/@whatwg-node/fetch/package.json +31 -0
  37. package/node_modules/@whatwg-node/node-fetch/cjs/AbortError.js +19 -0
  38. package/node_modules/@whatwg-node/node-fetch/cjs/Blob.js +291 -0
  39. package/node_modules/@whatwg-node/node-fetch/cjs/Body.js +529 -0
  40. package/node_modules/@whatwg-node/node-fetch/cjs/CompressionStream.js +34 -0
  41. package/node_modules/@whatwg-node/node-fetch/cjs/DecompressionStream.js +34 -0
  42. package/node_modules/@whatwg-node/node-fetch/cjs/File.js +15 -0
  43. package/node_modules/@whatwg-node/node-fetch/cjs/FormData.js +150 -0
  44. package/node_modules/@whatwg-node/node-fetch/cjs/Headers.js +309 -0
  45. package/node_modules/@whatwg-node/node-fetch/cjs/IteratorObject.js +134 -0
  46. package/node_modules/@whatwg-node/node-fetch/cjs/ReadableStream.js +245 -0
  47. package/node_modules/@whatwg-node/node-fetch/cjs/Request.js +128 -0
  48. package/node_modules/@whatwg-node/node-fetch/cjs/Response.js +108 -0
  49. package/node_modules/@whatwg-node/node-fetch/cjs/TextEncoderDecoder.js +49 -0
  50. package/node_modules/@whatwg-node/node-fetch/cjs/TextEncoderDecoderStream.js +40 -0
  51. package/node_modules/@whatwg-node/node-fetch/cjs/TransformStream.js +79 -0
  52. package/node_modules/@whatwg-node/node-fetch/cjs/URL.js +28 -0
  53. package/node_modules/@whatwg-node/node-fetch/cjs/URLSearchParams.js +4 -0
  54. package/node_modules/@whatwg-node/node-fetch/cjs/WritableStream.js +115 -0
  55. package/node_modules/@whatwg-node/node-fetch/cjs/fetch.js +107 -0
  56. package/node_modules/@whatwg-node/node-fetch/cjs/fetchCurl.js +142 -0
  57. package/node_modules/@whatwg-node/node-fetch/cjs/fetchNodeHttp.js +152 -0
  58. package/node_modules/@whatwg-node/node-fetch/cjs/index.js +42 -0
  59. package/node_modules/@whatwg-node/node-fetch/cjs/package.json +1 -0
  60. package/node_modules/@whatwg-node/node-fetch/cjs/utils.js +125 -0
  61. package/node_modules/@whatwg-node/node-fetch/esm/AbortError.js +15 -0
  62. package/node_modules/@whatwg-node/node-fetch/esm/Blob.js +279 -0
  63. package/node_modules/@whatwg-node/node-fetch/esm/Body.js +525 -0
  64. package/node_modules/@whatwg-node/node-fetch/esm/CompressionStream.js +29 -0
  65. package/node_modules/@whatwg-node/node-fetch/esm/DecompressionStream.js +29 -0
  66. package/node_modules/@whatwg-node/node-fetch/esm/File.js +11 -0
  67. package/node_modules/@whatwg-node/node-fetch/esm/FormData.js +145 -0
  68. package/node_modules/@whatwg-node/node-fetch/esm/Headers.js +304 -0
  69. package/node_modules/@whatwg-node/node-fetch/esm/IteratorObject.js +130 -0
  70. package/node_modules/@whatwg-node/node-fetch/esm/ReadableStream.js +241 -0
  71. package/node_modules/@whatwg-node/node-fetch/esm/Request.js +124 -0
  72. package/node_modules/@whatwg-node/node-fetch/esm/Response.js +104 -0
  73. package/node_modules/@whatwg-node/node-fetch/esm/TextEncoderDecoder.js +43 -0
  74. package/node_modules/@whatwg-node/node-fetch/esm/TextEncoderDecoderStream.js +35 -0
  75. package/node_modules/@whatwg-node/node-fetch/esm/TransformStream.js +75 -0
  76. package/node_modules/@whatwg-node/node-fetch/esm/URL.js +24 -0
  77. package/node_modules/@whatwg-node/node-fetch/esm/URLSearchParams.js +1 -0
  78. package/node_modules/@whatwg-node/node-fetch/esm/WritableStream.js +111 -0
  79. package/node_modules/@whatwg-node/node-fetch/esm/fetch.js +104 -0
  80. package/node_modules/@whatwg-node/node-fetch/esm/fetchCurl.js +139 -0
  81. package/node_modules/@whatwg-node/node-fetch/esm/fetchNodeHttp.js +148 -0
  82. package/node_modules/@whatwg-node/node-fetch/esm/index.js +18 -0
  83. package/node_modules/@whatwg-node/node-fetch/esm/utils.js +110 -0
  84. package/node_modules/@whatwg-node/node-fetch/package.json +46 -0
  85. package/node_modules/@whatwg-node/node-fetch/typings/AbortError.d.cts +4 -0
  86. package/node_modules/@whatwg-node/node-fetch/typings/AbortError.d.ts +4 -0
  87. package/node_modules/@whatwg-node/node-fetch/typings/Blob.d.cts +63 -0
  88. package/node_modules/@whatwg-node/node-fetch/typings/Blob.d.ts +63 -0
  89. package/node_modules/@whatwg-node/node-fetch/typings/Body.d.cts +54 -0
  90. package/node_modules/@whatwg-node/node-fetch/typings/Body.d.ts +54 -0
  91. package/node_modules/@whatwg-node/node-fetch/typings/CompressionStream.d.cts +6 -0
  92. package/node_modules/@whatwg-node/node-fetch/typings/CompressionStream.d.ts +6 -0
  93. package/node_modules/@whatwg-node/node-fetch/typings/DecompressionStream.d.cts +6 -0
  94. package/node_modules/@whatwg-node/node-fetch/typings/DecompressionStream.d.ts +6 -0
  95. package/node_modules/@whatwg-node/node-fetch/typings/File.d.cts +7 -0
  96. package/node_modules/@whatwg-node/node-fetch/typings/File.d.ts +7 -0
  97. package/node_modules/@whatwg-node/node-fetch/typings/FormData.d.cts +22 -0
  98. package/node_modules/@whatwg-node/node-fetch/typings/FormData.d.ts +22 -0
  99. package/node_modules/@whatwg-node/node-fetch/typings/Headers.d.cts +26 -0
  100. package/node_modules/@whatwg-node/node-fetch/typings/Headers.d.ts +26 -0
  101. package/node_modules/@whatwg-node/node-fetch/typings/IteratorObject.d.cts +20 -0
  102. package/node_modules/@whatwg-node/node-fetch/typings/IteratorObject.d.ts +20 -0
  103. package/node_modules/@whatwg-node/node-fetch/typings/ReadableStream.d.cts +27 -0
  104. package/node_modules/@whatwg-node/node-fetch/typings/ReadableStream.d.ts +27 -0
  105. package/node_modules/@whatwg-node/node-fetch/typings/Request.d.cts +38 -0
  106. package/node_modules/@whatwg-node/node-fetch/typings/Request.d.ts +38 -0
  107. package/node_modules/@whatwg-node/node-fetch/typings/Response.d.cts +23 -0
  108. package/node_modules/@whatwg-node/node-fetch/typings/Response.d.ts +23 -0
  109. package/node_modules/@whatwg-node/node-fetch/typings/TextEncoderDecoder.d.cts +15 -0
  110. package/node_modules/@whatwg-node/node-fetch/typings/TextEncoderDecoder.d.ts +15 -0
  111. package/node_modules/@whatwg-node/node-fetch/typings/TextEncoderDecoderStream.d.cts +14 -0
  112. package/node_modules/@whatwg-node/node-fetch/typings/TextEncoderDecoderStream.d.ts +14 -0
  113. package/node_modules/@whatwg-node/node-fetch/typings/TransformStream.d.cts +9 -0
  114. package/node_modules/@whatwg-node/node-fetch/typings/TransformStream.d.ts +9 -0
  115. package/node_modules/@whatwg-node/node-fetch/typings/URL.d.cts +16 -0
  116. package/node_modules/@whatwg-node/node-fetch/typings/URL.d.ts +16 -0
  117. package/node_modules/@whatwg-node/node-fetch/typings/URLSearchParams.d.cts +4 -0
  118. package/node_modules/@whatwg-node/node-fetch/typings/URLSearchParams.d.ts +4 -0
  119. package/node_modules/@whatwg-node/node-fetch/typings/WritableStream.d.cts +9 -0
  120. package/node_modules/@whatwg-node/node-fetch/typings/WritableStream.d.ts +9 -0
  121. package/node_modules/@whatwg-node/node-fetch/typings/fetch.d.cts +3 -0
  122. package/node_modules/@whatwg-node/node-fetch/typings/fetch.d.ts +3 -0
  123. package/node_modules/@whatwg-node/node-fetch/typings/fetchCurl.d.cts +3 -0
  124. package/node_modules/@whatwg-node/node-fetch/typings/fetchCurl.d.ts +3 -0
  125. package/node_modules/@whatwg-node/node-fetch/typings/fetchNodeHttp.d.cts +3 -0
  126. package/node_modules/@whatwg-node/node-fetch/typings/fetchNodeHttp.d.ts +3 -0
  127. package/node_modules/@whatwg-node/node-fetch/typings/index.d.cts +18 -0
  128. package/node_modules/@whatwg-node/node-fetch/typings/index.d.ts +18 -0
  129. package/node_modules/@whatwg-node/node-fetch/typings/utils.d.cts +21 -0
  130. package/node_modules/@whatwg-node/node-fetch/typings/utils.d.ts +21 -0
  131. package/node_modules/@whatwg-node/server/package.json +2 -1
  132. package/node_modules/urlpattern-polyfill/LICENSE +19 -0
  133. package/node_modules/urlpattern-polyfill/README.md +242 -0
  134. package/node_modules/urlpattern-polyfill/dist/index.d.ts +9 -0
  135. package/node_modules/urlpattern-polyfill/dist/types.d.ts +49 -0
  136. package/node_modules/urlpattern-polyfill/dist/urlpattern.cjs +1 -0
  137. package/node_modules/urlpattern-polyfill/dist/urlpattern.js +1 -0
  138. package/node_modules/urlpattern-polyfill/index.cjs +7 -0
  139. package/node_modules/urlpattern-polyfill/index.js +7 -0
  140. package/node_modules/urlpattern-polyfill/package.json +149 -0
  141. package/package.json +18 -8
  142. package/src/context.ts +1 -1
  143. package/src/index.ts +2 -0
  144. package/src/lib/map-share.ts +1 -1
  145. package/src/routes/maps.ts +1 -1
  146. package/src/types.ts +2 -2
@@ -0,0 +1,196 @@
1
+ // Definitions by: Jacob Baskin <https://github.com/jacobbaskin>
2
+ // BendingBender <https://github.com/BendingBender>
3
+ // Igor Savin <https://github.com/kibertoad>
4
+
5
+ /// <reference types="node" />
6
+
7
+ import * as http from 'node:http';
8
+ import { Readable, Writable } from 'node:stream';
9
+ export { Dicer } from "../deps/dicer/lib/dicer";
10
+
11
+ export const Busboy: BusboyConstructor;
12
+ export default Busboy;
13
+
14
+ export interface BusboyConfig {
15
+ /**
16
+ * These are the HTTP headers of the incoming request, which are used by individual parsers.
17
+ */
18
+ headers: BusboyHeaders;
19
+ /**
20
+ * `highWaterMark` to use for this Busboy instance.
21
+ * @default WritableStream default.
22
+ */
23
+ highWaterMark?: number | undefined;
24
+ /**
25
+ * highWaterMark to use for file streams.
26
+ * @default ReadableStream default.
27
+ */
28
+ fileHwm?: number | undefined;
29
+ /**
30
+ * Default character set to use when one isn't defined.
31
+ * @default 'utf8'
32
+ */
33
+ defCharset?: string | undefined;
34
+ /**
35
+ * Detect if a Part is a file.
36
+ *
37
+ * By default a file is detected if contentType
38
+ * is application/octet-stream or fileName is not
39
+ * undefined.
40
+ *
41
+ * Modify this to handle e.g. Blobs.
42
+ */
43
+ isPartAFile?: (fieldName: string | undefined, contentType: string | undefined, fileName: string | undefined) => boolean;
44
+ /**
45
+ * If paths in the multipart 'filename' field shall be preserved.
46
+ * @default false
47
+ */
48
+ preservePath?: boolean | undefined;
49
+ /**
50
+ * Various limits on incoming data.
51
+ */
52
+ limits?:
53
+ | {
54
+ /**
55
+ * Max field name size (in bytes)
56
+ * @default 100 bytes
57
+ */
58
+ fieldNameSize?: number | undefined;
59
+ /**
60
+ * Max field value size (in bytes)
61
+ * @default 1MB
62
+ */
63
+ fieldSize?: number | undefined;
64
+ /**
65
+ * Max number of non-file fields
66
+ * @default Infinity
67
+ */
68
+ fields?: number | undefined;
69
+ /**
70
+ * For multipart forms, the max file size (in bytes)
71
+ * @default Infinity
72
+ */
73
+ fileSize?: number | undefined;
74
+ /**
75
+ * For multipart forms, the max number of file fields
76
+ * @default Infinity
77
+ */
78
+ files?: number | undefined;
79
+ /**
80
+ * For multipart forms, the max number of parts (fields + files)
81
+ * @default Infinity
82
+ */
83
+ parts?: number | undefined;
84
+ /**
85
+ * For multipart forms, the max number of header key=>value pairs to parse
86
+ * @default 2000
87
+ */
88
+ headerPairs?: number | undefined;
89
+
90
+ /**
91
+ * For multipart forms, the max size of a header part
92
+ * @default 81920
93
+ */
94
+ headerSize?: number | undefined;
95
+ }
96
+ | undefined;
97
+ }
98
+
99
+ export type BusboyHeaders = { 'content-type': string } & http.IncomingHttpHeaders;
100
+
101
+ export interface BusboyFileStream extends
102
+ Readable {
103
+
104
+ truncated: boolean;
105
+
106
+ /**
107
+ * The number of bytes that have been read so far.
108
+ */
109
+ bytesRead: number;
110
+ }
111
+
112
+ export interface Busboy extends Writable {
113
+ addListener<Event extends keyof BusboyEvents>(event: Event, listener: BusboyEvents[Event]): this;
114
+
115
+ addListener(event: string | symbol, listener: (...args: any[]) => void): this;
116
+
117
+ on<Event extends keyof BusboyEvents>(event: Event, listener: BusboyEvents[Event]): this;
118
+
119
+ on(event: string | symbol, listener: (...args: any[]) => void): this;
120
+
121
+ once<Event extends keyof BusboyEvents>(event: Event, listener: BusboyEvents[Event]): this;
122
+
123
+ once(event: string | symbol, listener: (...args: any[]) => void): this;
124
+
125
+ removeListener<Event extends keyof BusboyEvents>(event: Event, listener: BusboyEvents[Event]): this;
126
+
127
+ removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
128
+
129
+ off<Event extends keyof BusboyEvents>(event: Event, listener: BusboyEvents[Event]): this;
130
+
131
+ off(event: string | symbol, listener: (...args: any[]) => void): this;
132
+
133
+ prependListener<Event extends keyof BusboyEvents>(event: Event, listener: BusboyEvents[Event]): this;
134
+
135
+ prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
136
+
137
+ prependOnceListener<Event extends keyof BusboyEvents>(event: Event, listener: BusboyEvents[Event]): this;
138
+
139
+ prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
140
+ }
141
+
142
+ export interface BusboyEvents {
143
+ /**
144
+ * Emitted for each new file form field found.
145
+ *
146
+ * * Note: if you listen for this event, you should always handle the `stream` no matter if you care about the
147
+ * file contents or not (e.g. you can simply just do `stream.resume();` if you want to discard the contents),
148
+ * otherwise the 'finish' event will never fire on the Busboy instance. However, if you don't care about **any**
149
+ * incoming files, you can simply not listen for the 'file' event at all and any/all files will be automatically
150
+ * and safely discarded (these discarded files do still count towards `files` and `parts` limits).
151
+ * * If a configured file size limit was reached, `stream` will both have a boolean property `truncated`
152
+ * (best checked at the end of the stream) and emit a 'limit' event to notify you when this happens.
153
+ *
154
+ * @param listener.transferEncoding Contains the 'Content-Transfer-Encoding' value for the file stream.
155
+ * @param listener.mimeType Contains the 'Content-Type' value for the file stream.
156
+ */
157
+ file: (
158
+ fieldname: string,
159
+ stream: BusboyFileStream,
160
+ filename: string,
161
+ transferEncoding: string,
162
+ mimeType: string,
163
+ ) => void;
164
+ /**
165
+ * Emitted for each new non-file field found.
166
+ */
167
+ field: (
168
+ fieldname: string,
169
+ value: string,
170
+ fieldnameTruncated: boolean,
171
+ valueTruncated: boolean,
172
+ transferEncoding: string,
173
+ mimeType: string,
174
+ ) => void;
175
+ finish: () => void;
176
+ /**
177
+ * Emitted when specified `parts` limit has been reached. No more 'file' or 'field' events will be emitted.
178
+ */
179
+ partsLimit: () => void;
180
+ /**
181
+ * Emitted when specified `files` limit has been reached. No more 'file' events will be emitted.
182
+ */
183
+ filesLimit: () => void;
184
+ /**
185
+ * Emitted when specified `fields` limit has been reached. No more 'field' events will be emitted.
186
+ */
187
+ fieldsLimit: () => void;
188
+ error: (error: unknown) => void;
189
+ }
190
+
191
+ export interface BusboyConstructor {
192
+ (options: BusboyConfig): Busboy;
193
+
194
+ new(options: BusboyConfig): Busboy;
195
+ }
196
+
@@ -0,0 +1,85 @@
1
+ 'use strict'
2
+
3
+ const WritableStream = require('node:stream').Writable
4
+ const { inherits } = require('node:util')
5
+ const Dicer = require('../deps/dicer/lib/Dicer')
6
+
7
+ const MultipartParser = require('./types/multipart')
8
+ const UrlencodedParser = require('./types/urlencoded')
9
+ const parseParams = require('./utils/parseParams')
10
+
11
+ function Busboy (opts) {
12
+ if (!(this instanceof Busboy)) { return new Busboy(opts) }
13
+
14
+ if (typeof opts !== 'object') {
15
+ throw new TypeError('Busboy expected an options-Object.')
16
+ }
17
+ if (typeof opts.headers !== 'object') {
18
+ throw new TypeError('Busboy expected an options-Object with headers-attribute.')
19
+ }
20
+ if (typeof opts.headers['content-type'] !== 'string') {
21
+ throw new TypeError('Missing Content-Type-header.')
22
+ }
23
+
24
+ const {
25
+ headers,
26
+ ...streamOptions
27
+ } = opts
28
+
29
+ this.opts = {
30
+ autoDestroy: false,
31
+ ...streamOptions
32
+ }
33
+ WritableStream.call(this, this.opts)
34
+
35
+ this._done = false
36
+ this._parser = this.getParserByHeaders(headers)
37
+ this._finished = false
38
+ }
39
+ inherits(Busboy, WritableStream)
40
+
41
+ Busboy.prototype.emit = function (ev) {
42
+ if (ev === 'finish') {
43
+ if (!this._done) {
44
+ this._parser?.end()
45
+ return
46
+ } else if (this._finished) {
47
+ return
48
+ }
49
+ this._finished = true
50
+ }
51
+ WritableStream.prototype.emit.apply(this, arguments)
52
+ }
53
+
54
+ Busboy.prototype.getParserByHeaders = function (headers) {
55
+ const parsed = parseParams(headers['content-type'])
56
+
57
+ const cfg = {
58
+ defCharset: this.opts.defCharset,
59
+ fileHwm: this.opts.fileHwm,
60
+ headers,
61
+ highWaterMark: this.opts.highWaterMark,
62
+ isPartAFile: this.opts.isPartAFile,
63
+ limits: this.opts.limits,
64
+ parsedConType: parsed,
65
+ preservePath: this.opts.preservePath
66
+ }
67
+
68
+ if (MultipartParser.detect.test(parsed[0])) {
69
+ return new MultipartParser(this, cfg)
70
+ }
71
+ if (UrlencodedParser.detect.test(parsed[0])) {
72
+ return new UrlencodedParser(this, cfg)
73
+ }
74
+ throw new Error('Unsupported Content-Type.')
75
+ }
76
+
77
+ Busboy.prototype._write = function (chunk, encoding, cb) {
78
+ this._parser.write(chunk, cb)
79
+ }
80
+
81
+ module.exports = Busboy
82
+ module.exports.default = Busboy
83
+ module.exports.Busboy = Busboy
84
+
85
+ module.exports.Dicer = Dicer
@@ -0,0 +1,306 @@
1
+ 'use strict'
2
+
3
+ // TODO:
4
+ // * support 1 nested multipart level
5
+ // (see second multipart example here:
6
+ // http://www.w3.org/TR/html401/interact/forms.html#didx-multipartform-data)
7
+ // * support limits.fieldNameSize
8
+ // -- this will require modifications to utils.parseParams
9
+
10
+ const { Readable } = require('node:stream')
11
+ const { inherits } = require('node:util')
12
+
13
+ const Dicer = require('../../deps/dicer/lib/Dicer')
14
+
15
+ const parseParams = require('../utils/parseParams')
16
+ const decodeText = require('../utils/decodeText')
17
+ const basename = require('../utils/basename')
18
+ const getLimit = require('../utils/getLimit')
19
+
20
+ const RE_BOUNDARY = /^boundary$/i
21
+ const RE_FIELD = /^form-data$/i
22
+ const RE_CHARSET = /^charset$/i
23
+ const RE_FILENAME = /^filename$/i
24
+ const RE_NAME = /^name$/i
25
+
26
+ Multipart.detect = /^multipart\/form-data/i
27
+ function Multipart (boy, cfg) {
28
+ let i
29
+ let len
30
+ const self = this
31
+ let boundary
32
+ const limits = cfg.limits
33
+ const isPartAFile = cfg.isPartAFile || ((fieldName, contentType, fileName) => (contentType === 'application/octet-stream' || fileName !== undefined))
34
+ const parsedConType = cfg.parsedConType || []
35
+ const defCharset = cfg.defCharset || 'utf8'
36
+ const preservePath = cfg.preservePath
37
+ const fileOpts = { highWaterMark: cfg.fileHwm }
38
+
39
+ for (i = 0, len = parsedConType.length; i < len; ++i) {
40
+ if (Array.isArray(parsedConType[i]) &&
41
+ RE_BOUNDARY.test(parsedConType[i][0])) {
42
+ boundary = parsedConType[i][1]
43
+ break
44
+ }
45
+ }
46
+
47
+ function checkFinished () {
48
+ if (nends === 0 && finished && !boy._done) {
49
+ finished = false
50
+ self.end()
51
+ }
52
+ }
53
+
54
+ if (typeof boundary !== 'string') { throw new Error('Multipart: Boundary not found') }
55
+
56
+ const fieldSizeLimit = getLimit(limits, 'fieldSize', 1 * 1024 * 1024)
57
+ const fileSizeLimit = getLimit(limits, 'fileSize', Infinity)
58
+ const filesLimit = getLimit(limits, 'files', Infinity)
59
+ const fieldsLimit = getLimit(limits, 'fields', Infinity)
60
+ const partsLimit = getLimit(limits, 'parts', Infinity)
61
+ const headerPairsLimit = getLimit(limits, 'headerPairs', 2000)
62
+ const headerSizeLimit = getLimit(limits, 'headerSize', 80 * 1024)
63
+
64
+ let nfiles = 0
65
+ let nfields = 0
66
+ let nends = 0
67
+ let curFile
68
+ let curField
69
+ let finished = false
70
+
71
+ this._needDrain = false
72
+ this._pause = false
73
+ this._cb = undefined
74
+ this._nparts = 0
75
+ this._boy = boy
76
+
77
+ const parserCfg = {
78
+ boundary,
79
+ maxHeaderPairs: headerPairsLimit,
80
+ maxHeaderSize: headerSizeLimit,
81
+ partHwm: fileOpts.highWaterMark,
82
+ highWaterMark: cfg.highWaterMark
83
+ }
84
+
85
+ this.parser = new Dicer(parserCfg)
86
+ this.parser.on('drain', function () {
87
+ self._needDrain = false
88
+ if (self._cb && !self._pause) {
89
+ const cb = self._cb
90
+ self._cb = undefined
91
+ cb()
92
+ }
93
+ }).on('part', function onPart (part) {
94
+ if (++self._nparts > partsLimit) {
95
+ self.parser.removeListener('part', onPart)
96
+ self.parser.on('part', skipPart)
97
+ boy.hitPartsLimit = true
98
+ boy.emit('partsLimit')
99
+ return skipPart(part)
100
+ }
101
+
102
+ // hack because streams2 _always_ doesn't emit 'end' until nextTick, so let
103
+ // us emit 'end' early since we know the part has ended if we are already
104
+ // seeing the next part
105
+ if (curField) {
106
+ const field = curField
107
+ field.emit('end')
108
+ field.removeAllListeners('end')
109
+ }
110
+
111
+ part.on('header', function (header) {
112
+ let contype
113
+ let fieldname
114
+ let parsed
115
+ let charset
116
+ let encoding
117
+ let filename
118
+ let nsize = 0
119
+
120
+ if (header['content-type']) {
121
+ parsed = parseParams(header['content-type'][0])
122
+ if (parsed[0]) {
123
+ contype = parsed[0].toLowerCase()
124
+ for (i = 0, len = parsed.length; i < len; ++i) {
125
+ if (RE_CHARSET.test(parsed[i][0])) {
126
+ charset = parsed[i][1].toLowerCase()
127
+ break
128
+ }
129
+ }
130
+ }
131
+ }
132
+
133
+ if (contype === undefined) { contype = 'text/plain' }
134
+ if (charset === undefined) { charset = defCharset }
135
+
136
+ if (header['content-disposition']) {
137
+ parsed = parseParams(header['content-disposition'][0])
138
+ if (!RE_FIELD.test(parsed[0])) { return skipPart(part) }
139
+ for (i = 0, len = parsed.length; i < len; ++i) {
140
+ if (RE_NAME.test(parsed[i][0])) {
141
+ fieldname = parsed[i][1]
142
+ } else if (RE_FILENAME.test(parsed[i][0])) {
143
+ filename = parsed[i][1]
144
+ if (!preservePath) { filename = basename(filename) }
145
+ }
146
+ }
147
+ } else { return skipPart(part) }
148
+
149
+ if (header['content-transfer-encoding']) { encoding = header['content-transfer-encoding'][0].toLowerCase() } else { encoding = '7bit' }
150
+
151
+ let onData,
152
+ onEnd
153
+
154
+ if (isPartAFile(fieldname, contype, filename)) {
155
+ // file/binary field
156
+ if (nfiles === filesLimit) {
157
+ if (!boy.hitFilesLimit) {
158
+ boy.hitFilesLimit = true
159
+ boy.emit('filesLimit')
160
+ }
161
+ return skipPart(part)
162
+ }
163
+
164
+ ++nfiles
165
+
166
+ if (boy.listenerCount('file') === 0) {
167
+ self.parser._ignore()
168
+ return
169
+ }
170
+
171
+ ++nends
172
+ const file = new FileStream(fileOpts)
173
+ curFile = file
174
+ file.on('end', function () {
175
+ --nends
176
+ self._pause = false
177
+ checkFinished()
178
+ if (self._cb && !self._needDrain) {
179
+ const cb = self._cb
180
+ self._cb = undefined
181
+ cb()
182
+ }
183
+ })
184
+ file._read = function (n) {
185
+ if (!self._pause) { return }
186
+ self._pause = false
187
+ if (self._cb && !self._needDrain) {
188
+ const cb = self._cb
189
+ self._cb = undefined
190
+ cb()
191
+ }
192
+ }
193
+ boy.emit('file', fieldname, file, filename, encoding, contype)
194
+
195
+ onData = function (data) {
196
+ if ((nsize += data.length) > fileSizeLimit) {
197
+ const extralen = fileSizeLimit - nsize + data.length
198
+ if (extralen > 0) { file.push(data.slice(0, extralen)) }
199
+ file.truncated = true
200
+ file.bytesRead = fileSizeLimit
201
+ part.removeAllListeners('data')
202
+ file.emit('limit')
203
+ return
204
+ } else if (!file.push(data)) { self._pause = true }
205
+
206
+ file.bytesRead = nsize
207
+ }
208
+
209
+ onEnd = function () {
210
+ curFile = undefined
211
+ file.push(null)
212
+ }
213
+ } else {
214
+ // non-file field
215
+ if (nfields === fieldsLimit) {
216
+ if (!boy.hitFieldsLimit) {
217
+ boy.hitFieldsLimit = true
218
+ boy.emit('fieldsLimit')
219
+ }
220
+ return skipPart(part)
221
+ }
222
+
223
+ ++nfields
224
+ ++nends
225
+ let buffer = ''
226
+ let truncated = false
227
+ curField = part
228
+
229
+ onData = function (data) {
230
+ if ((nsize += data.length) > fieldSizeLimit) {
231
+ const extralen = (fieldSizeLimit - (nsize - data.length))
232
+ buffer += data.toString('binary', 0, extralen)
233
+ truncated = true
234
+ part.removeAllListeners('data')
235
+ } else { buffer += data.toString('binary') }
236
+ }
237
+
238
+ onEnd = function () {
239
+ curField = undefined
240
+ if (buffer.length) { buffer = decodeText(buffer, 'binary', charset) }
241
+ boy.emit('field', fieldname, buffer, false, truncated, encoding, contype)
242
+ --nends
243
+ checkFinished()
244
+ }
245
+ }
246
+
247
+ /* As of node@2efe4ab761666 (v0.10.29+/v0.11.14+), busboy had become
248
+ broken. Streams2/streams3 is a huge black box of confusion, but
249
+ somehow overriding the sync state seems to fix things again (and still
250
+ seems to work for previous node versions).
251
+ */
252
+ part._readableState.sync = false
253
+
254
+ part.on('data', onData)
255
+ part.on('end', onEnd)
256
+ }).on('error', function (err) {
257
+ if (curFile) { curFile.emit('error', err) }
258
+ })
259
+ }).on('error', function (err) {
260
+ boy.emit('error', err)
261
+ }).on('finish', function () {
262
+ finished = true
263
+ checkFinished()
264
+ })
265
+ }
266
+
267
+ Multipart.prototype.write = function (chunk, cb) {
268
+ const r = this.parser.write(chunk)
269
+ if (r && !this._pause) {
270
+ cb()
271
+ } else {
272
+ this._needDrain = !r
273
+ this._cb = cb
274
+ }
275
+ }
276
+
277
+ Multipart.prototype.end = function () {
278
+ const self = this
279
+
280
+ if (self.parser.writable) {
281
+ self.parser.end()
282
+ } else if (!self._boy._done) {
283
+ process.nextTick(function () {
284
+ self._boy._done = true
285
+ self._boy.emit('finish')
286
+ })
287
+ }
288
+ }
289
+
290
+ function skipPart (part) {
291
+ part.resume()
292
+ }
293
+
294
+ function FileStream (opts) {
295
+ Readable.call(this, opts)
296
+
297
+ this.bytesRead = 0
298
+
299
+ this.truncated = false
300
+ }
301
+
302
+ inherits(FileStream, Readable)
303
+
304
+ FileStream.prototype._read = function (n) {}
305
+
306
+ module.exports = Multipart