@c9up/ream 0.2.0 → 0.2.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.
- package/dist/Ignitor.d.ts +0 -8
- package/dist/Ignitor.d.ts.map +1 -1
- package/dist/Ignitor.js +15 -1
- package/dist/Ignitor.js.map +1 -1
- package/dist/bodyparser/MultipartFile.d.ts +22 -12
- package/dist/bodyparser/MultipartFile.d.ts.map +1 -1
- package/dist/bodyparser/MultipartFile.js +42 -15
- package/dist/bodyparser/MultipartFile.js.map +1 -1
- package/dist/errors/aggregate.d.ts +24 -0
- package/dist/errors/aggregate.d.ts.map +1 -0
- package/dist/errors/aggregate.js +24 -0
- package/dist/errors/aggregate.js.map +1 -0
- package/dist/events/services/main.d.ts.map +1 -1
- package/dist/events/services/main.js +3 -10
- package/dist/events/services/main.js.map +1 -1
- package/dist/http/Exception.d.ts +76 -6
- package/dist/http/Exception.d.ts.map +1 -1
- package/dist/http/Exception.js +178 -85
- package/dist/http/Exception.js.map +1 -1
- package/dist/index.d.ts +10 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -4
- package/dist/index.js.map +1 -1
- package/dist/router/Router.js +1 -1
- package/dist/router/Router.js.map +1 -1
- package/dist/services/app.d.ts.map +1 -1
- package/dist/services/app.js +3 -21
- package/dist/services/app.js.map +1 -1
- package/dist/services/console.d.ts.map +1 -1
- package/dist/services/console.js +3 -19
- package/dist/services/console.js.map +1 -1
- package/dist/services/createServiceProxy.d.ts +19 -0
- package/dist/services/createServiceProxy.d.ts.map +1 -0
- package/dist/services/createServiceProxy.js +44 -0
- package/dist/services/createServiceProxy.js.map +1 -0
- package/dist/services/router.d.ts.map +1 -1
- package/dist/services/router.js +3 -12
- package/dist/services/router.js.map +1 -1
- package/dist/services/server.d.ts.map +1 -1
- package/dist/services/server.js +3 -22
- package/dist/services/server.js.map +1 -1
- package/dist/types/container.d.ts +64 -0
- package/dist/types/container.d.ts.map +1 -0
- package/dist/types/container.js +23 -0
- package/dist/types/container.js.map +1 -0
- package/events.win32-x64-msvc.node +0 -0
- package/index.win32-x64-msvc.node +0 -0
- package/package.json +52 -30
- package/scheduler.win32-x64-msvc.node +0 -0
- package/src/Ignitor.ts +15 -9
- package/src/bodyparser/MultipartFile.ts +43 -15
- package/src/errors/aggregate.ts +33 -0
- package/src/events/services/main.ts +6 -12
- package/src/http/Exception.ts +225 -99
- package/src/index.ts +15 -2
- package/src/router/Router.ts +1 -1
- package/src/services/app.ts +6 -23
- package/src/services/console.ts +6 -21
- package/src/services/createServiceProxy.ts +47 -0
- package/src/services/router.ts +6 -14
- package/src/services/server.ts +6 -24
- package/src/types/container.ts +66 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@c9up/ream",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Ream — Rust-powered Node.js application framework",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -11,6 +11,14 @@
|
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
12
|
"import": "./dist/index.js"
|
|
13
13
|
},
|
|
14
|
+
"./types": {
|
|
15
|
+
"types": "./dist/types/container.d.ts",
|
|
16
|
+
"import": "./dist/types/container.js"
|
|
17
|
+
},
|
|
18
|
+
"./exceptions": {
|
|
19
|
+
"types": "./dist/http/Exception.d.ts",
|
|
20
|
+
"import": "./dist/http/Exception.js"
|
|
21
|
+
},
|
|
14
22
|
"./console": {
|
|
15
23
|
"types": "./dist/console/index.d.ts",
|
|
16
24
|
"import": "./dist/console/index.js"
|
|
@@ -43,10 +51,42 @@
|
|
|
43
51
|
"types": "./dist/session/SessionMiddleware.d.ts",
|
|
44
52
|
"import": "./dist/session/SessionMiddleware.js"
|
|
45
53
|
},
|
|
54
|
+
"./helpers": {
|
|
55
|
+
"types": "./dist/helpers/index.d.ts",
|
|
56
|
+
"import": "./dist/helpers/index.js"
|
|
57
|
+
},
|
|
58
|
+
"./helpers/string": {
|
|
59
|
+
"types": "./dist/helpers/string.d.ts",
|
|
60
|
+
"import": "./dist/helpers/string.js"
|
|
61
|
+
},
|
|
62
|
+
"./helpers/is": {
|
|
63
|
+
"types": "./dist/helpers/is.d.ts",
|
|
64
|
+
"import": "./dist/helpers/is.js"
|
|
65
|
+
},
|
|
66
|
+
"./helpers/base64": {
|
|
67
|
+
"types": "./dist/helpers/base64.d.ts",
|
|
68
|
+
"import": "./dist/helpers/base64.js"
|
|
69
|
+
},
|
|
70
|
+
"./helpers/types": {
|
|
71
|
+
"types": "./dist/helpers/types.d.ts",
|
|
72
|
+
"import": "./dist/helpers/types.js"
|
|
73
|
+
},
|
|
74
|
+
"./testing": {
|
|
75
|
+
"types": "./dist/testing/TestClient.d.ts",
|
|
76
|
+
"import": "./dist/testing/TestClient.js"
|
|
77
|
+
},
|
|
78
|
+
"./bootstrap": {
|
|
79
|
+
"types": "./dist/bootstrap/hyper-server.d.ts",
|
|
80
|
+
"import": "./dist/bootstrap/hyper-server.js"
|
|
81
|
+
},
|
|
46
82
|
"./events": {
|
|
47
83
|
"types": "./dist/events/index.d.ts",
|
|
48
84
|
"import": "./dist/events/index.js"
|
|
49
85
|
},
|
|
86
|
+
"./health": {
|
|
87
|
+
"types": "./dist/health/index.d.ts",
|
|
88
|
+
"import": "./dist/health/index.js"
|
|
89
|
+
},
|
|
50
90
|
"./events/provider": {
|
|
51
91
|
"types": "./dist/events/EventsProvider.d.ts",
|
|
52
92
|
"import": "./dist/events/EventsProvider.js"
|
|
@@ -95,36 +135,18 @@
|
|
|
95
135
|
"types": "./dist/events/configure.d.ts",
|
|
96
136
|
"import": "./dist/events/configure.js"
|
|
97
137
|
},
|
|
98
|
-
"./helpers": {
|
|
99
|
-
"types": "./dist/helpers/index.d.ts",
|
|
100
|
-
"import": "./dist/helpers/index.js"
|
|
101
|
-
},
|
|
102
|
-
"./helpers/string": {
|
|
103
|
-
"types": "./dist/helpers/string.d.ts",
|
|
104
|
-
"import": "./dist/helpers/string.js"
|
|
105
|
-
},
|
|
106
|
-
"./helpers/is": {
|
|
107
|
-
"types": "./dist/helpers/is.d.ts",
|
|
108
|
-
"import": "./dist/helpers/is.js"
|
|
109
|
-
},
|
|
110
|
-
"./helpers/base64": {
|
|
111
|
-
"types": "./dist/helpers/base64.d.ts",
|
|
112
|
-
"import": "./dist/helpers/base64.js"
|
|
113
|
-
},
|
|
114
|
-
"./helpers/types": {
|
|
115
|
-
"types": "./dist/helpers/types.d.ts",
|
|
116
|
-
"import": "./dist/helpers/types.js"
|
|
117
|
-
},
|
|
118
|
-
"./testing": {
|
|
119
|
-
"types": "./dist/testing/TestClient.d.ts",
|
|
120
|
-
"import": "./dist/testing/TestClient.js"
|
|
121
|
-
},
|
|
122
|
-
"./bootstrap": {
|
|
123
|
-
"types": "./dist/bootstrap/hyper-server.d.ts",
|
|
124
|
-
"import": "./dist/bootstrap/hyper-server.js"
|
|
125
|
-
},
|
|
126
138
|
"./tsconfig.app.json": "./tsconfig.app.json",
|
|
127
|
-
"./swcrc.app.json": "./swcrc.app.json"
|
|
139
|
+
"./swcrc.app.json": "./swcrc.app.json",
|
|
140
|
+
"./tsconfig.package.json": "./tsconfig.package.json",
|
|
141
|
+
"./tsconfig.client.json": "./tsconfig.client.json",
|
|
142
|
+
"./session_middleware": {
|
|
143
|
+
"types": "./dist/session/SessionMiddleware.d.ts",
|
|
144
|
+
"import": "./dist/session/SessionMiddleware.js"
|
|
145
|
+
},
|
|
146
|
+
"./bodyparser_middleware": {
|
|
147
|
+
"types": "./dist/bodyparser/BodyParserMiddleware.d.ts",
|
|
148
|
+
"import": "./dist/bodyparser/BodyParserMiddleware.js"
|
|
149
|
+
}
|
|
128
150
|
},
|
|
129
151
|
"files": [
|
|
130
152
|
"LICENSE",
|
|
Binary file
|
package/src/Ignitor.ts
CHANGED
|
@@ -142,14 +142,6 @@ export interface TestsConfig {
|
|
|
142
142
|
* `tests/bootstrap.ts`; that stays the default here, and this overrides it.
|
|
143
143
|
*/
|
|
144
144
|
bootstrap?: string
|
|
145
|
-
/**
|
|
146
|
-
* Point `@japa/runner/core` at helix's shim in every worker, so official Japa
|
|
147
|
-
* plugins (`@japa/assert`, …) instrument the runner that is actually running.
|
|
148
|
-
*
|
|
149
|
-
* Off by default: redirecting a package specifier is not something to do
|
|
150
|
-
* behind a user's back, and a project with no Japa plugin gains nothing.
|
|
151
|
-
*/
|
|
152
|
-
japaPlugins?: boolean
|
|
153
145
|
}
|
|
154
146
|
|
|
155
147
|
/** defineConfig helper — like AdonisJS defineConfig(). */
|
|
@@ -269,6 +261,9 @@ export class Ignitor {
|
|
|
269
261
|
// registry" and say something useful in each case.
|
|
270
262
|
this.app.container.singleton('migrations', () => this.migrations)
|
|
271
263
|
this.app.container.singleton('app', () => this.app)
|
|
264
|
+
// AdonisJS binds the config store too, so code that only needs settings can
|
|
265
|
+
// resolve `config` instead of taking the whole application.
|
|
266
|
+
this.app.container.singleton('config', () => this.app.config)
|
|
272
267
|
// The HttpContext CLASS, so an integration provider can extend it the way
|
|
273
268
|
// AdonisJS does — `HttpContext.getter('view', …)` is how the view layer
|
|
274
269
|
// attaches `ctx.view`. Exported from the barrel too, but a provider that
|
|
@@ -733,7 +728,18 @@ export class Ignitor {
|
|
|
733
728
|
for (const file of files) {
|
|
734
729
|
const key = basename(file).replace(/\.(ts|js)$/, '')
|
|
735
730
|
const mod = await import(pathToFileURL(join(configDir, file)).href)
|
|
736
|
-
|
|
731
|
+
// A config file that declares `export default` owns the value it exports,
|
|
732
|
+
// even when that value is `undefined` — that is how a module says "I am
|
|
733
|
+
// not configured", and a provider's `if (!config) return` guard has to be
|
|
734
|
+
// able to see it. Testing the binding rather than the value is what keeps
|
|
735
|
+
// that readable; `mod.default ?? mod` turns the absent value back into the
|
|
736
|
+
// truthy namespace and makes the guard unreachable.
|
|
737
|
+
//
|
|
738
|
+
// Without a `default` binding, the named exports become the config, which
|
|
739
|
+
// is what AdonisJS does (`fsImportAll`). Spread rather than stored as-is:
|
|
740
|
+
// an ESM namespace is sealed and null-prototype, so a later merge into
|
|
741
|
+
// this entry would fail on it.
|
|
742
|
+
this.app.config.set(key, 'default' in mod ? mod.default : { ...mod })
|
|
737
743
|
}
|
|
738
744
|
}
|
|
739
745
|
|
|
@@ -19,22 +19,49 @@ export class MultipartFile {
|
|
|
19
19
|
readonly clientName: string
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
* The PRIMARY mime type
|
|
23
|
-
*
|
|
22
|
+
* The PRIMARY mime type — `image` for `image/png`. Pair it with
|
|
23
|
+
* {@link subtype}, as AdonisJS does.
|
|
24
24
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
25
|
+
* DERIVED FROM THE MAGIC BYTES when they can be read, and only from the
|
|
26
|
+
* Content-Type header when they cannot — upstream's precedence, and the one
|
|
27
|
+
* that matters: the header is written by the client, so a `.exe` announced as
|
|
28
|
+
* `image/png` would otherwise sail through a mime allowlist. A renamed file
|
|
29
|
+
* reports what it actually is.
|
|
29
30
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
31
|
+
* BREAKING as of 0.2.0: it used to hold the whole `image/png`. TypeScript
|
|
32
|
+
* cannot catch a comparison against a full mime string — `file.type ===
|
|
33
|
+
* 'image/png'` still compiles and simply never matches. Use {@link mime}.
|
|
33
34
|
*/
|
|
34
|
-
|
|
35
|
+
get type(): string | undefined {
|
|
36
|
+
return this.#mimeParts()[0]
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** The mime SUBTYPE — `png` for `image/png`. Same source as {@link type}. */
|
|
40
|
+
get subtype(): string | undefined {
|
|
41
|
+
return this.#mimeParts()[1]
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The full mime to validate against — `image/png`.
|
|
46
|
+
*
|
|
47
|
+
* What an allowlist wants, and the reason this exists: splitting the mime for
|
|
48
|
+
* upstream parity left every caller re-joining it by hand, and a caller that
|
|
49
|
+
* forgot got a filter that silently matched nothing. Same trustworthy source
|
|
50
|
+
* as {@link type}.
|
|
51
|
+
*/
|
|
52
|
+
get mime(): string | undefined {
|
|
53
|
+
const [type, subtype] = this.#mimeParts()
|
|
54
|
+
if (!type) return undefined
|
|
55
|
+
return subtype ? `${type}/${subtype}` : type
|
|
56
|
+
}
|
|
35
57
|
|
|
36
|
-
/**
|
|
37
|
-
|
|
58
|
+
/** Split the trustworthy mime once, detected bytes first, header second. */
|
|
59
|
+
#mimeParts(): [string | undefined, string | undefined] {
|
|
60
|
+
const source = this.#detected?.mime ?? this.#headerMime
|
|
61
|
+
if (!source) return [undefined, undefined]
|
|
62
|
+
const [type, subtype] = source.split(';')[0].trim().split('/')
|
|
63
|
+
return [type || undefined, subtype || undefined]
|
|
64
|
+
}
|
|
38
65
|
|
|
39
66
|
/**
|
|
40
67
|
* The part's headers.
|
|
@@ -78,6 +105,9 @@ export class MultipartFile {
|
|
|
78
105
|
/** Rules set through `sizeLimit` / `allowedExtensions`, used by a bare `validate()`. */
|
|
79
106
|
#validationOptions: FileValidationOptions = {}
|
|
80
107
|
|
|
108
|
+
/** The Content-Type the client sent — attacker-controlled, the fallback only. */
|
|
109
|
+
readonly #headerMime: string
|
|
110
|
+
|
|
81
111
|
/** Magic-byte fingerprint — set by {@link detectType}; absent for content `file-type` can't detect (text: txt/csv/svg/json). */
|
|
82
112
|
#detected?: { ext: string; mime: string }
|
|
83
113
|
|
|
@@ -90,9 +120,7 @@ export class MultipartFile {
|
|
|
90
120
|
this.fieldName = options.fieldName
|
|
91
121
|
this.clientName = options.clientName
|
|
92
122
|
this.headers = { 'content-type': options.type }
|
|
93
|
-
|
|
94
|
-
this.type = type || undefined
|
|
95
|
-
this.subtype = subtype || undefined
|
|
123
|
+
this.#headerMime = options.type
|
|
96
124
|
this.content = options.content
|
|
97
125
|
this.size = options.content.length
|
|
98
126
|
const segments = options.clientName.split('.')
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The framework's exceptions, in one bag.
|
|
3
|
+
*
|
|
4
|
+
* AdonisJS exposes `import { errors } from '@adonisjs/core'` (and one bag per
|
|
5
|
+
* module) so an app can branch on `error instanceof errors.E_ROUTE_NOT_FOUND`
|
|
6
|
+
* without importing each class by name. The flat named exports stay — this is
|
|
7
|
+
* the shape a migrating app already writes.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { EnvValidationException } from '../env/Env.js'
|
|
11
|
+
import {
|
|
12
|
+
E_FORBIDDEN,
|
|
13
|
+
E_HTTP_EXCEPTION,
|
|
14
|
+
E_HTTP_REQUEST_ABORTED,
|
|
15
|
+
E_ROUTE_NOT_FOUND,
|
|
16
|
+
E_ROW_NOT_FOUND,
|
|
17
|
+
E_UNAUTHORIZED,
|
|
18
|
+
E_VALIDATION_ERROR,
|
|
19
|
+
} from '../http/Exception.js'
|
|
20
|
+
import { E_INSECURE_APP_KEY, E_MISSING_APP_KEY } from '../security/CookieSigner.js'
|
|
21
|
+
|
|
22
|
+
export const errors = {
|
|
23
|
+
E_FORBIDDEN,
|
|
24
|
+
E_HTTP_EXCEPTION,
|
|
25
|
+
E_HTTP_REQUEST_ABORTED,
|
|
26
|
+
E_INSECURE_APP_KEY,
|
|
27
|
+
E_INVALID_ENV_VARIABLES: EnvValidationException,
|
|
28
|
+
E_MISSING_APP_KEY,
|
|
29
|
+
E_ROUTE_NOT_FOUND,
|
|
30
|
+
E_ROW_NOT_FOUND,
|
|
31
|
+
E_UNAUTHORIZED,
|
|
32
|
+
E_VALIDATION_ERROR,
|
|
33
|
+
} as const
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* Populated by `EventsProvider.boot()`.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
import { createServiceProxy } from '../../services/createServiceProxy.js'
|
|
12
13
|
import type { Emitter } from '../Emitter.js'
|
|
13
14
|
|
|
14
15
|
let instance: Emitter | undefined
|
|
@@ -23,17 +24,10 @@ export function getEmitter(): Emitter | undefined {
|
|
|
23
24
|
return instance
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
const emitter: Emitter =
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
'Check that `@c9up/ream/events/provider` is listed in your reamrc.ts providers.',
|
|
32
|
-
)
|
|
33
|
-
}
|
|
34
|
-
const value = Reflect.get(instance, prop, instance)
|
|
35
|
-
return typeof value === 'function' ? value.bind(instance) : value
|
|
36
|
-
},
|
|
37
|
-
})
|
|
27
|
+
const emitter: Emitter = createServiceProxy<Emitter>(
|
|
28
|
+
() => instance,
|
|
29
|
+
'[ream:events] Emitter singleton accessed before EventsProvider.boot() ran. ' +
|
|
30
|
+
'Check that `@c9up/ream/events/provider` is listed in your reamrc.ts providers.',
|
|
31
|
+
)
|
|
38
32
|
|
|
39
33
|
export default emitter
|