ingenium 0.0.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.
- package/LICENSE +21 -0
- package/README.md +943 -0
- package/dist/index.cjs +7078 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +4262 -0
- package/dist/index.d.ts +4262 -0
- package/dist/index.js +6963 -0
- package/dist/index.js.map +1 -0
- package/package.json +47 -0
- package/src/api-key/middleware.ts +157 -0
- package/src/api-key/types.ts +37 -0
- package/src/app/scope.ts +392 -0
- package/src/app.ts +1752 -0
- package/src/body/limit.ts +21 -0
- package/src/body/middleware.ts +30 -0
- package/src/body/multipart-types.ts +40 -0
- package/src/body/multipart.ts +254 -0
- package/src/context/body.ts +324 -0
- package/src/context/context.ts +650 -0
- package/src/context/cookies.ts +282 -0
- package/src/context/pool.ts +32 -0
- package/src/cors/middleware.ts +182 -0
- package/src/cors/types.ts +79 -0
- package/src/cron/parser.ts +311 -0
- package/src/cron/registry.ts +49 -0
- package/src/cron/scheduler.ts +153 -0
- package/src/csrf/middleware.ts +224 -0
- package/src/csrf/types.ts +65 -0
- package/src/errors.ts +148 -0
- package/src/idempotency/middleware.ts +197 -0
- package/src/idempotency/store.ts +70 -0
- package/src/idempotency/types.ts +87 -0
- package/src/index.ts +328 -0
- package/src/jobs/queue.ts +306 -0
- package/src/jobs/registry.ts +82 -0
- package/src/jobs/store-memory.ts +113 -0
- package/src/jobs/types.ts +135 -0
- package/src/jwt/jwks.ts +143 -0
- package/src/jwt/middleware.ts +313 -0
- package/src/jwt/types.ts +137 -0
- package/src/jwt/verify.ts +370 -0
- package/src/middleware/compose.ts +94 -0
- package/src/middleware/types.ts +37 -0
- package/src/negotiation/accept.ts +159 -0
- package/src/negotiation/etag.ts +30 -0
- package/src/negotiation/format.ts +88 -0
- package/src/negotiation/fresh.ts +89 -0
- package/src/negotiation/json-etag.ts +122 -0
- package/src/negotiation/negotiate.ts +97 -0
- package/src/openapi/describe.ts +79 -0
- package/src/openapi/extract-params.ts +62 -0
- package/src/openapi/generate.ts +251 -0
- package/src/openapi/handler.ts +73 -0
- package/src/openapi/types.ts +145 -0
- package/src/plugin/decorators.ts +100 -0
- package/src/plugin/hooks.ts +114 -0
- package/src/plugin/types.ts +189 -0
- package/src/problem/middleware.ts +55 -0
- package/src/problem/serialize.ts +121 -0
- package/src/problem/types.ts +68 -0
- package/src/proxy/trust.ts +247 -0
- package/src/rate-limit/middleware.ts +72 -0
- package/src/rate-limit/store.ts +129 -0
- package/src/rate-limit/types.ts +60 -0
- package/src/response/reflect.ts +93 -0
- package/src/router/router.ts +284 -0
- package/src/router/trie.ts +309 -0
- package/src/router/types.ts +54 -0
- package/src/schema/standard.ts +67 -0
- package/src/session/middleware.ts +379 -0
- package/src/session/store-memory.ts +79 -0
- package/src/session/types.ts +95 -0
- package/src/sinatra/filters.ts +129 -0
- package/src/sinatra/top-level.ts +151 -0
- package/src/sse/keep-alive.ts +52 -0
- package/src/sse/sse.ts +115 -0
- package/src/static/middleware.ts +254 -0
- package/src/static/types.ts +31 -0
- package/src/transport/http2-helpers.ts +242 -0
- package/src/transport/http2.ts +316 -0
- package/src/transport/node.ts +261 -0
- package/src/transport/shutdown.ts +86 -0
- package/src/transport/types.ts +72 -0
- package/src/util/safe-json.ts +66 -0
- package/src/ws/index.ts +164 -0
- package/src/ws/middleware.ts +178 -0
- package/src/ws/types.ts +52 -0
- package/src/ws/ws-node-adapter.ts +162 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { CachedResponse, IdempotencyStore } from './types.ts'
|
|
2
|
+
|
|
3
|
+
interface Entry {
|
|
4
|
+
value: CachedResponse
|
|
5
|
+
expiresAt: number
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* In-process idempotency cache. Suitable for single-replica deployments and
|
|
10
|
+
* tests; back with Redis when running multiple replicas behind a load
|
|
11
|
+
* balancer (responses cached on one replica won't replay on another).
|
|
12
|
+
*
|
|
13
|
+
* A periodic sweep removes expired entries so long-lived processes don't
|
|
14
|
+
* leak memory across forgotten keys. The sweep timer is `.unref()`'d, so
|
|
15
|
+
* it never keeps the Node event loop alive.
|
|
16
|
+
*/
|
|
17
|
+
export class IdempotencyMemoryStore implements IdempotencyStore {
|
|
18
|
+
private readonly map: Map<string, Entry> = new Map()
|
|
19
|
+
private sweeper: NodeJS.Timeout | null = null
|
|
20
|
+
private sweepIntervalMs = 0
|
|
21
|
+
|
|
22
|
+
get(key: string): Promise<CachedResponse | null> {
|
|
23
|
+
const entry = this.map.get(key)
|
|
24
|
+
if (!entry) return Promise.resolve(null)
|
|
25
|
+
if (Date.now() >= entry.expiresAt) {
|
|
26
|
+
this.map.delete(key)
|
|
27
|
+
return Promise.resolve(null)
|
|
28
|
+
}
|
|
29
|
+
return Promise.resolve(entry.value)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
set(key: string, value: CachedResponse, ttlMs: number): Promise<void> {
|
|
33
|
+
this.map.set(key, { value, expiresAt: Date.now() + ttlMs })
|
|
34
|
+
this.ensureSweeper(ttlMs)
|
|
35
|
+
return Promise.resolve()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
delete(key: string): Promise<void> {
|
|
39
|
+
this.map.delete(key)
|
|
40
|
+
return Promise.resolve()
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Stop the cleanup interval. Safe to call multiple times. Mostly useful
|
|
45
|
+
* in tests; production usage doesn't need this because the timer is
|
|
46
|
+
* already unref'd.
|
|
47
|
+
*/
|
|
48
|
+
destroy(): void {
|
|
49
|
+
if (this.sweeper) {
|
|
50
|
+
clearInterval(this.sweeper)
|
|
51
|
+
this.sweeper = null
|
|
52
|
+
}
|
|
53
|
+
this.map.clear()
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private ensureSweeper(ttlMs: number): void {
|
|
57
|
+
if (this.sweeper && this.sweepIntervalMs === ttlMs) return
|
|
58
|
+
if (this.sweeper) clearInterval(this.sweeper)
|
|
59
|
+
this.sweepIntervalMs = ttlMs
|
|
60
|
+
this.sweeper = setInterval(() => this.sweep(), ttlMs)
|
|
61
|
+
if (typeof this.sweeper.unref === 'function') this.sweeper.unref()
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
private sweep(): void {
|
|
65
|
+
const now = Date.now()
|
|
66
|
+
for (const [key, entry] of this.map) {
|
|
67
|
+
if (now >= entry.expiresAt) this.map.delete(key)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { Buffer } from 'node:buffer'
|
|
2
|
+
import type { IngeniumContext } from '../context/context.ts'
|
|
3
|
+
import type { HttpMethod } from '../router/types.ts'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A frozen snapshot of an outgoing response. Captured AFTER the handler
|
|
7
|
+
* runs and stored in the idempotency cache for replay on retry.
|
|
8
|
+
*
|
|
9
|
+
* `body` is `null` only for empty responses (e.g. 204).
|
|
10
|
+
*/
|
|
11
|
+
export interface CachedResponse {
|
|
12
|
+
/** HTTP status code from the original response. */
|
|
13
|
+
statusCode: number
|
|
14
|
+
/** Plain header bag (lowercased keys), copied from `ctx._headers`. */
|
|
15
|
+
headers: Record<string, string | string[]>
|
|
16
|
+
/** Serialized body. `null` when the original response had no body. */
|
|
17
|
+
body: string | Buffer | null
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Pluggable storage for the idempotency cache. Default impl is in-memory;
|
|
22
|
+
* swap for Redis/etc. when running multiple replicas.
|
|
23
|
+
*/
|
|
24
|
+
export interface IdempotencyStore {
|
|
25
|
+
/** Returns the cached response for `key` or `null` if missing/expired. */
|
|
26
|
+
get(key: string): Promise<CachedResponse | null>
|
|
27
|
+
/** Persist `value` under `key` for `ttlMs` milliseconds. */
|
|
28
|
+
set(key: string, value: CachedResponse, ttlMs: number): Promise<void>
|
|
29
|
+
/** Remove `key`. Idempotent — does nothing if absent. */
|
|
30
|
+
delete(key: string): Promise<void>
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Options accepted by `ingenium.idempotency(...)`. */
|
|
34
|
+
export interface IdempotencyOptions {
|
|
35
|
+
/**
|
|
36
|
+
* Header name carrying the idempotency key. Comparison is
|
|
37
|
+
* case-insensitive (Node lowercases header names automatically).
|
|
38
|
+
* Default `'Idempotency-Key'`.
|
|
39
|
+
*/
|
|
40
|
+
header?: string
|
|
41
|
+
|
|
42
|
+
/** Backing cache. Default: an in-process `IdempotencyMemoryStore`. */
|
|
43
|
+
store?: IdempotencyStore
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Time-to-live for cached responses, in seconds. After this elapses, the
|
|
47
|
+
* same key replays nothing and the handler runs again. Default `86400`
|
|
48
|
+
* (24h) — matches Stripe's documented behavior.
|
|
49
|
+
*/
|
|
50
|
+
ttlSeconds?: number
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Namespace function — distinguishes keys belonging to different callers
|
|
54
|
+
* so two clients can independently use the same idempotency-key string.
|
|
55
|
+
* Default uses the `Authorization` header (or `'anon'` when absent).
|
|
56
|
+
*/
|
|
57
|
+
scope?: (ctx: IngeniumContext) => string
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* HTTP methods eligible for idempotency caching. Default: `['POST',
|
|
61
|
+
* 'PATCH', 'DELETE']` — only mutating methods. Safe methods (GET/HEAD/
|
|
62
|
+
* OPTIONS) and idempotent-by-spec PUT are skipped by default; opt in by
|
|
63
|
+
* extending this list if you need PUT semantics cached too.
|
|
64
|
+
*/
|
|
65
|
+
methods?: readonly HttpMethod[]
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Predicate deciding which response status codes are cacheable. Default:
|
|
69
|
+
* `(s) => s >= 200 && s < 500` — caches 2xx/3xx/4xx but NOT 5xx, matching
|
|
70
|
+
* Stripe's documented behavior. The intent: a transient 500 (DB blip,
|
|
71
|
+
* deploy race) must NOT be cached for the entire TTL — every retry would
|
|
72
|
+
* replay the same failure and the user would be permanently broken until
|
|
73
|
+
* the cache expires. Validation errors (4xx) are deterministic and worth
|
|
74
|
+
* caching. Override to opt in to 5xx caching or tighten further.
|
|
75
|
+
*/
|
|
76
|
+
cacheable?: (statusCode: number) => boolean
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Resolved options after defaults have been applied. Internal. */
|
|
80
|
+
export interface ResolvedIdempotencyOptions {
|
|
81
|
+
header: string
|
|
82
|
+
store: IdempotencyStore
|
|
83
|
+
ttlMs: number
|
|
84
|
+
scope: (ctx: IngeniumContext) => string
|
|
85
|
+
methodSet: ReadonlySet<HttpMethod>
|
|
86
|
+
cacheable: (statusCode: number) => boolean
|
|
87
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ingenium — Express DX, Hono/Fastify throughput.
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { makeIngeniumFactory, type IngeniumFactory } from './app.ts'
|
|
8
|
+
import { jsonMiddleware, urlencodedMiddleware } from './body/middleware.ts'
|
|
9
|
+
import { staticMiddleware } from './static/middleware.ts'
|
|
10
|
+
import { corsMiddleware } from './cors/middleware.ts'
|
|
11
|
+
import { sse } from './sse/sse.ts'
|
|
12
|
+
import { rateLimit } from './rate-limit/middleware.ts'
|
|
13
|
+
import { csrfMiddleware } from './csrf/middleware.ts'
|
|
14
|
+
import { problemDetailsMiddleware } from './problem/middleware.ts'
|
|
15
|
+
import { idempotencyMiddleware } from './idempotency/middleware.ts'
|
|
16
|
+
import { jwtMiddleware } from './jwt/middleware.ts'
|
|
17
|
+
import { apiKeyMiddleware } from './api-key/middleware.ts'
|
|
18
|
+
import { openapiHandler } from './openapi/handler.ts'
|
|
19
|
+
|
|
20
|
+
// ───── App + Router ────────────────────────────────────────────────────────
|
|
21
|
+
export {
|
|
22
|
+
IngeniumApp,
|
|
23
|
+
type IngeniumAppOptions,
|
|
24
|
+
type IngeniumErrorHandler,
|
|
25
|
+
type RouteOptions,
|
|
26
|
+
type InjectRequest,
|
|
27
|
+
type InjectResponse,
|
|
28
|
+
} from './app.ts'
|
|
29
|
+
export { Router, RouteBuilder } from './router/router.ts'
|
|
30
|
+
|
|
31
|
+
// ───── Context + Body ──────────────────────────────────────────────────────
|
|
32
|
+
export { IngeniumContext, type ResponseBody, type IngeniumQuery } from './context/context.ts'
|
|
33
|
+
export type {
|
|
34
|
+
IngeniumCookies,
|
|
35
|
+
CookieSetOptions,
|
|
36
|
+
CookieGetOptions,
|
|
37
|
+
} from './context/cookies.ts'
|
|
38
|
+
export { IngeniumBody, type ParseSchema, type SafeParseSchema } from './context/body.ts'
|
|
39
|
+
export { IngeniumContextPool } from './context/pool.ts'
|
|
40
|
+
export type {
|
|
41
|
+
MultipartFile,
|
|
42
|
+
MultipartOptions,
|
|
43
|
+
MultipartResult,
|
|
44
|
+
} from './body/multipart-types.ts'
|
|
45
|
+
|
|
46
|
+
// ───── Standard Schema (https://standardschema.dev) ────────────────────────
|
|
47
|
+
export {
|
|
48
|
+
isStandardSchema,
|
|
49
|
+
type StandardSchemaV1,
|
|
50
|
+
type StandardResult,
|
|
51
|
+
type StandardIssue,
|
|
52
|
+
type StandardPathSegment,
|
|
53
|
+
type StandardSuccessResult,
|
|
54
|
+
type StandardFailureResult,
|
|
55
|
+
type StandardSchemaV1Props,
|
|
56
|
+
} from './schema/standard.ts'
|
|
57
|
+
|
|
58
|
+
// ───── Middleware + Handler types ──────────────────────────────────────────
|
|
59
|
+
export type { IngeniumMiddleware, IngeniumHandler, ComposedHandler } from './middleware/types.ts'
|
|
60
|
+
export { compose, composeWithHandler } from './middleware/compose.ts'
|
|
61
|
+
|
|
62
|
+
// ───── Router types ────────────────────────────────────────────────────────
|
|
63
|
+
export type { HttpMethod, ExtractParams } from './router/types.ts'
|
|
64
|
+
export { HTTP_METHODS } from './router/types.ts'
|
|
65
|
+
export { RouterTrie, TrieNode, type MatchResult, type MatchMiss } from './router/trie.ts'
|
|
66
|
+
|
|
67
|
+
// ───── Static-file middleware ──────────────────────────────────────────────
|
|
68
|
+
export { staticMiddleware as static_ } from './static/middleware.ts'
|
|
69
|
+
export type { StaticOptions } from './static/types.ts'
|
|
70
|
+
|
|
71
|
+
// ───── CORS middleware ─────────────────────────────────────────────────────
|
|
72
|
+
export { corsMiddleware as cors_ } from './cors/middleware.ts'
|
|
73
|
+
export type { CorsOptions, CorsOrigin, CorsOriginFn } from './cors/types.ts'
|
|
74
|
+
|
|
75
|
+
// ───── Errors ──────────────────────────────────────────────────────────────
|
|
76
|
+
export {
|
|
77
|
+
IngeniumError,
|
|
78
|
+
IngeniumNotFoundError,
|
|
79
|
+
IngeniumUnauthorizedError,
|
|
80
|
+
IngeniumMethodNotAllowedError,
|
|
81
|
+
IngeniumPayloadTooLargeError,
|
|
82
|
+
IngeniumValidationError,
|
|
83
|
+
IngeniumBadRequestError,
|
|
84
|
+
IngeniumHeaderInjectionError,
|
|
85
|
+
IngeniumUnserializableError,
|
|
86
|
+
IngeniumTimeoutError,
|
|
87
|
+
IngeniumHaltError,
|
|
88
|
+
} from './errors.ts'
|
|
89
|
+
|
|
90
|
+
// ───── JSON serialization helpers ──────────────────────────────────────────
|
|
91
|
+
export { safeJsonStringify, type SafeJsonStringifyOptions } from './util/safe-json.ts'
|
|
92
|
+
|
|
93
|
+
// ───── Transport (mainly for advanced users / tests) ───────────────────────
|
|
94
|
+
export type { Transport, TransportHooks, ListeningServer, CloseOptions } from './transport/types.ts'
|
|
95
|
+
export { NodeAdapter } from './transport/node.ts'
|
|
96
|
+
export { Http2Adapter, Http2cAdapter, type Http2AdapterOptions } from './transport/http2.ts'
|
|
97
|
+
export { gracefulShutdown, type ShutdownOptions } from './transport/shutdown.ts'
|
|
98
|
+
|
|
99
|
+
// ───── Trust-proxy ─────────────────────────────────────────────────────────
|
|
100
|
+
export { resolveForwarded, type TrustProxy, type ForwardedInfo } from './proxy/trust.ts'
|
|
101
|
+
|
|
102
|
+
// ───── Server-Sent Events helper ───────────────────────────────────────────
|
|
103
|
+
export { sse, type SseStream, type SseEvent } from './sse/sse.ts'
|
|
104
|
+
export { startKeepAlive } from './sse/keep-alive.ts'
|
|
105
|
+
|
|
106
|
+
// ───── Rate-limit middleware ───────────────────────────────────────────────
|
|
107
|
+
export { rateLimit } from './rate-limit/middleware.ts'
|
|
108
|
+
export { MemoryStore as RateLimitMemoryStore } from './rate-limit/store.ts'
|
|
109
|
+
export type { RateLimitOptions, RateLimitStore } from './rate-limit/types.ts'
|
|
110
|
+
|
|
111
|
+
// ───── CSRF middleware ─────────────────────────────────────────────────────
|
|
112
|
+
export { csrfMiddleware, IngeniumCsrfError } from './csrf/middleware.ts'
|
|
113
|
+
export type { CsrfOptions, CsrfStorage, CsrfCookieOptions, CsrfValueReader } from './csrf/types.ts'
|
|
114
|
+
|
|
115
|
+
// ───── Content negotiation ─────────────────────────────────────────────────
|
|
116
|
+
export {
|
|
117
|
+
parseAcceptHeader,
|
|
118
|
+
selectBest,
|
|
119
|
+
expandShorthand,
|
|
120
|
+
sortByPreference,
|
|
121
|
+
type ParsedAccept,
|
|
122
|
+
} from './negotiation/accept.ts'
|
|
123
|
+
export {
|
|
124
|
+
accepts,
|
|
125
|
+
acceptsCharsets,
|
|
126
|
+
acceptsLanguages,
|
|
127
|
+
acceptsEncodings,
|
|
128
|
+
type NegotiableCtx,
|
|
129
|
+
} from './negotiation/negotiate.ts'
|
|
130
|
+
export {
|
|
131
|
+
formatResponse,
|
|
132
|
+
type FormatHandlers,
|
|
133
|
+
type FormattableCtx,
|
|
134
|
+
} from './negotiation/format.ts'
|
|
135
|
+
export { isFresh, type HeaderBag } from './negotiation/fresh.ts'
|
|
136
|
+
export { computeEtag } from './negotiation/etag.ts'
|
|
137
|
+
export {
|
|
138
|
+
respondJsonWithEtag,
|
|
139
|
+
type JsonEtagOptions,
|
|
140
|
+
type JsonEtagCtx,
|
|
141
|
+
} from './negotiation/json-etag.ts'
|
|
142
|
+
|
|
143
|
+
// ───── RFC 7807 Problem Details middleware ─────────────────────────────────
|
|
144
|
+
export { problemDetailsMiddleware } from './problem/middleware.ts'
|
|
145
|
+
export { toProblemDetails } from './problem/serialize.ts'
|
|
146
|
+
export type { ProblemDetails, ProblemDetailsOptions } from './problem/types.ts'
|
|
147
|
+
|
|
148
|
+
// ───── Idempotency-Key middleware ──────────────────────────────────────────
|
|
149
|
+
export { idempotencyMiddleware } from './idempotency/middleware.ts'
|
|
150
|
+
export { IdempotencyMemoryStore } from './idempotency/store.ts'
|
|
151
|
+
export type {
|
|
152
|
+
CachedResponse,
|
|
153
|
+
IdempotencyOptions,
|
|
154
|
+
IdempotencyStore,
|
|
155
|
+
} from './idempotency/types.ts'
|
|
156
|
+
|
|
157
|
+
// ───── JWT middleware ──────────────────────────────────────────────────────
|
|
158
|
+
export { jwtMiddleware } from './jwt/middleware.ts'
|
|
159
|
+
export { verifyJwt } from './jwt/verify.ts'
|
|
160
|
+
export { fetchJwks, clearJwksCache } from './jwt/jwks.ts'
|
|
161
|
+
export type {
|
|
162
|
+
JwtAlgorithm,
|
|
163
|
+
JwtHeader,
|
|
164
|
+
JwtKey,
|
|
165
|
+
JwtOptions,
|
|
166
|
+
JwtSecret,
|
|
167
|
+
JwtSecretResolver,
|
|
168
|
+
JwtTokenReader,
|
|
169
|
+
JwtVerified,
|
|
170
|
+
JwtLogger,
|
|
171
|
+
} from './jwt/types.ts'
|
|
172
|
+
|
|
173
|
+
// ───── API-key middleware ──────────────────────────────────────────────────
|
|
174
|
+
export { apiKeyMiddleware } from './api-key/middleware.ts'
|
|
175
|
+
export type { ApiKeyOptions, ApiKeyValidator, ApiKeyLogger } from './api-key/types.ts'
|
|
176
|
+
|
|
177
|
+
// ───── OpenAPI 3.1 spec generation ─────────────────────────────────────────
|
|
178
|
+
export { generateOpenApi } from './openapi/generate.ts'
|
|
179
|
+
export type { GenerateOpenApiOptions } from './openapi/generate.ts'
|
|
180
|
+
export { openapiHandler } from './openapi/handler.ts'
|
|
181
|
+
export type { RouteDescriptor } from './openapi/describe.ts'
|
|
182
|
+
export type {
|
|
183
|
+
OpenApiSpec,
|
|
184
|
+
PathItem,
|
|
185
|
+
Operation,
|
|
186
|
+
Parameter,
|
|
187
|
+
RequestBody,
|
|
188
|
+
Response as OpenApiResponse,
|
|
189
|
+
Schema as OpenApiSchema,
|
|
190
|
+
Info as OpenApiInfo,
|
|
191
|
+
Server as OpenApiServer,
|
|
192
|
+
Tag as OpenApiTag,
|
|
193
|
+
Components as OpenApiComponents,
|
|
194
|
+
SecurityScheme as OpenApiSecurityScheme,
|
|
195
|
+
SecurityRequirement as OpenApiSecurityRequirement,
|
|
196
|
+
} from './openapi/types.ts'
|
|
197
|
+
|
|
198
|
+
// ───── Background jobs ─────────────────────────────────────────────────────
|
|
199
|
+
export { IngeniumQueue } from './jobs/queue.ts'
|
|
200
|
+
export { QueueRegistry } from './jobs/registry.ts'
|
|
201
|
+
export { MemoryQueueStore } from './jobs/store-memory.ts'
|
|
202
|
+
export type {
|
|
203
|
+
QueueOptions,
|
|
204
|
+
QueueWorker,
|
|
205
|
+
QueueStore,
|
|
206
|
+
RetryPolicy,
|
|
207
|
+
FailedJob,
|
|
208
|
+
JobHandle,
|
|
209
|
+
RegisteredQueue,
|
|
210
|
+
} from './jobs/types.ts'
|
|
211
|
+
|
|
212
|
+
// ───── Cron scheduling ─────────────────────────────────────────────────────
|
|
213
|
+
export { IngeniumCronJob } from './cron/scheduler.ts'
|
|
214
|
+
export type { CronHandler, CronOptions } from './cron/scheduler.ts'
|
|
215
|
+
export { CronRegistry } from './cron/registry.ts'
|
|
216
|
+
export { parseCronSpec, nextFireFrom } from './cron/parser.ts'
|
|
217
|
+
export type { CronMatch } from './cron/parser.ts'
|
|
218
|
+
|
|
219
|
+
// ───── Session middleware ──────────────────────────────────────────────────
|
|
220
|
+
export { sessionMiddleware } from './session/middleware.ts'
|
|
221
|
+
export { MemoryStore as SessionMemoryStore } from './session/store-memory.ts'
|
|
222
|
+
export type {
|
|
223
|
+
Session,
|
|
224
|
+
SessionOptions,
|
|
225
|
+
SessionStore,
|
|
226
|
+
SessionCookieOptions,
|
|
227
|
+
} from './session/types.ts'
|
|
228
|
+
|
|
229
|
+
// ───── WebSocket adapter (optional `ws` peer dep) ──────────────────────────
|
|
230
|
+
export {
|
|
231
|
+
enableWebSockets,
|
|
232
|
+
createWebSocketRegistrar,
|
|
233
|
+
peerHasWs,
|
|
234
|
+
WsNodeAdapter,
|
|
235
|
+
type EnableWebSocketsOptions,
|
|
236
|
+
type WebSocketHandler,
|
|
237
|
+
type WebSocketHandlerOptions,
|
|
238
|
+
type WsIntegrator,
|
|
239
|
+
type WsRegistrar,
|
|
240
|
+
type WebSocket,
|
|
241
|
+
} from './ws/index.ts'
|
|
242
|
+
|
|
243
|
+
// ───── Plugin system ───────────────────────────────────────────────────────
|
|
244
|
+
export type {
|
|
245
|
+
IngeniumPlugin,
|
|
246
|
+
PluginTarget,
|
|
247
|
+
Hooks,
|
|
248
|
+
RegistrationEvent,
|
|
249
|
+
Decorator,
|
|
250
|
+
LazyDecorator,
|
|
251
|
+
EagerDecorator,
|
|
252
|
+
OnRouteHook,
|
|
253
|
+
OnComposeHook,
|
|
254
|
+
OnRequestHook,
|
|
255
|
+
OnResponseHook,
|
|
256
|
+
OnErrorHook,
|
|
257
|
+
} from './plugin/types.ts'
|
|
258
|
+
export { HooksRegistry } from './plugin/hooks.ts'
|
|
259
|
+
export { DecoratorRegistry } from './plugin/decorators.ts'
|
|
260
|
+
export { ScopedApp } from './app/scope.ts'
|
|
261
|
+
|
|
262
|
+
// ───── Default factory + body parsers ──────────────────────────────────────
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Create a new Ingenium application.
|
|
266
|
+
*
|
|
267
|
+
* @example
|
|
268
|
+
* import { ingenium } from 'ingenium'
|
|
269
|
+
*
|
|
270
|
+
* const app = ingenium()
|
|
271
|
+
* app.get('/', (ctx) => ({ hello: 'world' }))
|
|
272
|
+
* await app.listen(3000)
|
|
273
|
+
*/
|
|
274
|
+
const ingeniumCore: IngeniumFactory = makeIngeniumFactory()
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* The `ingenium` export is callable AND has static helpers attached:
|
|
278
|
+
*
|
|
279
|
+
* - `ingenium(opts?)` — create an app
|
|
280
|
+
* - `ingenium.Router()` — create a mountable router
|
|
281
|
+
* - `ingenium.json(opts?)` — Express-compat body-parser shim (no-op; parsing is lazy)
|
|
282
|
+
* - `ingenium.urlencoded(opts?)` — same, for `application/x-www-form-urlencoded`
|
|
283
|
+
* - `ingenium.static(root, opts?)` — serve files from a directory
|
|
284
|
+
* - `ingenium.cors(opts?)` — CORS middleware (simple + preflight)
|
|
285
|
+
*/
|
|
286
|
+
// ───── Sinatra-style top-level ──────────────────────────────────────────────
|
|
287
|
+
//
|
|
288
|
+
// Lets users skip the app object entirely:
|
|
289
|
+
//
|
|
290
|
+
// import { get, listen } from 'ingenium'
|
|
291
|
+
// get('/', () => 'hi')
|
|
292
|
+
// await listen(3000)
|
|
293
|
+
//
|
|
294
|
+
// Every verb routes to a lazy singleton `IngeniumApp` (see `defaultApp()`).
|
|
295
|
+
// `_resetDefaultApp` is test-only and throws under NODE_ENV=production.
|
|
296
|
+
export {
|
|
297
|
+
defaultApp,
|
|
298
|
+
_resetDefaultApp,
|
|
299
|
+
get,
|
|
300
|
+
post,
|
|
301
|
+
put,
|
|
302
|
+
patch,
|
|
303
|
+
del as delete,
|
|
304
|
+
head,
|
|
305
|
+
options,
|
|
306
|
+
use,
|
|
307
|
+
onError,
|
|
308
|
+
listen,
|
|
309
|
+
before,
|
|
310
|
+
after,
|
|
311
|
+
} from './sinatra/top-level.ts'
|
|
312
|
+
|
|
313
|
+
export const ingenium = Object.assign(ingeniumCore, {
|
|
314
|
+
json: jsonMiddleware,
|
|
315
|
+
urlencoded: urlencodedMiddleware,
|
|
316
|
+
static: staticMiddleware,
|
|
317
|
+
cors: corsMiddleware,
|
|
318
|
+
csrf: csrfMiddleware,
|
|
319
|
+
sse,
|
|
320
|
+
rateLimit,
|
|
321
|
+
problemDetails: problemDetailsMiddleware,
|
|
322
|
+
idempotency: idempotencyMiddleware,
|
|
323
|
+
jwt: jwtMiddleware,
|
|
324
|
+
apiKey: apiKeyMiddleware,
|
|
325
|
+
openapiHandler,
|
|
326
|
+
})
|
|
327
|
+
|
|
328
|
+
export default ingenium
|