webhoster 0.3.7 → 0.3.8

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
@@ -31,6 +31,10 @@ By default, the framework does nothing. It parses no headers. It writes no heade
31
31
 
32
32
  For now, take a look at [/test/index.js](/test/index.js)
33
33
 
34
+ ## Docs
35
+
36
+ Start at [docs/README.md](./docs/README.md) for the documentation index.
37
+
34
38
  ## Core
35
39
 
36
40
  ### [HttpHandler.js](/lib/HttpHandler.js)
@@ -70,9 +70,12 @@ async function parseFormUrlEncoded(request) {
70
70
  const CONTENT_READER = {
71
71
  type: 'application',
72
72
  subtype: 'x-www-form-urlencoded',
73
- parse: async (/** @type {HttpRequest} */ request) => Object.fromEntries(
74
- await parseFormUrlEncoded(request),
75
- ),
73
+ /** @this {HttpRequest} */
74
+ parse: async function parse() {
75
+ return Object.fromEntries(
76
+ await parseFormUrlEncoded(this),
77
+ );
78
+ },
76
79
  };
77
80
 
78
81
  /**
package/package.json CHANGED
@@ -18,7 +18,9 @@
18
18
  "eslint-plugin-canonical": "^4.18.1",
19
19
  "eslint-plugin-jsdoc": "^46.10.1",
20
20
  "eslint-plugin-n": "^16.6.2",
21
- "eslint-plugin-unicorn": "^48.0.1"
21
+ "eslint-plugin-unicorn": "^48.0.1",
22
+ "rimraf": "^4.4.1",
23
+ "typescript": "^5.9.3"
22
24
  },
23
25
  "engines": {
24
26
  "node": ">v16.13"
@@ -26,11 +28,10 @@
26
28
  "exports": {
27
29
  "./data/*": "./data/*",
28
30
  "./errata/*": "./errata/*",
29
- "./examples/*": "./examples/*",
30
31
  "./helpers/*": "./helpers/*",
31
32
  "./lib/*": "./lib/*",
32
33
  "./middleware/*": "./middleware/*",
33
- "./polyfills/*": "./polyfills/*",
34
+ "./polyfill/*": "./polyfill/*",
34
35
  "./templates/*": "./templates/*",
35
36
  "./types/*": "./types/*",
36
37
  "./utils/*": "./utils/*"
@@ -52,7 +53,7 @@
52
53
  "helpers",
53
54
  "lib",
54
55
  "middleware",
55
- "polyfills",
56
+ "polyfill",
56
57
  "templates",
57
58
  "types",
58
59
  "utils"
@@ -70,6 +71,14 @@
70
71
  "testall": "scripts/test-all.sh",
71
72
  "posttestall": "c8 report"
72
73
  },
74
+ "repository": {
75
+ "type": "git",
76
+ "url": "git+https://github.com/clshortfuse/webhoster.git"
77
+ },
78
+ "bugs": {
79
+ "url": "https://github.com/clshortfuse/webhoster/issues"
80
+ },
81
+ "homepage": "https://github.com/clshortfuse/webhoster#readme",
73
82
  "type": "module",
74
83
  "typesVersions": {
75
84
  "*": {
@@ -78,5 +87,5 @@
78
87
  ]
79
88
  }
80
89
  },
81
- "version": "0.3.7"
82
- }
90
+ "version": "0.3.8"
91
+ }
@@ -0,0 +1,164 @@
1
+ /* @see https://xhr.spec.whatwg.org/#dom-formdata */
2
+
3
+ /** @implements {FormData} */
4
+ export default class FormData {
5
+ /** @type {Map<string, (string|File)[]>} */
6
+ #list = new Map();
7
+
8
+ /** @param {HTMLFormElement} [form] */
9
+ constructor(form) {
10
+ if (form) {
11
+ throw new Error('InvalidStateError');
12
+ }
13
+ }
14
+
15
+ /**
16
+ * @param {string} s
17
+ * @return {string}
18
+ */
19
+ static #scalarValue = String;
20
+
21
+ /**
22
+ * @param {string} name
23
+ * @param {string|Blob} value
24
+ * @param {string} [filename]
25
+ * @return {{name:string, value:string|File}}
26
+ */
27
+ static #createEntry(name, value, filename) {
28
+ if (typeof value === 'string') {
29
+ return {
30
+ name: FormData.#scalarValue(name),
31
+ value: FormData.#scalarValue(value),
32
+ };
33
+ }
34
+
35
+ if (typeof File === 'undefined') {
36
+ if (!('name' in value) && !('lastModified' in value)) {
37
+ // eslint-disable-next-line unicorn/prefer-spread
38
+ const file = /** @type {File} */ (Object.defineProperties(value.slice(), {
39
+ name: {
40
+ value: filename === undefined ? 'blob' : filename,
41
+ },
42
+ lastModified: {
43
+ value: Date.now(),
44
+ },
45
+ webkitRelativePath: { value: '' },
46
+ toString: { value: () => '[object File]' },
47
+ }));
48
+ return {
49
+ name: FormData.#scalarValue(name),
50
+ value: file,
51
+ };
52
+ }
53
+ return {
54
+ name: FormData.#scalarValue(name),
55
+ // eslint-disable-next-line object-shorthand
56
+ value: /** @type {File} */ (value),
57
+ };
58
+ }
59
+ if (value instanceof File) {
60
+ return {
61
+ name: FormData.#scalarValue(name),
62
+ value,
63
+ };
64
+ }
65
+ return {
66
+ name: FormData.#scalarValue(name),
67
+ value: new File([value], filename === undefined ? 'blob' : filename, {}),
68
+ };
69
+ }
70
+
71
+ /**
72
+ * @param {string} name
73
+ * @param {string|Blob} value
74
+ * @param {string} [filename]
75
+ * @return {void}
76
+ */
77
+ append(name, value, filename) {
78
+ const entry = FormData.#createEntry(name, value, filename);
79
+ if (this.#list.has(entry.name)) {
80
+ this.#list.get(entry.name).push(entry.value);
81
+ } else {
82
+ this.#list.set(name, [entry.value]);
83
+ }
84
+ }
85
+
86
+ /**
87
+ * @param {string} name
88
+ * @return {void}
89
+ */
90
+ delete(name) {
91
+ this.#list.delete(name);
92
+ }
93
+
94
+ /**
95
+ * @param {string} name
96
+ * @return {null|File|string}
97
+ */
98
+ get(name) {
99
+ const entry = this.#list.get(name);
100
+ if (!entry) return null;
101
+ return entry[0];
102
+ }
103
+
104
+ /**
105
+ * @param {string} name
106
+ * @return {(File|string)[]}
107
+ */
108
+ getAll(name) {
109
+ return this.#list.get(name) ?? [];
110
+ }
111
+
112
+ /**
113
+ * @param {string} name
114
+ * @return {boolean}
115
+ */
116
+ has(name) {
117
+ return this.#list.has(name);
118
+ }
119
+
120
+ /**
121
+ * @param {string} name
122
+ * @param {string|Blob} value
123
+ * @param {string} [filename]
124
+ * @return {void}
125
+ */
126
+ set(name, value, filename) {
127
+ const entry = FormData.#createEntry(name, value, filename);
128
+ if (this.#list.has(entry.name)) {
129
+ const entries = this.#list.get(name);
130
+ entries.splice(0, entries.length, entry.value);
131
+ } else {
132
+ this.#list.set(name, [entry.value]);
133
+ }
134
+ }
135
+
136
+ /**
137
+ * @param {(value:(string|File), key:string, parent:this) => void} callback
138
+ * @return {void}
139
+ */
140
+ forEach(callback) {
141
+ for (const [key, value] of this) {
142
+ callback(value, key, this);
143
+ }
144
+ }
145
+
146
+ get keys() {
147
+ return this.#list.keys;
148
+ }
149
+
150
+ * values() {
151
+ for (const value of this.#list.values()) {
152
+ yield value[0];
153
+ }
154
+ }
155
+
156
+ * [Symbol.iterator]() {
157
+ for (const entry of this.#list.entries()) {
158
+ yield /** @type {[string, string|File]} */ ([entry[0], entry[1][0]]);
159
+ }
160
+ }
161
+ }
162
+
163
+ FormData.prototype.entries = FormData.prototype[Symbol.iterator];
164
+ FormData.prototype.toString = () => '[Object FormData]';
@@ -1 +1 @@
1
- {"version":3,"file":"ReadFormData.d.ts","sourceRoot":"","sources":["../../middleware/ReadFormData.js"],"names":[],"mappings":"AAwFA;;IAEI,aAA8C;CAQjD;0BAlGa,OAAO,uBAAuB,EAAE,OAAO;iCACvC,OAAO,yBAAyB,EAAE,kBAAkB"}
1
+ {"version":3,"file":"ReadFormData.d.ts","sourceRoot":"","sources":["../../middleware/ReadFormData.js"],"names":[],"mappings":"AA2FA;;IAEI,aAA8C;CAQjD;0BArGa,OAAO,uBAAuB,EAAE,OAAO;iCACvC,OAAO,yBAAyB,EAAE,kBAAkB"}
@@ -12,7 +12,7 @@
12
12
  */
13
13
  export default class SendJsonMiddleware {
14
14
  /** @type {SendJsonMiddleware} */
15
- static "__#5@#defaultInstance": SendJsonMiddleware;
15
+ static "__#private@#defaultInstance": SendJsonMiddleware;
16
16
  /**
17
17
  * @param {string} charset
18
18
  * @return {BufferEncoding}
@@ -1 +1 @@
1
- {"version":3,"file":"SendJsonMiddleware.d.ts","sourceRoot":"","sources":["../../middleware/SendJsonMiddleware.js"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,yGAAyG;AACzG,yFAAyF;AACzF,uFAAuF;AAEvF;;;;;;;GAOG;AAIH;IACE,iCAAiC;IACjC,gCADW,kBAAkB,CACL;IAExB;;;OAGG;IACH,wCAHW,MAAM,GACL,cAAc,CAsBzB;;;;IAcD,mDAAmD;IACnD,sBADY,yBAAyB,EASpC;IAPC;;;;MAIC;;;;;CAkEJ;0BAlIa,OAAO,yBAAyB,EAAE,WAAW;yCAC7C,OAAO,yBAAyB,EAAE,0BAA0B;iCAC5D,OAAO,yBAAyB,EAAE,kBAAkB;gCACpD,OAAO,yBAAyB,EAAE,iBAAiB;;qBAIvD,MAAM;;;;iBACN,OAAO;;;;mBAEP,OAAO"}
1
+ {"version":3,"file":"SendJsonMiddleware.d.ts","sourceRoot":"","sources":["../../middleware/SendJsonMiddleware.js"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,yGAAyG;AACzG,yFAAyF;AACzF,uFAAuF;AAEvF;;;;;;;GAOG;AAIH;IACE,iCAAiC;IACjC,sCADW,kBAAkB,CACL;IAExB;;;OAGG;IACH,wCAHW,MAAM,GACL,cAAc,CAsBzB;;;;IAcD,mDAAmD;IACnD,sBADY,yBAAyB,EASpC;IAPC;;;;MAIC;;;;;CAkEJ;0BAlIa,OAAO,yBAAyB,EAAE,WAAW;yCAC7C,OAAO,yBAAyB,EAAE,0BAA0B;iCAC5D,OAAO,yBAAyB,EAAE,kBAAkB;gCACpD,OAAO,yBAAyB,EAAE,iBAAiB;;qBAIvD,MAAM;;;;iBACN,OAAO;;;;mBAEP,OAAO"}
@@ -0,0 +1,66 @@
1
+ /** @implements {FormData} */
2
+ export default class FormData implements FormData {
3
+ /**
4
+ * @param {string} s
5
+ * @return {string}
6
+ */
7
+ static "__#private@#scalarValue": StringConstructor;
8
+ /**
9
+ * @param {string} name
10
+ * @param {string|Blob} value
11
+ * @param {string} [filename]
12
+ * @return {{name:string, value:string|File}}
13
+ */
14
+ static "__#private@#createEntry"(name: string, value: string | Blob, filename?: string): {
15
+ name: string;
16
+ value: string | File;
17
+ };
18
+ /** @param {HTMLFormElement} [form] */
19
+ constructor(form?: HTMLFormElement);
20
+ /**
21
+ * @param {string} name
22
+ * @param {string|Blob} value
23
+ * @param {string} [filename]
24
+ * @return {void}
25
+ */
26
+ append(name: string, value: string | Blob, filename?: string): void;
27
+ /**
28
+ * @param {string} name
29
+ * @return {void}
30
+ */
31
+ delete(name: string): void;
32
+ /**
33
+ * @param {string} name
34
+ * @return {null|File|string}
35
+ */
36
+ get(name: string): null | File | string;
37
+ /**
38
+ * @param {string} name
39
+ * @return {(File|string)[]}
40
+ */
41
+ getAll(name: string): (File | string)[];
42
+ /**
43
+ * @param {string} name
44
+ * @return {boolean}
45
+ */
46
+ has(name: string): boolean;
47
+ /**
48
+ * @param {string} name
49
+ * @param {string|Blob} value
50
+ * @param {string} [filename]
51
+ * @return {void}
52
+ */
53
+ set(name: string, value: string | Blob, filename?: string): void;
54
+ /**
55
+ * @param {(value:(string|File), key:string, parent:this) => void} callback
56
+ * @return {void}
57
+ */
58
+ forEach(callback: (value: (string | File), key: string, parent: this) => void): void;
59
+ get keys(): () => MapIterator<string>;
60
+ values(): Generator<string | File, void, unknown>;
61
+ entries: () => Generator<[string, string | File], void, unknown>;
62
+ toString(): string;
63
+ [Symbol.iterator](): Generator<[string, string | File], void, unknown>;
64
+ #private;
65
+ }
66
+ //# sourceMappingURL=FormData.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormData.d.ts","sourceRoot":"","sources":["../../polyfill/FormData.js"],"names":[],"mappings":"AAEA,6BAA6B;AAC7B,yCADiB,QAAQ;IAYvB;;;OAGG;IACH,oDAA6B;IAE7B;;;;;OAKG;IACH,uCALW,MAAM,SACN,MAAM,GAAC,IAAI,aACX,MAAM,GACL;QAAC,IAAI,EAAC,MAAM,CAAC;QAAC,KAAK,EAAC,MAAM,GAAC,IAAI,CAAA;KAAC,CA4C3C;IA7DD,sCAAsC;IACtC,mBADY,eAAe,EAK1B;IA0DD;;;;;OAKG;IACH,aALW,MAAM,SACN,MAAM,GAAC,IAAI,aACX,MAAM,GACL,IAAI,CASf;IAED;;;OAGG;IACH,aAHW,MAAM,GACL,IAAI,CAIf;IAED;;;OAGG;IACH,UAHW,MAAM,GACL,IAAI,GAAC,IAAI,GAAC,MAAM,CAM3B;IAED;;;OAGG;IACH,aAHW,MAAM,GACL,CAAC,IAAI,GAAC,MAAM,CAAC,EAAE,CAI1B;IAED;;;OAGG;IACH,UAHW,MAAM,GACL,OAAO,CAIlB;IAED;;;;;OAKG;IACH,UALW,MAAM,SACN,MAAM,GAAC,IAAI,aACX,MAAM,GACL,IAAI,CAUf;IAED;;;OAGG;IACH,kBAHW,CAAC,KAAK,EAAC,CAAC,MAAM,GAAC,IAAI,CAAC,EAAE,GAAG,EAAC,MAAM,EAAE,MAAM,EAAC,IAAI,KAAK,IAAI,GACrD,IAAI,CAMf;IAED,sCAEC;IAED,kDAIC;IASH,iEAA0B;IAC1B,mBAAuD;IARrD,uEAIC;;CACF"}