@nocobase/plugin-field-sort 1.5.0-alpha.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 (142) hide show
  1. package/LICENSE.txt +159 -0
  2. package/README.md +1 -0
  3. package/client.d.ts +2 -0
  4. package/client.js +1 -0
  5. package/dist/client/index.d.ts +15 -0
  6. package/dist/client/index.js +10 -0
  7. package/dist/client/locale.d.ts +10 -0
  8. package/dist/client/sort-interface.d.ts +131 -0
  9. package/dist/externalVersion.js +18 -0
  10. package/dist/index.d.ts +10 -0
  11. package/dist/index.js +48 -0
  12. package/dist/locale/en-US.json +1 -0
  13. package/dist/locale/zh-CN.json +1 -0
  14. package/dist/node_modules/@nocobase/lock-manager/LICENSE +661 -0
  15. package/dist/node_modules/@nocobase/lock-manager/lib/index.d.ts +10 -0
  16. package/dist/node_modules/@nocobase/lock-manager/lib/index.js +1 -0
  17. package/dist/node_modules/@nocobase/lock-manager/lib/lock-manager.d.ts +46 -0
  18. package/dist/node_modules/@nocobase/lock-manager/lib/lock-manager.js +171 -0
  19. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/client.js +12 -0
  20. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/assign.d.ts +17 -0
  21. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/assign.js +143 -0
  22. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/client.d.ts +30 -0
  23. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/client.js +88 -0
  24. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/collections-graph.d.ts +24 -0
  25. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/collections-graph.js +107 -0
  26. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/common.d.ts +14 -0
  27. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/common.js +87 -0
  28. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/date.d.ts +38 -0
  29. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/date.js +214 -0
  30. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/dayjs.d.ts +10 -0
  31. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/dayjs.js +72 -0
  32. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/forEach.d.ts +9 -0
  33. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/forEach.js +45 -0
  34. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/fs-exists.d.ts +9 -0
  35. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/fs-exists.js +46 -0
  36. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/getValuesByPath.d.ts +9 -0
  37. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/getValuesByPath.js +71 -0
  38. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/handlebars.d.ts +10 -0
  39. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/handlebars.js +73 -0
  40. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/i18n.d.ts +10 -0
  41. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/i18n.js +43 -0
  42. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/index.d.ts +38 -0
  43. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/index.js +105 -0
  44. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/isPortalInBody.d.ts +13 -0
  45. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/isPortalInBody.js +54 -0
  46. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/isValidFilter.d.ts +9 -0
  47. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/isValidFilter.js +63 -0
  48. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/json-templates.d.ts +9 -0
  49. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/json-templates.js +141 -0
  50. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/koa-multer.d.ts +15 -0
  51. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/koa-multer.js +92 -0
  52. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/log.d.ts +9 -0
  53. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/log.js +39 -0
  54. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/measure-execution-time.d.ts +9 -0
  55. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/measure-execution-time.js +44 -0
  56. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/merge.d.ts +9 -0
  57. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/merge.js +55 -0
  58. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/mixin/AsyncEmitter.d.ts +11 -0
  59. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/mixin/AsyncEmitter.js +80 -0
  60. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/mixin/index.d.ts +9 -0
  61. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/mixin/index.js +48 -0
  62. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/notification.d.ts +9 -0
  63. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/notification.js +43 -0
  64. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/number.d.ts +9 -0
  65. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/number.js +45 -0
  66. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/parse-date.d.ts +15 -0
  67. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/parse-date.js +262 -0
  68. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/parse-filter.d.ts +67 -0
  69. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/parse-filter.js +320 -0
  70. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/parseHTML.d.ts +15 -0
  71. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/parseHTML.js +42 -0
  72. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/perf-hooks.d.ts +14 -0
  73. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/perf-hooks.js +69 -0
  74. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/registry.d.ts +22 -0
  75. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/registry.js +69 -0
  76. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/requireModule.d.ts +12 -0
  77. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/requireModule.js +90 -0
  78. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/server.d.ts +19 -0
  79. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/server.js +50 -0
  80. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/toposort.d.ts +18 -0
  81. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/toposort.js +83 -0
  82. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/uid.d.ts +9 -0
  83. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/uid.js +44 -0
  84. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/url.d.ts +14 -0
  85. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/url.js +46 -0
  86. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/wrap-middleware.d.ts +1 -0
  87. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/lib/wrap-middleware.js +63 -0
  88. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/package.json +20 -0
  89. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/plugin-symlink.d.ts +6 -0
  90. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/plugin-symlink.js +102 -0
  91. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/server.d.ts +2 -0
  92. package/dist/node_modules/@nocobase/lock-manager/node_modules/@nocobase/utils/server.js +12 -0
  93. package/dist/node_modules/@nocobase/lock-manager/node_modules/busboy/.eslintrc.js +5 -0
  94. package/dist/node_modules/@nocobase/lock-manager/node_modules/busboy/.github/workflows/ci.yml +24 -0
  95. package/dist/node_modules/@nocobase/lock-manager/node_modules/busboy/.github/workflows/lint.yml +23 -0
  96. package/dist/node_modules/@nocobase/lock-manager/node_modules/busboy/bench/bench-multipart-fields-100mb-big.js +149 -0
  97. package/dist/node_modules/@nocobase/lock-manager/node_modules/busboy/bench/bench-multipart-fields-100mb-small.js +143 -0
  98. package/dist/node_modules/@nocobase/lock-manager/node_modules/busboy/bench/bench-multipart-files-100mb-big.js +154 -0
  99. package/dist/node_modules/@nocobase/lock-manager/node_modules/busboy/bench/bench-multipart-files-100mb-small.js +148 -0
  100. package/dist/node_modules/@nocobase/lock-manager/node_modules/busboy/bench/bench-urlencoded-fields-100pairs-small.js +101 -0
  101. package/dist/node_modules/@nocobase/lock-manager/node_modules/busboy/bench/bench-urlencoded-fields-900pairs-small-alt.js +84 -0
  102. package/dist/node_modules/@nocobase/lock-manager/node_modules/busboy/lib/index.js +57 -0
  103. package/dist/node_modules/@nocobase/lock-manager/node_modules/busboy/lib/types/multipart.js +653 -0
  104. package/dist/node_modules/@nocobase/lock-manager/node_modules/busboy/lib/types/urlencoded.js +350 -0
  105. package/dist/node_modules/@nocobase/lock-manager/node_modules/busboy/lib/utils.js +596 -0
  106. package/dist/node_modules/@nocobase/lock-manager/node_modules/busboy/package.json +22 -0
  107. package/dist/node_modules/@nocobase/lock-manager/node_modules/busboy/test/common.js +109 -0
  108. package/dist/node_modules/@nocobase/lock-manager/node_modules/busboy/test/test-types-multipart-charsets.js +94 -0
  109. package/dist/node_modules/@nocobase/lock-manager/node_modules/busboy/test/test-types-multipart-stream-pause.js +102 -0
  110. package/dist/node_modules/@nocobase/lock-manager/node_modules/busboy/test/test-types-multipart.js +1053 -0
  111. package/dist/node_modules/@nocobase/lock-manager/node_modules/busboy/test/test-types-urlencoded.js +488 -0
  112. package/dist/node_modules/@nocobase/lock-manager/node_modules/busboy/test/test.js +20 -0
  113. package/dist/node_modules/@nocobase/lock-manager/node_modules/multer/index.js +104 -0
  114. package/dist/node_modules/@nocobase/lock-manager/node_modules/multer/lib/counter.js +28 -0
  115. package/dist/node_modules/@nocobase/lock-manager/node_modules/multer/lib/file-appender.js +67 -0
  116. package/dist/node_modules/@nocobase/lock-manager/node_modules/multer/lib/make-middleware.js +173 -0
  117. package/dist/node_modules/@nocobase/lock-manager/node_modules/multer/lib/multer-error.js +24 -0
  118. package/dist/node_modules/@nocobase/lock-manager/node_modules/multer/lib/remove-uploaded-files.js +28 -0
  119. package/dist/node_modules/@nocobase/lock-manager/node_modules/multer/package.json +52 -0
  120. package/dist/node_modules/@nocobase/lock-manager/node_modules/multer/storage/disk.js +66 -0
  121. package/dist/node_modules/@nocobase/lock-manager/node_modules/multer/storage/memory.js +21 -0
  122. package/dist/node_modules/@nocobase/lock-manager/node_modules/streamsearch/.eslintrc.js +5 -0
  123. package/dist/node_modules/@nocobase/lock-manager/node_modules/streamsearch/.github/workflows/ci.yml +24 -0
  124. package/dist/node_modules/@nocobase/lock-manager/node_modules/streamsearch/.github/workflows/lint.yml +23 -0
  125. package/dist/node_modules/@nocobase/lock-manager/node_modules/streamsearch/lib/sbmh.js +267 -0
  126. package/dist/node_modules/@nocobase/lock-manager/node_modules/streamsearch/package.json +34 -0
  127. package/dist/node_modules/@nocobase/lock-manager/node_modules/streamsearch/test/test.js +70 -0
  128. package/dist/node_modules/@nocobase/lock-manager/package.json +1 -0
  129. package/dist/node_modules/@nocobase/lock-manager/src/__tests__/lock-manager.test.ts +169 -0
  130. package/dist/node_modules/@nocobase/lock-manager/src/index.ts +11 -0
  131. package/dist/node_modules/@nocobase/lock-manager/src/lock-manager.ts +169 -0
  132. package/dist/server/action.d.ts +26 -0
  133. package/dist/server/action.js +168 -0
  134. package/dist/server/index.d.ts +10 -0
  135. package/dist/server/index.js +48 -0
  136. package/dist/server/plugin.d.ts +19 -0
  137. package/dist/server/plugin.js +69 -0
  138. package/dist/server/sort-field.d.ts +24 -0
  139. package/dist/server/sort-field.js +197 -0
  140. package/package.json +16 -0
  141. package/server.d.ts +2 -0
  142. package/server.js +1 -0
@@ -0,0 +1,488 @@
1
+ 'use strict';
2
+
3
+ const assert = require('assert');
4
+ const { transcode } = require('buffer');
5
+ const { inspect } = require('util');
6
+
7
+ const busboy = require('..');
8
+
9
+ const active = new Map();
10
+
11
+ const tests = [
12
+ { source: ['foo'],
13
+ expected: [
14
+ ['foo',
15
+ '',
16
+ { nameTruncated: false,
17
+ valueTruncated: false,
18
+ encoding: 'utf-8',
19
+ mimeType: 'text/plain' },
20
+ ],
21
+ ],
22
+ what: 'Unassigned value'
23
+ },
24
+ { source: ['foo=bar'],
25
+ expected: [
26
+ ['foo',
27
+ 'bar',
28
+ { nameTruncated: false,
29
+ valueTruncated: false,
30
+ encoding: 'utf-8',
31
+ mimeType: 'text/plain' },
32
+ ],
33
+ ],
34
+ what: 'Assigned value'
35
+ },
36
+ { source: ['foo&bar=baz'],
37
+ expected: [
38
+ ['foo',
39
+ '',
40
+ { nameTruncated: false,
41
+ valueTruncated: false,
42
+ encoding: 'utf-8',
43
+ mimeType: 'text/plain' },
44
+ ],
45
+ ['bar',
46
+ 'baz',
47
+ { nameTruncated: false,
48
+ valueTruncated: false,
49
+ encoding: 'utf-8',
50
+ mimeType: 'text/plain' },
51
+ ],
52
+ ],
53
+ what: 'Unassigned and assigned value'
54
+ },
55
+ { source: ['foo=bar&baz'],
56
+ expected: [
57
+ ['foo',
58
+ 'bar',
59
+ { nameTruncated: false,
60
+ valueTruncated: false,
61
+ encoding: 'utf-8',
62
+ mimeType: 'text/plain' },
63
+ ],
64
+ ['baz',
65
+ '',
66
+ { nameTruncated: false,
67
+ valueTruncated: false,
68
+ encoding: 'utf-8',
69
+ mimeType: 'text/plain' },
70
+ ],
71
+ ],
72
+ what: 'Assigned and unassigned value'
73
+ },
74
+ { source: ['foo=bar&baz=bla'],
75
+ expected: [
76
+ ['foo',
77
+ 'bar',
78
+ { nameTruncated: false,
79
+ valueTruncated: false,
80
+ encoding: 'utf-8',
81
+ mimeType: 'text/plain' },
82
+ ],
83
+ ['baz',
84
+ 'bla',
85
+ { nameTruncated: false,
86
+ valueTruncated: false,
87
+ encoding: 'utf-8',
88
+ mimeType: 'text/plain' },
89
+ ],
90
+ ],
91
+ what: 'Two assigned values'
92
+ },
93
+ { source: ['foo&bar'],
94
+ expected: [
95
+ ['foo',
96
+ '',
97
+ { nameTruncated: false,
98
+ valueTruncated: false,
99
+ encoding: 'utf-8',
100
+ mimeType: 'text/plain' },
101
+ ],
102
+ ['bar',
103
+ '',
104
+ { nameTruncated: false,
105
+ valueTruncated: false,
106
+ encoding: 'utf-8',
107
+ mimeType: 'text/plain' },
108
+ ],
109
+ ],
110
+ what: 'Two unassigned values'
111
+ },
112
+ { source: ['foo&bar&'],
113
+ expected: [
114
+ ['foo',
115
+ '',
116
+ { nameTruncated: false,
117
+ valueTruncated: false,
118
+ encoding: 'utf-8',
119
+ mimeType: 'text/plain' },
120
+ ],
121
+ ['bar',
122
+ '',
123
+ { nameTruncated: false,
124
+ valueTruncated: false,
125
+ encoding: 'utf-8',
126
+ mimeType: 'text/plain' },
127
+ ],
128
+ ],
129
+ what: 'Two unassigned values and ampersand'
130
+ },
131
+ { source: ['foo+1=bar+baz%2Bquux'],
132
+ expected: [
133
+ ['foo 1',
134
+ 'bar baz+quux',
135
+ { nameTruncated: false,
136
+ valueTruncated: false,
137
+ encoding: 'utf-8',
138
+ mimeType: 'text/plain' },
139
+ ],
140
+ ],
141
+ what: 'Assigned key and value with (plus) space'
142
+ },
143
+ { source: ['foo=bar%20baz%21'],
144
+ expected: [
145
+ ['foo',
146
+ 'bar baz!',
147
+ { nameTruncated: false,
148
+ valueTruncated: false,
149
+ encoding: 'utf-8',
150
+ mimeType: 'text/plain' },
151
+ ],
152
+ ],
153
+ what: 'Assigned value with encoded bytes'
154
+ },
155
+ { source: ['foo%20bar=baz%20bla%21'],
156
+ expected: [
157
+ ['foo bar',
158
+ 'baz bla!',
159
+ { nameTruncated: false,
160
+ valueTruncated: false,
161
+ encoding: 'utf-8',
162
+ mimeType: 'text/plain' },
163
+ ],
164
+ ],
165
+ what: 'Assigned value with encoded bytes #2'
166
+ },
167
+ { source: ['foo=bar%20baz%21&num=1000'],
168
+ expected: [
169
+ ['foo',
170
+ 'bar baz!',
171
+ { nameTruncated: false,
172
+ valueTruncated: false,
173
+ encoding: 'utf-8',
174
+ mimeType: 'text/plain' },
175
+ ],
176
+ ['num',
177
+ '1000',
178
+ { nameTruncated: false,
179
+ valueTruncated: false,
180
+ encoding: 'utf-8',
181
+ mimeType: 'text/plain' },
182
+ ],
183
+ ],
184
+ what: 'Two assigned values, one with encoded bytes'
185
+ },
186
+ { source: [
187
+ Array.from(transcode(Buffer.from('foo'), 'utf8', 'utf16le')).map(
188
+ (n) => `%${n.toString(16).padStart(2, '0')}`
189
+ ).join(''),
190
+ '=',
191
+ Array.from(transcode(Buffer.from('😀!'), 'utf8', 'utf16le')).map(
192
+ (n) => `%${n.toString(16).padStart(2, '0')}`
193
+ ).join(''),
194
+ ],
195
+ expected: [
196
+ ['foo',
197
+ '😀!',
198
+ { nameTruncated: false,
199
+ valueTruncated: false,
200
+ encoding: 'UTF-16LE',
201
+ mimeType: 'text/plain' },
202
+ ],
203
+ ],
204
+ charset: 'UTF-16LE',
205
+ what: 'Encoded value with multi-byte charset'
206
+ },
207
+ { source: [
208
+ 'foo=<',
209
+ Array.from(transcode(Buffer.from('©:^þ'), 'utf8', 'latin1')).map(
210
+ (n) => `%${n.toString(16).padStart(2, '0')}`
211
+ ).join(''),
212
+ ],
213
+ expected: [
214
+ ['foo',
215
+ '<©:^þ',
216
+ { nameTruncated: false,
217
+ valueTruncated: false,
218
+ encoding: 'ISO-8859-1',
219
+ mimeType: 'text/plain' },
220
+ ],
221
+ ],
222
+ charset: 'ISO-8859-1',
223
+ what: 'Encoded value with single-byte, ASCII-compatible, non-UTF8 charset'
224
+ },
225
+ { source: ['foo=bar&baz=bla'],
226
+ expected: [],
227
+ what: 'Limits: zero fields',
228
+ limits: { fields: 0 }
229
+ },
230
+ { source: ['foo=bar&baz=bla'],
231
+ expected: [
232
+ ['foo',
233
+ 'bar',
234
+ { nameTruncated: false,
235
+ valueTruncated: false,
236
+ encoding: 'utf-8',
237
+ mimeType: 'text/plain' },
238
+ ],
239
+ ],
240
+ what: 'Limits: one field',
241
+ limits: { fields: 1 }
242
+ },
243
+ { source: ['foo=bar&baz=bla'],
244
+ expected: [
245
+ ['foo',
246
+ 'bar',
247
+ { nameTruncated: false,
248
+ valueTruncated: false,
249
+ encoding: 'utf-8',
250
+ mimeType: 'text/plain' },
251
+ ],
252
+ ['baz',
253
+ 'bla',
254
+ { nameTruncated: false,
255
+ valueTruncated: false,
256
+ encoding: 'utf-8',
257
+ mimeType: 'text/plain' },
258
+ ],
259
+ ],
260
+ what: 'Limits: field part lengths match limits',
261
+ limits: { fieldNameSize: 3, fieldSize: 3 }
262
+ },
263
+ { source: ['foo=bar&baz=bla'],
264
+ expected: [
265
+ ['fo',
266
+ 'bar',
267
+ { nameTruncated: true,
268
+ valueTruncated: false,
269
+ encoding: 'utf-8',
270
+ mimeType: 'text/plain' },
271
+ ],
272
+ ['ba',
273
+ 'bla',
274
+ { nameTruncated: true,
275
+ valueTruncated: false,
276
+ encoding: 'utf-8',
277
+ mimeType: 'text/plain' },
278
+ ],
279
+ ],
280
+ what: 'Limits: truncated field name',
281
+ limits: { fieldNameSize: 2 }
282
+ },
283
+ { source: ['foo=bar&baz=bla'],
284
+ expected: [
285
+ ['foo',
286
+ 'ba',
287
+ { nameTruncated: false,
288
+ valueTruncated: true,
289
+ encoding: 'utf-8',
290
+ mimeType: 'text/plain' },
291
+ ],
292
+ ['baz',
293
+ 'bl',
294
+ { nameTruncated: false,
295
+ valueTruncated: true,
296
+ encoding: 'utf-8',
297
+ mimeType: 'text/plain' },
298
+ ],
299
+ ],
300
+ what: 'Limits: truncated field value',
301
+ limits: { fieldSize: 2 }
302
+ },
303
+ { source: ['foo=bar&baz=bla'],
304
+ expected: [
305
+ ['fo',
306
+ 'ba',
307
+ { nameTruncated: true,
308
+ valueTruncated: true,
309
+ encoding: 'utf-8',
310
+ mimeType: 'text/plain' },
311
+ ],
312
+ ['ba',
313
+ 'bl',
314
+ { nameTruncated: true,
315
+ valueTruncated: true,
316
+ encoding: 'utf-8',
317
+ mimeType: 'text/plain' },
318
+ ],
319
+ ],
320
+ what: 'Limits: truncated field name and value',
321
+ limits: { fieldNameSize: 2, fieldSize: 2 }
322
+ },
323
+ { source: ['foo=bar&baz=bla'],
324
+ expected: [
325
+ ['fo',
326
+ '',
327
+ { nameTruncated: true,
328
+ valueTruncated: true,
329
+ encoding: 'utf-8',
330
+ mimeType: 'text/plain' },
331
+ ],
332
+ ['ba',
333
+ '',
334
+ { nameTruncated: true,
335
+ valueTruncated: true,
336
+ encoding: 'utf-8',
337
+ mimeType: 'text/plain' },
338
+ ],
339
+ ],
340
+ what: 'Limits: truncated field name and zero value limit',
341
+ limits: { fieldNameSize: 2, fieldSize: 0 }
342
+ },
343
+ { source: ['foo=bar&baz=bla'],
344
+ expected: [
345
+ ['',
346
+ '',
347
+ { nameTruncated: true,
348
+ valueTruncated: true,
349
+ encoding: 'utf-8',
350
+ mimeType: 'text/plain' },
351
+ ],
352
+ ['',
353
+ '',
354
+ { nameTruncated: true,
355
+ valueTruncated: true,
356
+ encoding: 'utf-8',
357
+ mimeType: 'text/plain' },
358
+ ],
359
+ ],
360
+ what: 'Limits: truncated zero field name and zero value limit',
361
+ limits: { fieldNameSize: 0, fieldSize: 0 }
362
+ },
363
+ { source: ['&'],
364
+ expected: [],
365
+ what: 'Ampersand'
366
+ },
367
+ { source: ['&&&&&'],
368
+ expected: [],
369
+ what: 'Many ampersands'
370
+ },
371
+ { source: ['='],
372
+ expected: [
373
+ ['',
374
+ '',
375
+ { nameTruncated: false,
376
+ valueTruncated: false,
377
+ encoding: 'utf-8',
378
+ mimeType: 'text/plain' },
379
+ ],
380
+ ],
381
+ what: 'Assigned value, empty name and value'
382
+ },
383
+ { source: [''],
384
+ expected: [],
385
+ what: 'Nothing'
386
+ },
387
+ ];
388
+
389
+ for (const test of tests) {
390
+ active.set(test, 1);
391
+
392
+ const { what } = test;
393
+ const charset = test.charset || 'utf-8';
394
+ const bb = busboy({
395
+ limits: test.limits,
396
+ headers: {
397
+ 'content-type': `application/x-www-form-urlencoded; charset=${charset}`,
398
+ },
399
+ });
400
+ const results = [];
401
+
402
+ bb.on('field', (key, val, info) => {
403
+ results.push([key, val, info]);
404
+ });
405
+
406
+ bb.on('file', () => {
407
+ throw new Error(`[${what}] Unexpected file`);
408
+ });
409
+
410
+ bb.on('close', () => {
411
+ active.delete(test);
412
+
413
+ assert.deepStrictEqual(
414
+ results,
415
+ test.expected,
416
+ `[${what}] Results mismatch.\n`
417
+ + `Parsed: ${inspect(results)}\n`
418
+ + `Expected: ${inspect(test.expected)}`
419
+ );
420
+ });
421
+
422
+ for (const src of test.source) {
423
+ const buf = (typeof src === 'string' ? Buffer.from(src, 'utf8') : src);
424
+ bb.write(buf);
425
+ }
426
+ bb.end();
427
+ }
428
+
429
+ // Byte-by-byte versions
430
+ for (let test of tests) {
431
+ test = { ...test };
432
+ test.what += ' (byte-by-byte)';
433
+ active.set(test, 1);
434
+
435
+ const { what } = test;
436
+ const charset = test.charset || 'utf-8';
437
+ const bb = busboy({
438
+ limits: test.limits,
439
+ headers: {
440
+ 'content-type': `application/x-www-form-urlencoded; charset="${charset}"`,
441
+ },
442
+ });
443
+ const results = [];
444
+
445
+ bb.on('field', (key, val, info) => {
446
+ results.push([key, val, info]);
447
+ });
448
+
449
+ bb.on('file', () => {
450
+ throw new Error(`[${what}] Unexpected file`);
451
+ });
452
+
453
+ bb.on('close', () => {
454
+ active.delete(test);
455
+
456
+ assert.deepStrictEqual(
457
+ results,
458
+ test.expected,
459
+ `[${what}] Results mismatch.\n`
460
+ + `Parsed: ${inspect(results)}\n`
461
+ + `Expected: ${inspect(test.expected)}`
462
+ );
463
+ });
464
+
465
+ for (const src of test.source) {
466
+ const buf = (typeof src === 'string' ? Buffer.from(src, 'utf8') : src);
467
+ for (let i = 0; i < buf.length; ++i)
468
+ bb.write(buf.slice(i, i + 1));
469
+ }
470
+ bb.end();
471
+ }
472
+
473
+ {
474
+ let exception = false;
475
+ process.once('uncaughtException', (ex) => {
476
+ exception = true;
477
+ throw ex;
478
+ });
479
+ process.on('exit', () => {
480
+ if (exception || active.size === 0)
481
+ return;
482
+ process.exitCode = 1;
483
+ console.error('==========================');
484
+ console.error(`${active.size} test(s) did not finish:`);
485
+ console.error('==========================');
486
+ console.error(Array.from(active.keys()).map((v) => v.what).join('\n'));
487
+ });
488
+ }
@@ -0,0 +1,20 @@
1
+ 'use strict';
2
+
3
+ const { spawnSync } = require('child_process');
4
+ const { readdirSync } = require('fs');
5
+ const { join } = require('path');
6
+
7
+ const files = readdirSync(__dirname).sort();
8
+ for (const filename of files) {
9
+ if (filename.startsWith('test-')) {
10
+ const path = join(__dirname, filename);
11
+ console.log(`> Running ${filename} ...`);
12
+ const result = spawnSync(`${process.argv0} ${path}`, {
13
+ shell: true,
14
+ stdio: 'inherit',
15
+ windowsHide: true
16
+ });
17
+ if (result.status !== 0)
18
+ process.exitCode = 1;
19
+ }
20
+ }
@@ -0,0 +1,104 @@
1
+ var makeMiddleware = require('./lib/make-middleware')
2
+
3
+ var diskStorage = require('./storage/disk')
4
+ var memoryStorage = require('./storage/memory')
5
+ var MulterError = require('./lib/multer-error')
6
+
7
+ function allowAll (req, file, cb) {
8
+ cb(null, true)
9
+ }
10
+
11
+ function Multer (options) {
12
+ if (options.storage) {
13
+ this.storage = options.storage
14
+ } else if (options.dest) {
15
+ this.storage = diskStorage({ destination: options.dest })
16
+ } else {
17
+ this.storage = memoryStorage()
18
+ }
19
+
20
+ this.limits = options.limits
21
+ this.preservePath = options.preservePath
22
+ this.fileFilter = options.fileFilter || allowAll
23
+ }
24
+
25
+ Multer.prototype._makeMiddleware = function (fields, fileStrategy) {
26
+ function setup () {
27
+ var fileFilter = this.fileFilter
28
+ var filesLeft = Object.create(null)
29
+
30
+ fields.forEach(function (field) {
31
+ if (typeof field.maxCount === 'number') {
32
+ filesLeft[field.name] = field.maxCount
33
+ } else {
34
+ filesLeft[field.name] = Infinity
35
+ }
36
+ })
37
+
38
+ function wrappedFileFilter (req, file, cb) {
39
+ if ((filesLeft[file.fieldname] || 0) <= 0) {
40
+ return cb(new MulterError('LIMIT_UNEXPECTED_FILE', file.fieldname))
41
+ }
42
+
43
+ filesLeft[file.fieldname] -= 1
44
+ fileFilter(req, file, cb)
45
+ }
46
+
47
+ return {
48
+ limits: this.limits,
49
+ preservePath: this.preservePath,
50
+ storage: this.storage,
51
+ fileFilter: wrappedFileFilter,
52
+ fileStrategy: fileStrategy
53
+ }
54
+ }
55
+
56
+ return makeMiddleware(setup.bind(this))
57
+ }
58
+
59
+ Multer.prototype.single = function (name) {
60
+ return this._makeMiddleware([{ name: name, maxCount: 1 }], 'VALUE')
61
+ }
62
+
63
+ Multer.prototype.array = function (name, maxCount) {
64
+ return this._makeMiddleware([{ name: name, maxCount: maxCount }], 'ARRAY')
65
+ }
66
+
67
+ Multer.prototype.fields = function (fields) {
68
+ return this._makeMiddleware(fields, 'OBJECT')
69
+ }
70
+
71
+ Multer.prototype.none = function () {
72
+ return this._makeMiddleware([], 'NONE')
73
+ }
74
+
75
+ Multer.prototype.any = function () {
76
+ function setup () {
77
+ return {
78
+ limits: this.limits,
79
+ preservePath: this.preservePath,
80
+ storage: this.storage,
81
+ fileFilter: this.fileFilter,
82
+ fileStrategy: 'ARRAY'
83
+ }
84
+ }
85
+
86
+ return makeMiddleware(setup.bind(this))
87
+ }
88
+
89
+ function multer (options) {
90
+ if (options === undefined) {
91
+ return new Multer({})
92
+ }
93
+
94
+ if (typeof options === 'object' && options !== null) {
95
+ return new Multer(options)
96
+ }
97
+
98
+ throw new TypeError('Expected object for argument options')
99
+ }
100
+
101
+ module.exports = multer
102
+ module.exports.diskStorage = diskStorage
103
+ module.exports.memoryStorage = memoryStorage
104
+ module.exports.MulterError = MulterError
@@ -0,0 +1,28 @@
1
+ var EventEmitter = require('events').EventEmitter
2
+
3
+ function Counter () {
4
+ EventEmitter.call(this)
5
+ this.value = 0
6
+ }
7
+
8
+ Counter.prototype = Object.create(EventEmitter.prototype)
9
+
10
+ Counter.prototype.increment = function increment () {
11
+ this.value++
12
+ }
13
+
14
+ Counter.prototype.decrement = function decrement () {
15
+ if (--this.value === 0) this.emit('zero')
16
+ }
17
+
18
+ Counter.prototype.isZero = function isZero () {
19
+ return (this.value === 0)
20
+ }
21
+
22
+ Counter.prototype.onceZero = function onceZero (fn) {
23
+ if (this.isZero()) return fn()
24
+
25
+ this.once('zero', fn)
26
+ }
27
+
28
+ module.exports = Counter
@@ -0,0 +1,67 @@
1
+ var objectAssign = require('object-assign')
2
+
3
+ function arrayRemove (arr, item) {
4
+ var idx = arr.indexOf(item)
5
+ if (~idx) arr.splice(idx, 1)
6
+ }
7
+
8
+ function FileAppender (strategy, req) {
9
+ this.strategy = strategy
10
+ this.req = req
11
+
12
+ switch (strategy) {
13
+ case 'NONE': break
14
+ case 'VALUE': break
15
+ case 'ARRAY': req.files = []; break
16
+ case 'OBJECT': req.files = Object.create(null); break
17
+ default: throw new Error('Unknown file strategy: ' + strategy)
18
+ }
19
+ }
20
+
21
+ FileAppender.prototype.insertPlaceholder = function (file) {
22
+ var placeholder = {
23
+ fieldname: file.fieldname
24
+ }
25
+
26
+ switch (this.strategy) {
27
+ case 'NONE': break
28
+ case 'VALUE': break
29
+ case 'ARRAY': this.req.files.push(placeholder); break
30
+ case 'OBJECT':
31
+ if (this.req.files[file.fieldname]) {
32
+ this.req.files[file.fieldname].push(placeholder)
33
+ } else {
34
+ this.req.files[file.fieldname] = [placeholder]
35
+ }
36
+ break
37
+ }
38
+
39
+ return placeholder
40
+ }
41
+
42
+ FileAppender.prototype.removePlaceholder = function (placeholder) {
43
+ switch (this.strategy) {
44
+ case 'NONE': break
45
+ case 'VALUE': break
46
+ case 'ARRAY': arrayRemove(this.req.files, placeholder); break
47
+ case 'OBJECT':
48
+ if (this.req.files[placeholder.fieldname].length === 1) {
49
+ delete this.req.files[placeholder.fieldname]
50
+ } else {
51
+ arrayRemove(this.req.files[placeholder.fieldname], placeholder)
52
+ }
53
+ break
54
+ }
55
+ }
56
+
57
+ FileAppender.prototype.replacePlaceholder = function (placeholder, file) {
58
+ if (this.strategy === 'VALUE') {
59
+ this.req.file = file
60
+ return
61
+ }
62
+
63
+ delete placeholder.fieldname
64
+ objectAssign(placeholder, file)
65
+ }
66
+
67
+ module.exports = FileAppender