@c9up/ream 0.2.28 → 0.2.30
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 +5 -6
- package/dist/Codemods.d.ts +24 -0
- package/dist/Codemods.d.ts.map +1 -1
- package/dist/Codemods.js +211 -1
- package/dist/Codemods.js.map +1 -1
- package/dist/HttpKernel.d.ts.map +1 -1
- package/dist/HttpKernel.js +17 -5
- package/dist/HttpKernel.js.map +1 -1
- package/dist/Ignitor.d.ts +15 -2
- package/dist/Ignitor.d.ts.map +1 -1
- package/dist/Ignitor.js +33 -23
- package/dist/Ignitor.js.map +1 -1
- package/dist/bodyparser/BodyParserMiddleware.d.ts +4 -4
- package/dist/bodyparser/BodyParserMiddleware.d.ts.map +1 -1
- package/dist/bodyparser/BodyParserMiddleware.js +41 -11
- package/dist/bodyparser/BodyParserMiddleware.js.map +1 -1
- package/dist/bodyparser/MultipartFile.d.ts +21 -15
- package/dist/bodyparser/MultipartFile.d.ts.map +1 -1
- package/dist/bodyparser/MultipartFile.js +40 -58
- package/dist/bodyparser/MultipartFile.js.map +1 -1
- package/dist/bodyparser/parseSize.d.ts +7 -4
- package/dist/bodyparser/parseSize.d.ts.map +1 -1
- package/dist/bodyparser/parseSize.js +12 -17
- package/dist/bodyparser/parseSize.js.map +1 -1
- package/dist/bodyparser/qsParse.d.ts +20 -1
- package/dist/bodyparser/qsParse.d.ts.map +1 -1
- package/dist/bodyparser/qsParse.js +78 -25
- package/dist/bodyparser/qsParse.js.map +1 -1
- package/dist/codemods/source.d.ts +57 -0
- package/dist/codemods/source.d.ts.map +1 -0
- package/dist/codemods/source.js +282 -0
- package/dist/codemods/source.js.map +1 -0
- package/dist/console/prompts.d.ts.map +1 -1
- package/dist/console/prompts.js +3 -1
- package/dist/console/prompts.js.map +1 -1
- package/dist/container/Container.d.ts.map +1 -1
- package/dist/container/Container.js +61 -71
- package/dist/container/Container.js.map +1 -1
- package/dist/events/Emitter.d.ts +12 -0
- package/dist/events/Emitter.d.ts.map +1 -1
- package/dist/events/Emitter.js +36 -9
- package/dist/events/Emitter.js.map +1 -1
- package/dist/events/helix/helpers.d.ts.map +1 -1
- package/dist/events/helix/helpers.js +19 -9
- package/dist/events/helix/helpers.js.map +1 -1
- package/dist/graphql/GraphQLEngine.d.ts +8 -0
- package/dist/graphql/GraphQLEngine.d.ts.map +1 -1
- package/dist/graphql/GraphQLEngine.js +79 -12
- package/dist/graphql/GraphQLEngine.js.map +1 -1
- package/dist/helpers/MessageBuilder.d.ts +4 -2
- package/dist/helpers/MessageBuilder.d.ts.map +1 -1
- package/dist/helpers/MessageBuilder.js +4 -2
- package/dist/helpers/MessageBuilder.js.map +1 -1
- package/dist/helpers/errors.d.ts +11 -0
- package/dist/helpers/errors.d.ts.map +1 -0
- package/dist/helpers/errors.js +17 -0
- package/dist/helpers/errors.js.map +1 -0
- package/dist/helpers/napi-loader.d.ts.map +1 -1
- package/dist/helpers/napi-loader.js +3 -2
- package/dist/helpers/napi-loader.js.map +1 -1
- package/dist/http/Exception.d.ts +14 -1
- package/dist/http/Exception.d.ts.map +1 -1
- package/dist/http/Exception.js +10 -2
- package/dist/http/Exception.js.map +1 -1
- package/dist/http/HttpContext.d.ts +31 -2
- package/dist/http/HttpContext.d.ts.map +1 -1
- package/dist/http/HttpContext.js +12 -5
- package/dist/http/HttpContext.js.map +1 -1
- package/dist/http/RedirectBuilder.d.ts +9 -3
- package/dist/http/RedirectBuilder.d.ts.map +1 -1
- package/dist/http/RedirectBuilder.js +43 -37
- package/dist/http/RedirectBuilder.js.map +1 -1
- package/dist/http/Request.d.ts +42 -17
- package/dist/http/Request.d.ts.map +1 -1
- package/dist/http/Request.js +80 -58
- package/dist/http/Request.js.map +1 -1
- package/dist/http/Response.d.ts +7 -4
- package/dist/http/Response.d.ts.map +1 -1
- package/dist/http/Response.js +14 -6
- package/dist/http/Response.js.map +1 -1
- package/dist/http/SseStream.js +6 -7
- package/dist/http/SseStream.js.map +1 -1
- package/dist/http/permissions.d.ts +25 -0
- package/dist/http/permissions.d.ts.map +1 -0
- package/dist/http/permissions.js +38 -0
- package/dist/http/permissions.js.map +1 -0
- package/dist/http-client/HttpClient.d.ts +111 -0
- package/dist/http-client/HttpClient.d.ts.map +1 -0
- package/dist/http-client/HttpClient.js +386 -0
- package/dist/http-client/HttpClient.js.map +1 -0
- package/dist/http-client/addresses.d.ts +14 -0
- package/dist/http-client/addresses.d.ts.map +1 -0
- package/dist/http-client/addresses.js +57 -0
- package/dist/http-client/addresses.js.map +1 -0
- package/dist/http-client/fake.d.ts +50 -0
- package/dist/http-client/fake.d.ts.map +1 -0
- package/dist/http-client/fake.js +95 -0
- package/dist/http-client/fake.js.map +1 -0
- package/dist/http-client/index.d.ts +7 -0
- package/dist/http-client/index.d.ts.map +1 -0
- package/dist/http-client/index.js +7 -0
- package/dist/http-client/index.js.map +1 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/middleware/Pipeline.d.ts.map +1 -1
- package/dist/middleware/Pipeline.js +6 -3
- package/dist/middleware/Pipeline.js.map +1 -1
- package/dist/native/generated.d.ts +93 -36
- package/dist/native/generated.d.ts.map +1 -1
- package/dist/profiler/Profiler.d.ts.map +1 -1
- package/dist/profiler/Profiler.js +4 -1
- package/dist/profiler/Profiler.js.map +1 -1
- package/dist/profiler/client.generated.d.ts +5 -0
- package/dist/profiler/client.generated.d.ts.map +1 -0
- package/dist/profiler/client.generated.js +6 -0
- package/dist/profiler/client.generated.js.map +1 -0
- package/dist/profiler/collectors.d.ts +92 -13
- package/dist/profiler/collectors.d.ts.map +1 -1
- package/dist/profiler/collectors.js +106 -19
- package/dist/profiler/collectors.js.map +1 -1
- package/dist/profiler/endpoint.d.ts +2 -1
- package/dist/profiler/endpoint.d.ts.map +1 -1
- package/dist/profiler/endpoint.js +25 -1
- package/dist/profiler/endpoint.js.map +1 -1
- package/dist/profiler/index.d.ts +8 -4
- package/dist/profiler/index.d.ts.map +1 -1
- package/dist/profiler/index.js +11 -4
- package/dist/profiler/index.js.map +1 -1
- package/dist/profiler/middleware.d.ts.map +1 -1
- package/dist/profiler/middleware.js +76 -10
- package/dist/profiler/middleware.js.map +1 -1
- package/dist/profiler/preview.d.ts +17 -0
- package/dist/profiler/preview.d.ts.map +1 -0
- package/dist/profiler/preview.js +100 -0
- package/dist/profiler/preview.js.map +1 -0
- package/dist/profiler/toolbar.d.ts +15 -23
- package/dist/profiler/toolbar.d.ts.map +1 -1
- package/dist/profiler/toolbar.js +25 -91
- package/dist/profiler/toolbar.js.map +1 -1
- package/dist/profiler/types.d.ts +6 -1
- package/dist/profiler/types.d.ts.map +1 -1
- package/dist/router/Router.d.ts +6 -0
- package/dist/router/Router.d.ts.map +1 -1
- package/dist/router/Router.js +115 -12
- package/dist/router/Router.js.map +1 -1
- package/dist/rpc/RpcProvider.d.ts +6 -0
- package/dist/rpc/RpcProvider.d.ts.map +1 -1
- package/dist/rpc/RpcProvider.js +4 -1
- package/dist/rpc/RpcProvider.js.map +1 -1
- package/dist/rpc/RpcRouter.d.ts +27 -14
- package/dist/rpc/RpcRouter.d.ts.map +1 -1
- package/dist/rpc/RpcRouter.js +97 -40
- package/dist/rpc/RpcRouter.js.map +1 -1
- package/dist/scheduler/Scheduler.js +1 -1
- package/dist/scheduler/Scheduler.js.map +1 -1
- package/dist/scheduler/locks/RedisLockBackend.d.ts.map +1 -1
- package/dist/scheduler/locks/RedisLockBackend.js +13 -2
- package/dist/scheduler/locks/RedisLockBackend.js.map +1 -1
- package/dist/security/CookieSigner.d.ts.map +1 -1
- package/dist/security/CookieSigner.js +32 -8
- package/dist/security/CookieSigner.js.map +1 -1
- package/dist/security/SignedUrl.d.ts.map +1 -1
- package/dist/security/SignedUrl.js +16 -19
- package/dist/security/SignedUrl.js.map +1 -1
- package/dist/server/Server.d.ts +44 -12
- package/dist/server/Server.d.ts.map +1 -1
- package/dist/server/Server.js +31 -10
- package/dist/server/Server.js.map +1 -1
- package/dist/server/nativeGrpc.d.ts +27 -0
- package/dist/server/nativeGrpc.d.ts.map +1 -0
- package/dist/server/nativeGrpc.js +47 -0
- package/dist/server/nativeGrpc.js.map +1 -0
- package/dist/server/nativeLimits.d.ts +57 -0
- package/dist/server/nativeLimits.d.ts.map +1 -0
- package/dist/server/nativeLimits.js +75 -0
- package/dist/server/nativeLimits.js.map +1 -0
- package/dist/session/Session.d.ts +12 -0
- package/dist/session/Session.d.ts.map +1 -1
- package/dist/session/Session.js +13 -4
- package/dist/session/Session.js.map +1 -1
- package/dist/session/SessionMiddleware.d.ts.map +1 -1
- package/dist/session/SessionMiddleware.js +28 -9
- package/dist/session/SessionMiddleware.js.map +1 -1
- package/dist/session/config.d.ts +5 -0
- package/dist/session/config.d.ts.map +1 -1
- package/dist/session/config.js +8 -0
- package/dist/session/config.js.map +1 -1
- package/dist/session/drivers/MemoryDriver.d.ts.map +1 -1
- package/dist/session/drivers/MemoryDriver.js +26 -7
- package/dist/session/drivers/MemoryDriver.js.map +1 -1
- package/dist/session/errors.d.ts +17 -0
- package/dist/session/errors.d.ts.map +1 -1
- package/dist/session/errors.js +21 -0
- package/dist/session/errors.js.map +1 -1
- package/dist/session/templateTags.d.ts +14 -0
- package/dist/session/templateTags.d.ts.map +1 -1
- package/dist/session/templateTags.js +45 -17
- package/dist/session/templateTags.js.map +1 -1
- package/dist/storage/StaticMiddleware.d.ts.map +1 -1
- package/dist/storage/StaticMiddleware.js +49 -27
- package/dist/storage/StaticMiddleware.js.map +1 -1
- package/dist/testing/ApiResponse.d.ts.map +1 -1
- package/dist/testing/ApiResponse.js +7 -1
- package/dist/testing/ApiResponse.js.map +1 -1
- package/dist/testing/TestClient.d.ts.map +1 -1
- package/dist/testing/TestClient.js +16 -4
- package/dist/testing/TestClient.js.map +1 -1
- package/dist/utils/Macroable.d.ts +1 -1
- package/dist/utils/Macroable.js +2 -2
- package/dist/utils/Macroable.js.map +1 -1
- package/events.darwin-arm64.node +0 -0
- package/events.darwin-x64.node +0 -0
- package/events.linux-arm64-gnu.node +0 -0
- package/events.linux-x64-gnu.node +0 -0
- package/events.win32-x64-msvc.node +0 -0
- package/index.darwin-arm64.node +0 -0
- package/index.darwin-x64.node +0 -0
- package/index.linux-arm64-gnu.node +0 -0
- package/index.linux-x64-gnu.node +0 -0
- package/index.win32-x64-msvc.node +0 -0
- package/package.json +11 -3
- package/scheduler.darwin-arm64.node +0 -0
- package/scheduler.darwin-x64.node +0 -0
- package/scheduler.linux-arm64-gnu.node +0 -0
- package/scheduler.linux-x64-gnu.node +0 -0
- package/scheduler.win32-x64-msvc.node +0 -0
- package/src/Codemods.ts +314 -3
- package/src/HttpKernel.ts +18 -7
- package/src/Ignitor.ts +58 -26
- package/src/bodyparser/BodyParserMiddleware.ts +45 -16
- package/src/bodyparser/MultipartFile.ts +46 -67
- package/src/bodyparser/parseSize.ts +17 -17
- package/src/bodyparser/qsParse.ts +96 -26
- package/src/codemods/source.ts +303 -0
- package/src/console/prompts.ts +3 -1
- package/src/container/Container.ts +97 -81
- package/src/events/Emitter.ts +37 -10
- package/src/events/helix/helpers.ts +24 -19
- package/src/graphql/GraphQLEngine.ts +91 -14
- package/src/helpers/MessageBuilder.ts +4 -2
- package/src/helpers/errors.ts +16 -0
- package/src/helpers/napi-loader.ts +3 -2
- package/src/http/Exception.ts +17 -2
- package/src/http/HttpContext.ts +34 -5
- package/src/http/RedirectBuilder.ts +51 -37
- package/src/http/Request.ts +102 -58
- package/src/http/Response.ts +15 -7
- package/src/http/SseStream.ts +6 -7
- package/src/http/permissions.ts +47 -0
- package/src/http-client/HttpClient.ts +505 -0
- package/src/http-client/addresses.ts +58 -0
- package/src/http-client/fake.ts +141 -0
- package/src/http-client/index.ts +21 -0
- package/src/index.ts +6 -1
- package/src/middleware/Pipeline.ts +7 -3
- package/src/native/generated.ts +106 -48
- package/src/profiler/Profiler.ts +4 -1
- package/src/profiler/client/toolbar.css +595 -0
- package/src/profiler/client/toolbar.js +1299 -0
- package/src/profiler/client.generated.ts +7 -0
- package/src/profiler/collectors.ts +156 -19
- package/src/profiler/endpoint.ts +27 -1
- package/src/profiler/index.ts +17 -3
- package/src/profiler/middleware.ts +74 -9
- package/src/profiler/preview.ts +104 -0
- package/src/profiler/toolbar.ts +28 -91
- package/src/profiler/types.ts +6 -1
- package/src/router/Router.ts +136 -13
- package/src/rpc/RpcProvider.ts +10 -1
- package/src/rpc/RpcRouter.ts +129 -45
- package/src/scheduler/Scheduler.ts +1 -1
- package/src/scheduler/locks/RedisLockBackend.ts +12 -4
- package/src/security/CookieSigner.ts +30 -8
- package/src/security/SignedUrl.ts +18 -17
- package/src/server/Server.ts +60 -12
- package/src/server/nativeGrpc.ts +59 -0
- package/src/server/nativeLimits.ts +111 -0
- package/src/session/Session.ts +29 -4
- package/src/session/SessionMiddleware.ts +30 -10
- package/src/session/config.ts +7 -0
- package/src/session/drivers/MemoryDriver.ts +26 -7
- package/src/session/errors.ts +31 -0
- package/src/session/templateTags.ts +57 -0
- package/src/storage/StaticMiddleware.ts +46 -27
- package/src/testing/ApiResponse.ts +7 -1
- package/src/testing/TestClient.ts +14 -5
- package/src/utils/Macroable.ts +2 -2
- package/scripts/build-napi-types.mjs +0 -69
- package/scripts/copy-napi.mjs +0 -121
- package/scripts/generate-mime.mjs +0 -119
- package/scripts/generate-napi-types.mjs +0 -187
|
@@ -19,11 +19,19 @@ function isMimeType(value) {
|
|
|
19
19
|
*
|
|
20
20
|
* Like AdonisJS MultipartFile:
|
|
21
21
|
* const avatar = request.file('avatar', { size: '2mb', extnames: ['jpg', 'png'] })
|
|
22
|
-
* await avatar.
|
|
22
|
+
* await avatar.move(app.makePath('uploads'))
|
|
23
|
+
*
|
|
24
|
+
* Macroable: a package extends every upload at boot, the way a storage
|
|
25
|
+
* package adds `moveToDisk(key, disk?, options?)` to write it to a configured
|
|
26
|
+
* disk. `moveToDisk` is deliberately not defined here, so that macro owns it.
|
|
23
27
|
*/
|
|
24
28
|
import { randomBytes } from 'node:crypto';
|
|
25
29
|
import { Readable } from 'node:stream';
|
|
26
|
-
|
|
30
|
+
import { errorCode } from '../helpers/errors.js';
|
|
31
|
+
import { Macroable } from '../utils/Macroable.js';
|
|
32
|
+
import { parseSize } from './parseSize.js';
|
|
33
|
+
import { parseFormFields } from './qsParse.js';
|
|
34
|
+
export class MultipartFile extends Macroable {
|
|
27
35
|
/** Original filename from the client. */
|
|
28
36
|
clientName;
|
|
29
37
|
/**
|
|
@@ -105,6 +113,11 @@ export class MultipartFile {
|
|
|
105
113
|
filePath;
|
|
106
114
|
/** The name it was written under, once it has been moved. */
|
|
107
115
|
fileName;
|
|
116
|
+
/**
|
|
117
|
+
* Free-form data about the file, for whoever moves it: a storage macro
|
|
118
|
+
* records the URL of the stored object here.
|
|
119
|
+
*/
|
|
120
|
+
meta = {};
|
|
108
121
|
/** File size in bytes. */
|
|
109
122
|
size;
|
|
110
123
|
/** Raw file content as Buffer. */
|
|
@@ -126,6 +139,7 @@ export class MultipartFile {
|
|
|
126
139
|
/** Whether the magic-byte pass has run, however it turned out. */
|
|
127
140
|
#detectionRan = false;
|
|
128
141
|
constructor(options) {
|
|
142
|
+
super();
|
|
129
143
|
this.fieldName = options.fieldName;
|
|
130
144
|
this.clientName = options.clientName;
|
|
131
145
|
this.headers = { 'content-type': options.type };
|
|
@@ -201,8 +215,8 @@ export class MultipartFile {
|
|
|
201
215
|
* spells it.
|
|
202
216
|
*/
|
|
203
217
|
validate(options = this.#validationOptions) {
|
|
204
|
-
if (options.size) {
|
|
205
|
-
const maxBytes =
|
|
218
|
+
if (options.size !== undefined) {
|
|
219
|
+
const maxBytes = parseSize(options.size);
|
|
206
220
|
if (this.size > maxBytes) {
|
|
207
221
|
this.errors.push(`File size ${this.size} exceeds limit ${options.size}`);
|
|
208
222
|
}
|
|
@@ -243,33 +257,6 @@ export class MultipartFile {
|
|
|
243
257
|
get isValid() {
|
|
244
258
|
return this.errors.length === 0;
|
|
245
259
|
}
|
|
246
|
-
/**
|
|
247
|
-
* Move file to a directory on disk. When `name` is supplied it must be
|
|
248
|
-
* a plain filename — no path separators, no `.`/`..` segments. The
|
|
249
|
-
* common footgun is passing the client-supplied `clientName` directly
|
|
250
|
-
* (`await file.moveToDisk('uploads', file.clientName)`); a malicious
|
|
251
|
-
* upload could otherwise traverse out of `directory` via `../../etc/...`.
|
|
252
|
-
*/
|
|
253
|
-
async moveToDisk(directory, name) {
|
|
254
|
-
const { mkdirSync, writeFileSync } = await import('node:fs');
|
|
255
|
-
const { join } = await import('node:path');
|
|
256
|
-
if (name !== undefined && !isSafeFilename(name)) {
|
|
257
|
-
throw new Error(`MultipartFile.moveToDisk: 'name' must be a plain filename (no path separators, '.', or '..'). Got: ${JSON.stringify(name)}`);
|
|
258
|
-
}
|
|
259
|
-
mkdirSync(directory, { recursive: true });
|
|
260
|
-
const fileName = name ?? `${randomBytes(16).toString('hex')}.${this.extname}`;
|
|
261
|
-
// Defense-in-depth: the default branch interpolates `extname` (derived
|
|
262
|
-
// from attacker-controlled `clientName`) into the filename, bypassing
|
|
263
|
-
// the `name` guard above. Re-validate the synthesized fileName before
|
|
264
|
-
// join to reject a hostile extname (separators, NUL).
|
|
265
|
-
if (!isSafeFilename(fileName)) {
|
|
266
|
-
throw new Error(`MultipartFile.moveToDisk: derived filename '${fileName}' is unsafe (separator or invalid char in clientName-derived extname).`);
|
|
267
|
-
}
|
|
268
|
-
const filePath = join(directory, fileName);
|
|
269
|
-
writeFileSync(filePath, this.content);
|
|
270
|
-
this.markAsMoved(fileName, filePath);
|
|
271
|
-
return filePath;
|
|
272
|
-
}
|
|
273
260
|
/**
|
|
274
261
|
* Write the file into `location` (AdonisJS `move`).
|
|
275
262
|
*
|
|
@@ -278,17 +265,27 @@ export class MultipartFile {
|
|
|
278
265
|
* construction), so this writes the buffer. There is therefore no
|
|
279
266
|
* `E_MISSING_FILE_TMP_PATH`: there is no temporary file to be missing.
|
|
280
267
|
*
|
|
281
|
-
* `overwrite` defaults to true, as upstream.
|
|
282
|
-
*
|
|
283
|
-
*
|
|
284
|
-
*
|
|
268
|
+
* `overwrite` defaults to true, as upstream.
|
|
269
|
+
*
|
|
270
|
+
* NAMED DEVIATION — without `name`, upstream writes under `clientName`, a
|
|
271
|
+
* value the client chose; Ream generates a random name carrying the
|
|
272
|
+
* detected extension, so an upload neither picks its own path nor
|
|
273
|
+
* overwrites another one by sharing its name.
|
|
274
|
+
*
|
|
275
|
+
* A caller-supplied `name` must be a plain filename (no separator, no `.`
|
|
276
|
+
* or `..`): the common footgun is passing `file.clientName` straight
|
|
277
|
+
* through. The generated name is checked too, since its extension comes
|
|
278
|
+
* from the client's filename when the bytes are not recognised.
|
|
285
279
|
*/
|
|
286
280
|
async move(location, options) {
|
|
287
281
|
const { mkdir, writeFile } = await import('node:fs/promises');
|
|
288
282
|
const { join } = await import('node:path');
|
|
283
|
+
if (options?.name !== undefined && !isSafeFilename(options.name)) {
|
|
284
|
+
throw new Error(`MultipartFile.move: 'name' must be a plain filename (no path separators, '.', or '..'). Got: ${JSON.stringify(options.name)}`);
|
|
285
|
+
}
|
|
289
286
|
const name = options?.name ?? `${randomBytes(16).toString('hex')}.${this.extname || 'unknown'}`;
|
|
290
287
|
if (!isSafeFilename(name)) {
|
|
291
|
-
throw new Error(`MultipartFile.move:
|
|
288
|
+
throw new Error(`MultipartFile.move: the derived file name ${JSON.stringify(name)} is unsafe (a separator or NUL in the extension of the client's filename).`);
|
|
292
289
|
}
|
|
293
290
|
const filePath = join(location, name);
|
|
294
291
|
await mkdir(location, { recursive: true });
|
|
@@ -306,7 +303,7 @@ export class MultipartFile {
|
|
|
306
303
|
await writeFile(filePath, this.content, options?.overwrite === false ? { flag: 'wx' } : {});
|
|
307
304
|
}
|
|
308
305
|
catch (error) {
|
|
309
|
-
if (error
|
|
306
|
+
if (errorCode(error) === 'EEXIST') {
|
|
310
307
|
throw new Error(`"${name}" already exists at "${location}". Set "overwrite = true" to overwrite it`);
|
|
311
308
|
}
|
|
312
309
|
throw error;
|
|
@@ -342,23 +339,6 @@ function isSafeFilename(name) {
|
|
|
342
339
|
return false;
|
|
343
340
|
return true;
|
|
344
341
|
}
|
|
345
|
-
function parseFileSize(size) {
|
|
346
|
-
const match = size.match(/^(\d+)(kb|mb|gb)?$/i);
|
|
347
|
-
if (!match)
|
|
348
|
-
return 1024 * 1024;
|
|
349
|
-
const [, digits, unit] = match;
|
|
350
|
-
const num = parseInt(digits ?? '0', 10);
|
|
351
|
-
switch (unit?.toLowerCase()) {
|
|
352
|
-
case 'kb':
|
|
353
|
-
return num * 1024;
|
|
354
|
-
case 'mb':
|
|
355
|
-
return num * 1024 * 1024;
|
|
356
|
-
case 'gb':
|
|
357
|
-
return num * 1024 * 1024 * 1024;
|
|
358
|
-
default:
|
|
359
|
-
return num;
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
342
|
/**
|
|
363
343
|
* Hydrate `MultipartFile` instances from the typed payload the Rust
|
|
364
344
|
* HyperServer attaches to the request. The wire-level parser (multer crate,
|
|
@@ -366,10 +346,12 @@ function parseFileSize(size) {
|
|
|
366
346
|
* parsing — JS just decodes the base64 envelope and wraps the result.
|
|
367
347
|
*/
|
|
368
348
|
export function hydrateMultipartPayload(payload) {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
349
|
+
// Nested and collected exactly like a urlencoded body: `tags[]` repeated is
|
|
350
|
+
// an array, `user[name]` an object. Flat, a repeated name kept only its
|
|
351
|
+
// last value once a file input was added to the form.
|
|
352
|
+
// The multipart part count is already bounded natively (`maxFields`), so
|
|
353
|
+
// no parameter cap applies on top of it here.
|
|
354
|
+
const fields = parseFormFields(payload.fields, { parameterLimit: Number.POSITIVE_INFINITY });
|
|
373
355
|
const files = payload.files.map((f) => new MultipartFile({
|
|
374
356
|
fieldName: f.fieldName,
|
|
375
357
|
clientName: f.clientName,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultipartFile.js","sourceRoot":"","sources":["../../src/bodyparser/MultipartFile.ts"],"names":[],"mappings":"AA8BA,MAAM,UAAU,GAAG,IAAI,GAAG,CAAS;IACjC,aAAa;IACb,OAAO;IACP,SAAS;IACT,MAAM;IACN,OAAO;IACP,SAAS;IACT,OAAO;IACP,WAAW;IACX,MAAM;IACN,OAAO;CACR,CAAC,CAAA;AAEF,6DAA6D;AAC7D,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;AAC9B,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"MultipartFile.js","sourceRoot":"","sources":["../../src/bodyparser/MultipartFile.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Read a size limit (`'1mb'`, `'50 mb'`, `'1.5kb'`, `1024`) into bytes, with
|
|
3
|
+
* the `bytes` grammar every size option of the body parser accepts.
|
|
4
|
+
*
|
|
5
|
+
* Throws on anything it cannot read, or on a negative size. A silent fallback
|
|
6
|
+
* is what turned `limit: '50 mb'` into a 1 MB cap with no word: a limit the
|
|
7
|
+
* application did not set is worse than a boot that refuses to start.
|
|
5
8
|
*/
|
|
6
|
-
export declare function parseSize(size: string): number;
|
|
9
|
+
export declare function parseSize(size: string | number): number;
|
|
7
10
|
//# sourceMappingURL=parseSize.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseSize.d.ts","sourceRoot":"","sources":["../../src/bodyparser/parseSize.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"parseSize.d.ts","sourceRoot":"","sources":["../../src/bodyparser/parseSize.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CASvD"}
|
|
@@ -1,23 +1,18 @@
|
|
|
1
|
+
import { ReamError } from '../errors/ReamError.js';
|
|
2
|
+
import { parse } from '../helpers/bytes.js';
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
4
|
+
* Read a size limit (`'1mb'`, `'50 mb'`, `'1.5kb'`, `1024`) into bytes, with
|
|
5
|
+
* the `bytes` grammar every size option of the body parser accepts.
|
|
6
|
+
*
|
|
7
|
+
* Throws on anything it cannot read, or on a negative size. A silent fallback
|
|
8
|
+
* is what turned `limit: '50 mb'` into a 1 MB cap with no word: a limit the
|
|
9
|
+
* application did not set is worse than a boot that refuses to start.
|
|
5
10
|
*/
|
|
6
11
|
export function parseSize(size) {
|
|
7
|
-
const
|
|
8
|
-
if (!
|
|
9
|
-
|
|
10
|
-
const [, digits, unit] = match;
|
|
11
|
-
const num = parseInt(digits ?? '0', 10);
|
|
12
|
-
switch (unit?.toLowerCase()) {
|
|
13
|
-
case 'kb':
|
|
14
|
-
return num * 1024;
|
|
15
|
-
case 'mb':
|
|
16
|
-
return num * 1024 * 1024;
|
|
17
|
-
case 'gb':
|
|
18
|
-
return num * 1024 * 1024 * 1024;
|
|
19
|
-
default:
|
|
20
|
-
return num;
|
|
12
|
+
const bytes = parse(size);
|
|
13
|
+
if (bytes === null || !Number.isFinite(bytes) || bytes < 0) {
|
|
14
|
+
throw new ReamError('E_BODYPARSER_INVALID_SIZE', `Cannot read the size ${JSON.stringify(size)}: expected a number of bytes or a value such as '512kb', '1.5mb' or '2 gb'.`);
|
|
21
15
|
}
|
|
16
|
+
return bytes;
|
|
22
17
|
}
|
|
23
18
|
//# sourceMappingURL=parseSize.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseSize.js","sourceRoot":"","sources":["../../src/bodyparser/parseSize.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"parseSize.js","sourceRoot":"","sources":["../../src/bodyparser/parseSize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAClD,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAE3C;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CAAC,IAAqB;IAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAA;IACzB,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QAC3D,MAAM,IAAI,SAAS,CACjB,2BAA2B,EAC3B,wBAAwB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,6EAA6E,CAC1H,CAAA;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC"}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* dependency it can write in a screenful, and the limits below are easier to
|
|
12
12
|
* defend when they are visible.
|
|
13
13
|
*
|
|
14
|
-
*
|
|
14
|
+
* Four guards, all of which `qs` also applies:
|
|
15
15
|
*
|
|
16
16
|
* - **Prototype keys are dropped.** `__proto__[x]=1` in a form body is the
|
|
17
17
|
* classic prototype-pollution vector; the key never reaches an object.
|
|
@@ -19,10 +19,13 @@
|
|
|
19
19
|
* as a literal key rather than allocating unbounded nesting.
|
|
20
20
|
* - **Parameter count is capped** (`qs` defaults to 1000), so a body of a
|
|
21
21
|
* million `a[0]`, `a[1]`… cannot be turned into a million-entry object.
|
|
22
|
+
* - **Explicit array indices are capped** (`qs` `arrayLimit`, default 20).
|
|
23
|
+
* A larger index is an object key, so `ids[4294967294]=1` stays one entry.
|
|
22
24
|
*/
|
|
23
25
|
/** `qs` defaults, reproduced so the behaviour is the same out of the box. */
|
|
24
26
|
export declare const DEFAULT_DEPTH = 5;
|
|
25
27
|
export declare const DEFAULT_PARAMETER_LIMIT = 1000;
|
|
28
|
+
export declare const DEFAULT_ARRAY_LIMIT = 20;
|
|
26
29
|
export interface QsParseOptions {
|
|
27
30
|
/**
|
|
28
31
|
* Treat `user.name` as `user[name]`. AdonisJS forces this ON for form
|
|
@@ -32,6 +35,12 @@ export interface QsParseOptions {
|
|
|
32
35
|
allowDots?: boolean;
|
|
33
36
|
depth?: number;
|
|
34
37
|
parameterLimit?: number;
|
|
38
|
+
/**
|
|
39
|
+
* Highest explicit index + 1 that still builds an array (`qs` defaults to
|
|
40
|
+
* 20). `ids[25]=x` becomes `{ ids: { '25': 'x' } }`, so a 16-byte request
|
|
41
|
+
* cannot allocate a 100-million-slot array.
|
|
42
|
+
*/
|
|
43
|
+
arrayLimit?: number;
|
|
35
44
|
/** Turn `''` into `null`, as AdonisJS' `convertEmptyStringsToNull` does. */
|
|
36
45
|
convertEmptyStringsToNull?: boolean;
|
|
37
46
|
/** Trim surrounding whitespace, as AdonisJS' `trimWhitespaces` does. */
|
|
@@ -49,4 +58,14 @@ export interface QsParseOptions {
|
|
|
49
58
|
export declare function decodeFormComponent(value: string): string;
|
|
50
59
|
/** Parse a urlencoded body into a nested object. */
|
|
51
60
|
export declare function parseQueryString(body: string, options?: QsParseOptions): Record<string, unknown>;
|
|
61
|
+
/**
|
|
62
|
+
* Nest form fields that arrive as decoded name/value pairs — a multipart
|
|
63
|
+
* body's text parts — with the key grammar and the guards of a urlencoded
|
|
64
|
+
* body. A `<select multiple name="tags[]">` keeps every value, and
|
|
65
|
+
* `user[name]` nests, whether or not the form also carries a file input.
|
|
66
|
+
*/
|
|
67
|
+
export declare function parseFormFields(fields: Iterable<{
|
|
68
|
+
name: string;
|
|
69
|
+
value: string;
|
|
70
|
+
}>, options?: QsParseOptions): Record<string, unknown>;
|
|
52
71
|
//# sourceMappingURL=qsParse.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qsParse.d.ts","sourceRoot":"","sources":["../../src/bodyparser/qsParse.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"qsParse.d.ts","sourceRoot":"","sources":["../../src/bodyparser/qsParse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,6EAA6E;AAC7E,eAAO,MAAM,aAAa,IAAI,CAAA;AAC9B,eAAO,MAAM,uBAAuB,OAAO,CAAA;AAC3C,eAAO,MAAM,mBAAmB,KAAK,CAAA;AAErC,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,4EAA4E;IAC5E,yBAAyB,CAAC,EAAE,OAAO,CAAA;IACnC,wEAAwE;IACxE,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B;AAyID;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOzD;AAED,oDAAoD;AACpD,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,cAAmB,GAC3B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAczB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,QAAQ,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,EACjD,OAAO,GAAE,cAAmB,GAC3B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAezB"}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* dependency it can write in a screenful, and the limits below are easier to
|
|
12
12
|
* defend when they are visible.
|
|
13
13
|
*
|
|
14
|
-
*
|
|
14
|
+
* Four guards, all of which `qs` also applies:
|
|
15
15
|
*
|
|
16
16
|
* - **Prototype keys are dropped.** `__proto__[x]=1` in a form body is the
|
|
17
17
|
* classic prototype-pollution vector; the key never reaches an object.
|
|
@@ -19,10 +19,13 @@
|
|
|
19
19
|
* as a literal key rather than allocating unbounded nesting.
|
|
20
20
|
* - **Parameter count is capped** (`qs` defaults to 1000), so a body of a
|
|
21
21
|
* million `a[0]`, `a[1]`… cannot be turned into a million-entry object.
|
|
22
|
+
* - **Explicit array indices are capped** (`qs` `arrayLimit`, default 20).
|
|
23
|
+
* A larger index is an object key, so `ids[4294967294]=1` stays one entry.
|
|
22
24
|
*/
|
|
23
25
|
/** `qs` defaults, reproduced so the behaviour is the same out of the box. */
|
|
24
26
|
export const DEFAULT_DEPTH = 5;
|
|
25
27
|
export const DEFAULT_PARAMETER_LIMIT = 1000;
|
|
28
|
+
export const DEFAULT_ARRAY_LIMIT = 20;
|
|
26
29
|
/** Keys that must never be written onto an object. */
|
|
27
30
|
const FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
28
31
|
/**
|
|
@@ -60,14 +63,42 @@ function splitKey(key, depth, allowDots) {
|
|
|
60
63
|
function isIndex(segment) {
|
|
61
64
|
return /^\d+$/.test(segment);
|
|
62
65
|
}
|
|
63
|
-
|
|
64
|
-
|
|
66
|
+
function isContainer(value) {
|
|
67
|
+
return typeof value === 'object' && value !== null;
|
|
68
|
+
}
|
|
69
|
+
/** `{ '0': a, '1': b }` from `[a, b]`, holes left out — what `qs` produces on overflow. */
|
|
70
|
+
function arrayToObject(array) {
|
|
71
|
+
const object = {};
|
|
72
|
+
array.forEach((item, index) => {
|
|
73
|
+
object[String(index)] = item;
|
|
74
|
+
});
|
|
75
|
+
return object;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Assign `value` at `segments` inside `target`, creating containers as needed.
|
|
79
|
+
*
|
|
80
|
+
* An explicit index at or above `arrayLimit` never addresses an array: the
|
|
81
|
+
* container becomes (or is converted into) an object keyed by that index,
|
|
82
|
+
* as `qs` does. Without it, `ids[100000000]=1` allocates a sparse array whose
|
|
83
|
+
* iteration or serialisation blocks the event loop for seconds. Appends
|
|
84
|
+
* (`tags[]`, a repeated key) stay arrays — each one costs a parameter, so
|
|
85
|
+
* `parameterLimit` already bounds them, and a long checkbox group keeps the
|
|
86
|
+
* shape its handler expects (`qs` turns those into objects past the limit).
|
|
87
|
+
*/
|
|
88
|
+
function assign(target, segments, value, arrayLimit) {
|
|
65
89
|
let cursor = target;
|
|
90
|
+
// Swaps `cursor` inside its parent when an array has to become an object.
|
|
91
|
+
let replace = () => { };
|
|
66
92
|
for (let i = 0; i < segments.length; i++) {
|
|
67
93
|
const segment = segments[i] ?? '';
|
|
68
94
|
const last = i === segments.length - 1;
|
|
69
95
|
if (FORBIDDEN_KEYS.has(segment))
|
|
70
96
|
return;
|
|
97
|
+
if (Array.isArray(cursor) && isIndex(segment) && Number(segment) >= arrayLimit) {
|
|
98
|
+
const converted = arrayToObject(cursor);
|
|
99
|
+
replace(converted);
|
|
100
|
+
cursor = converted;
|
|
101
|
+
}
|
|
71
102
|
if (last) {
|
|
72
103
|
if (segment === '') {
|
|
73
104
|
// `tags[]` — append.
|
|
@@ -94,23 +125,29 @@ function assign(target, segments, value) {
|
|
|
94
125
|
return;
|
|
95
126
|
}
|
|
96
127
|
const nextSegment = segments[i + 1] ?? '';
|
|
97
|
-
const wantsArray = nextSegment === '' || isIndex(nextSegment);
|
|
128
|
+
const wantsArray = nextSegment === '' || (isIndex(nextSegment) && Number(nextSegment) < arrayLimit);
|
|
98
129
|
if (Array.isArray(cursor)) {
|
|
99
130
|
if (!isIndex(segment))
|
|
100
131
|
return;
|
|
132
|
+
const array = cursor;
|
|
101
133
|
const index = Number(segment);
|
|
102
|
-
const existing =
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
134
|
+
const existing = array[index];
|
|
135
|
+
const child = isContainer(existing) ? existing : wantsArray ? [] : {};
|
|
136
|
+
array[index] = child;
|
|
137
|
+
replace = (next) => {
|
|
138
|
+
array[index] = next;
|
|
139
|
+
};
|
|
140
|
+
cursor = child;
|
|
107
141
|
continue;
|
|
108
142
|
}
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
143
|
+
const object = cursor;
|
|
144
|
+
const existing = object[segment];
|
|
145
|
+
const child = isContainer(existing) ? existing : wantsArray ? [] : {};
|
|
146
|
+
object[segment] = child;
|
|
147
|
+
replace = (next) => {
|
|
148
|
+
object[segment] = next;
|
|
149
|
+
};
|
|
150
|
+
cursor = child;
|
|
114
151
|
}
|
|
115
152
|
}
|
|
116
153
|
/**
|
|
@@ -133,28 +170,44 @@ export function decodeFormComponent(value) {
|
|
|
133
170
|
}
|
|
134
171
|
/** Parse a urlencoded body into a nested object. */
|
|
135
172
|
export function parseQueryString(body, options = {}) {
|
|
136
|
-
const depth = options.depth ?? DEFAULT_DEPTH;
|
|
137
|
-
const parameterLimit = options.parameterLimit ?? DEFAULT_PARAMETER_LIMIT;
|
|
138
|
-
const result = {};
|
|
139
173
|
if (!body)
|
|
140
|
-
return
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
for (const pair of
|
|
174
|
+
return {};
|
|
175
|
+
const parameterLimit = options.parameterLimit ?? DEFAULT_PARAMETER_LIMIT;
|
|
176
|
+
const fields = [];
|
|
177
|
+
for (const pair of body.split('&')) {
|
|
144
178
|
if (!pair)
|
|
145
179
|
continue;
|
|
146
|
-
|
|
180
|
+
// Nothing past the limit is even decoded.
|
|
181
|
+
if (fields.length >= parameterLimit)
|
|
147
182
|
break;
|
|
148
183
|
const eqIdx = pair.indexOf('=');
|
|
149
184
|
const rawKey = eqIdx === -1 ? pair : pair.slice(0, eqIdx);
|
|
150
185
|
const rawValue = eqIdx === -1 ? '' : pair.slice(eqIdx + 1);
|
|
151
|
-
|
|
152
|
-
|
|
186
|
+
fields.push({ name: decodeFormComponent(rawKey), value: decodeFormComponent(rawValue) });
|
|
187
|
+
}
|
|
188
|
+
return parseFormFields(fields, options);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Nest form fields that arrive as decoded name/value pairs — a multipart
|
|
192
|
+
* body's text parts — with the key grammar and the guards of a urlencoded
|
|
193
|
+
* body. A `<select multiple name="tags[]">` keeps every value, and
|
|
194
|
+
* `user[name]` nests, whether or not the form also carries a file input.
|
|
195
|
+
*/
|
|
196
|
+
export function parseFormFields(fields, options = {}) {
|
|
197
|
+
const depth = options.depth ?? DEFAULT_DEPTH;
|
|
198
|
+
const parameterLimit = options.parameterLimit ?? DEFAULT_PARAMETER_LIMIT;
|
|
199
|
+
const arrayLimit = options.arrayLimit ?? DEFAULT_ARRAY_LIMIT;
|
|
200
|
+
const result = {};
|
|
201
|
+
let seen = 0;
|
|
202
|
+
for (const field of fields) {
|
|
203
|
+
if (++seen > parameterLimit)
|
|
204
|
+
break;
|
|
205
|
+
let value = field.value;
|
|
153
206
|
if (options.trimWhitespaces && typeof value === 'string')
|
|
154
207
|
value = value.trim();
|
|
155
208
|
if (options.convertEmptyStringsToNull && value === '')
|
|
156
209
|
value = null;
|
|
157
|
-
assign(result, splitKey(
|
|
210
|
+
assign(result, splitKey(field.name, depth, options.allowDots ?? true), value, arrayLimit);
|
|
158
211
|
}
|
|
159
212
|
return result;
|
|
160
213
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qsParse.js","sourceRoot":"","sources":["../../src/bodyparser/qsParse.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"qsParse.js","sourceRoot":"","sources":["../../src/bodyparser/qsParse.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Just enough of a TypeScript scanner for the configure codemods: find a
|
|
3
|
+
* call or an object/array literal in CODE (never inside a string, a template
|
|
4
|
+
* or a comment), split a literal into its top-level entries, and append to
|
|
5
|
+
* one. Upstream does this with a full AST; ream ships no compiler, and the
|
|
6
|
+
* files these codemods edit (`start/env.ts`, `reamrc.ts`) are object and
|
|
7
|
+
* array literals.
|
|
8
|
+
*
|
|
9
|
+
* Not handled: regular-expression literals (a quote inside one reads as the
|
|
10
|
+
* start of a string). Neither file has a reason to contain one.
|
|
11
|
+
*/
|
|
12
|
+
/** Index of the bracket closing the one at `open`, or -1. */
|
|
13
|
+
export declare function matchClose(src: string, open: number): number;
|
|
14
|
+
/** One top-level entry of a literal: the text between two commas. */
|
|
15
|
+
export interface Segment {
|
|
16
|
+
start: number;
|
|
17
|
+
end: number;
|
|
18
|
+
/** First code character, or `end` when the entry is only trivia. */
|
|
19
|
+
codeStart: number;
|
|
20
|
+
/** Just past the last code character (comments and whitespace excluded). */
|
|
21
|
+
codeEnd: number;
|
|
22
|
+
}
|
|
23
|
+
/** Split `src[start, end)` on its top-level commas. */
|
|
24
|
+
export declare function segments(src: string, start: number, end: number): Segment[];
|
|
25
|
+
/**
|
|
26
|
+
* Whether `code` is one complete expression that cannot reach outside the
|
|
27
|
+
* slot it is written into: brackets balanced and never closing past where
|
|
28
|
+
* they opened, strings and comments terminated, no top-level comma.
|
|
29
|
+
*/
|
|
30
|
+
export declare function isSingleExpression(code: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Index of the `(` of the first call to `callee` in code, or -1. A mention
|
|
33
|
+
* inside a string or a comment, or as the tail of a longer name
|
|
34
|
+
* (`MyEnv.create`), does not count.
|
|
35
|
+
*/
|
|
36
|
+
export declare function findCall(src: string, callee: string): number;
|
|
37
|
+
/** Index of the `{` after the first `export default` in code, or -1. */
|
|
38
|
+
export declare function findExportDefaultObject(src: string): number;
|
|
39
|
+
/** A `key: value` entry of an object literal. */
|
|
40
|
+
export interface Property {
|
|
41
|
+
key: string;
|
|
42
|
+
valueStart: number;
|
|
43
|
+
valueEnd: number;
|
|
44
|
+
}
|
|
45
|
+
/** The `key: value` entries of the object literal opening at `open`. */
|
|
46
|
+
export declare function properties(src: string, open: number, close: number): Property[];
|
|
47
|
+
/**
|
|
48
|
+
* Append entries to the literal `src[open..close]` and return the new text.
|
|
49
|
+
*
|
|
50
|
+
* `build` receives the indentation of the existing entries (or one level
|
|
51
|
+
* deeper than the closing bracket when there are none) and returns the lines
|
|
52
|
+
* to add, each already ending with its comma. `blankLine` separates the new
|
|
53
|
+
* entries from existing ones. A missing comma after the last existing entry
|
|
54
|
+
* is added.
|
|
55
|
+
*/
|
|
56
|
+
export declare function appendToLiteral(src: string, open: number, close: number, eol: string, build: (indent: string) => string[], blankLine?: boolean): string;
|
|
57
|
+
//# sourceMappingURL=source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../src/codemods/source.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAuDH,6DAA6D;AAC7D,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAwB5D;AAoBD,qEAAqE;AACrE,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAA;IACjB,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,uDAAuD;AACvD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,EAAE,CAoC3E;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAsBxD;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAgB5D;AAED,wEAAwE;AACxE,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAkB3D;AAED,iDAAiD;AACjD,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAA;IACX,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,wEAAwE;AACxE,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,QAAQ,EAAE,CAY/E;AAQD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,EAAE,EACnC,SAAS,UAAQ,GAChB,MAAM,CA0BR"}
|