@nextrush/types 4.0.0-beta.0 → 4.0.0-beta.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/dist/index.d.ts CHANGED
@@ -159,6 +159,32 @@ type ContentTypeValue = (typeof ContentType)[keyof typeof ContentType];
159
159
  * This enables runtime-specific optimizations while maintaining a unified API.
160
160
  */
161
161
  type Runtime = 'node' | 'bun' | 'deno' | 'deno-deploy' | 'cloudflare-workers' | 'vercel-edge' | 'edge' | 'unknown';
162
+ /**
163
+ * Named serverless/edge deployment platform, orthogonal to {@link Runtime}.
164
+ *
165
+ * @remarks
166
+ * `Runtime` answers "which JS engine" (node/bun/deno/edge); `PlatformId`
167
+ * answers "which vendor platform" (Lambda, GCF, Azure, Cloudflare Workers,
168
+ * Vercel Edge, Netlify Edge) — two independent questions that `Runtime`
169
+ * conflating would make into one. Exposed as `ctx.platform` alongside the
170
+ * unchanged `ctx.runtime`.
171
+ *
172
+ * @see RFC-026
173
+ */
174
+ type PlatformId = 'lambda' | 'gcf' | 'azure' | 'cloudflare-workers' | 'vercel-edge' | 'netlify-edge';
175
+ /**
176
+ * Proxy-trust specification for client-IP resolution (RFC-030, SEC-01).
177
+ *
178
+ * @remarks
179
+ * `false` trusts nothing — the direct socket peer is always `ctx.ip`.
180
+ * A `number` trusts exactly that many proxy hops, selecting the
181
+ * corresponding `X-Forwarded-For` entry counting from the right rather than
182
+ * the client-authored leftmost entry. A `string[]` of CIDR ranges/literal
183
+ * IPs trusts only a direct peer (and every hop it names) falling inside the
184
+ * set. `true` and `0` are rejected at boot — see `resolveClientIp` in
185
+ * `@nextrush/runtime`.
186
+ */
187
+ type ProxyTrust = false | number | string[];
162
188
  /**
163
189
  * Runtime feature capabilities
164
190
  *
@@ -181,6 +207,10 @@ interface RuntimeCapabilities {
181
207
  cryptoSubtle: boolean;
182
208
  /** Supports Web Workers / Worker Threads */
183
209
  workers: boolean;
210
+ /** Supports TLS (HTTPS) — the runtime can terminate TLS connections */
211
+ secureServing: boolean;
212
+ /** Supports HTTP/2 negotiation via ALPN (requires secureServing) */
213
+ http2: boolean;
184
214
  }
185
215
  /**
186
216
  * Runtime information object
@@ -466,11 +496,26 @@ interface Context {
466
496
  */
467
497
  readonly url: string;
468
498
  /**
469
- * Request path without query string
499
+ * Request path without query string, canonicalized by the router (case
500
+ * folded per `caseSensitive`, structurally normalized) — the value the
501
+ * router actually matched on, and the one path-based policy middleware
502
+ * should compare against instead of hand-rolling its own normalization
503
+ * (RFC-029). See {@link originalPath} for the untouched raw target.
470
504
  * @example '/users/123'
471
505
  * @readonly
472
506
  */
473
507
  readonly path: string;
508
+ /**
509
+ * The raw request target as received, before router canonicalization —
510
+ * still query-string-free, but not case-folded or structurally normalized.
511
+ * Optional: populated once the router's dispatch middleware runs; absent
512
+ * (or equal to {@link path}) when no router has run yet, or when a caller
513
+ * constructs a `Context` directly (e.g. a test double) without one. Prefer
514
+ * `path` for any security- or routing-relevant comparison (RFC-029).
515
+ * @example '/Users/123' when a request for '/USERS/123' matched '/users/:id'
516
+ * @readonly
517
+ */
518
+ readonly originalPath?: string;
474
519
  /**
475
520
  * Parsed query string parameters
476
521
  * @example { include: 'posts', limit: '10' }
@@ -713,6 +758,25 @@ interface Context {
713
758
  * ```
714
759
  */
715
760
  readonly runtime: Runtime;
761
+ /**
762
+ * Named deployment platform, when known — orthogonal to {@link runtime}.
763
+ *
764
+ * @remarks
765
+ * `undefined` on adapters/runtimes with no named platform to report (e.g.
766
+ * plain Node.js, Bun, Deno). On `@nextrush/adapter-edge` and
767
+ * `@nextrush/adapter-serverless`, set when the platform is detectable
768
+ * (Cloudflare Workers, Vercel Edge, Netlify Edge) or explicitly known by
769
+ * the Tier-1 handler that built this context (AWS Lambda, Google Cloud
770
+ * Functions, Azure Functions).
771
+ *
772
+ * @example
773
+ * ```typescript
774
+ * if (ctx.platform === 'lambda') {
775
+ * // AWS Lambda-specific behavior
776
+ * }
777
+ * ```
778
+ */
779
+ readonly platform: PlatformId | undefined;
716
780
  /**
717
781
  * Body source for cross-runtime body reading
718
782
  *
@@ -1576,4 +1640,61 @@ interface RouteParam {
1576
1640
  pattern?: RegExp;
1577
1641
  }
1578
1642
 
1579
- export { type AdapterContext, type AdapterContextFactory, type BaseStreamWriter, type BodySource, type BodySourceOptions, type ClassProvider, type CommonHttpMethod, type Constructor, type Container, ContentType, type ContentTypeValue, type Context, type ContextOptions, type ContextState, type Extension, type ExtensionContext, type ExtensionHost, type FactoryProvider, type FetchAdapter, type FetchContext, type FetchHandler, type FetchHandlerOptions, HTTP_METHODS, type HandlerOptions, type HttpMethod, HttpStatus, type HttpStatusCode, type IncomingHeaders, type InferOutput, type Logger, type MetadataContribution, type Middleware, type NDJSONStreamWriter, type Next, type NodeStreamLike, type OutgoingHeaders, type ParsedBody, type Provider, type QueryParams, ROUTE_METADATA, type RawHttp, type RegisterOptions, type ResponseBody, type Route, type RouteDefinition, type RouteEntry, type RouteHandler, type RouteMatch, type RouteMetaMarker, type RouteMetadata, type RouteParam, type RouteParams, type RoutePattern, type Router, type RouterOptions, type Runtime, type RuntimeCapabilities, type RuntimeInfo, type SSEEvent, type SSEStreamWriter, type Scope, type ServerAdapter, type ServerAddress, type ServerHandle, type ServiceOptions, type StandardSchemaIssue, type StandardSchemaPathSegment, type StandardSchemaProps, type StandardSchemaResult, type StandardSchemaV1, type StreamRun, type StreamSource, type TextStreamWriter, type Token, type ValueProvider, type WebStreamLike };
1643
+ /**
1644
+ * @nextrush/types - Security Audit Contribution Contract
1645
+ *
1646
+ * `core` cannot import `@nextrush/{cors,static,cookies,errors}` (lower
1647
+ * packages never import from higher ones — `architecture.instructions.md`),
1648
+ * so `Application` cannot inspect a middleware instance's configuration
1649
+ * directly. This contract lets a middleware factory (`cors()`, `serveStatic()`,
1650
+ * `cookies()`, `errorHandler()`, …) optionally attach a boot-time check to the
1651
+ * `Middleware` function it already returns from `app.use()` — the same
1652
+ * "contribute via a well-known symbol, the owner collects it later" shape as
1653
+ * {@link ROUTE_METADATA}, applied to production-safety auditing instead of
1654
+ * route documentation (RFC gates this in `docs/RFC/` under the
1655
+ * `security-boundaries` capability's boot-audit requirement).
1656
+ *
1657
+ * @packageDocumentation
1658
+ */
1659
+
1660
+ /**
1661
+ * Well-known symbol by which a middleware factory contributes a security
1662
+ * audit check to the `Middleware` function it returns. `Application.use()`
1663
+ * reads this symbol off every registered middleware and collects any checks
1664
+ * present; `app.ready()` runs the collected set once, in production only.
1665
+ *
1666
+ * `Symbol.for` (global registry) matches {@link ROUTE_METADATA}'s choice, so
1667
+ * identity holds even across duplicate package instances.
1668
+ */
1669
+ declare const SECURITY_AUDIT: unique symbol;
1670
+ /**
1671
+ * The outcome of one security audit check.
1672
+ *
1673
+ * - `ok` — configuration is safe; nothing is reported.
1674
+ * - `warn` — configuration is unsafe but has a legitimate use; logged once,
1675
+ * never blocks boot.
1676
+ * - `throw` — configuration has no legitimate production use; boot fails.
1677
+ */
1678
+ type SecurityAuditVerdict = {
1679
+ readonly level: 'ok';
1680
+ } | {
1681
+ readonly level: 'warn';
1682
+ readonly message: string;
1683
+ } | {
1684
+ readonly level: 'throw';
1685
+ readonly message: string;
1686
+ };
1687
+ /**
1688
+ * A middleware's self-reported boot-time safety check, invoked only when the
1689
+ * application is booting in production. Pure and synchronous — a check
1690
+ * inspects configuration already closed over at construction time, never I/O.
1691
+ */
1692
+ type SecurityAuditCheck = () => SecurityAuditVerdict;
1693
+ /** A middleware function carrying a {@link SecurityAuditCheck} contribution. */
1694
+ interface SecurityAudited {
1695
+ readonly [SECURITY_AUDIT]: SecurityAuditCheck;
1696
+ }
1697
+ /** A registered middleware, optionally carrying a security audit contribution. */
1698
+ type AuditableMiddleware = Middleware & Partial<SecurityAudited>;
1699
+
1700
+ export { type AdapterContext, type AdapterContextFactory, type AuditableMiddleware, type BaseStreamWriter, type BodySource, type BodySourceOptions, type ClassProvider, type CommonHttpMethod, type Constructor, type Container, ContentType, type ContentTypeValue, type Context, type ContextOptions, type ContextState, type Extension, type ExtensionContext, type ExtensionHost, type FactoryProvider, type FetchAdapter, type FetchContext, type FetchHandler, type FetchHandlerOptions, HTTP_METHODS, type HandlerOptions, type HttpMethod, HttpStatus, type HttpStatusCode, type IncomingHeaders, type InferOutput, type Logger, type MetadataContribution, type Middleware, type NDJSONStreamWriter, type Next, type NodeStreamLike, type OutgoingHeaders, type ParsedBody, type PlatformId, type Provider, type ProxyTrust, type QueryParams, ROUTE_METADATA, type RawHttp, type RegisterOptions, type ResponseBody, type Route, type RouteDefinition, type RouteEntry, type RouteHandler, type RouteMatch, type RouteMetaMarker, type RouteMetadata, type RouteParam, type RouteParams, type RoutePattern, type Router, type RouterOptions, type Runtime, type RuntimeCapabilities, type RuntimeInfo, SECURITY_AUDIT, type SSEEvent, type SSEStreamWriter, type Scope, type SecurityAuditCheck, type SecurityAuditVerdict, type SecurityAudited, type ServerAdapter, type ServerAddress, type ServerHandle, type ServiceOptions, type StandardSchemaIssue, type StandardSchemaPathSegment, type StandardSchemaProps, type StandardSchemaResult, type StandardSchemaV1, type StreamRun, type StreamSource, type TextStreamWriter, type Token, type ValueProvider, type WebStreamLike };
package/dist/index.js CHANGED
@@ -76,6 +76,9 @@ var ContentType = {
76
76
  // src/route-metadata.ts
77
77
  var ROUTE_METADATA = /* @__PURE__ */ Symbol.for("nextrush.route.metadata");
78
78
 
79
- export { ContentType, HTTP_METHODS, HttpStatus, ROUTE_METADATA };
79
+ // src/security-audit.ts
80
+ var SECURITY_AUDIT = /* @__PURE__ */ Symbol.for("nextrush.security.audit");
81
+
82
+ export { ContentType, HTTP_METHODS, HttpStatus, ROUTE_METADATA, SECURITY_AUDIT };
80
83
  //# sourceMappingURL=index.js.map
81
84
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/http.ts","../src/route-metadata.ts"],"names":[],"mappings":";AAyCO,IAAM,YAAA,GAAe;AAAA,EAC1B,KAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF;AAuBO,IAAM,UAAA,GAAa;AAAA;AAAA,EAExB,EAAA,EAAI,GAAA;AAAA,EACJ,OAAA,EAAS,GAAA;AAAA,EACT,QAAA,EAAU,GAAA;AAAA,EACV,UAAA,EAAY,GAAA;AAAA;AAAA,EAGZ,iBAAA,EAAmB,GAAA;AAAA,EACnB,KAAA,EAAO,GAAA;AAAA,EACP,SAAA,EAAW,GAAA;AAAA,EACX,YAAA,EAAc,GAAA;AAAA,EACd,kBAAA,EAAoB,GAAA;AAAA,EACpB,kBAAA,EAAoB,GAAA;AAAA;AAAA,EAGpB,WAAA,EAAa,GAAA;AAAA,EACb,YAAA,EAAc,GAAA;AAAA,EACd,gBAAA,EAAkB,GAAA;AAAA,EAClB,SAAA,EAAW,GAAA;AAAA,EACX,SAAA,EAAW,GAAA;AAAA,EACX,kBAAA,EAAoB,GAAA;AAAA,EACpB,cAAA,EAAgB,GAAA;AAAA,EAChB,mBAAA,EAAqB,GAAA;AAAA,EACrB,eAAA,EAAiB,GAAA;AAAA,EACjB,QAAA,EAAU,GAAA;AAAA,EACV,IAAA,EAAM,GAAA;AAAA,EACN,eAAA,EAAiB,GAAA;AAAA,EACjB,mBAAA,EAAqB,GAAA;AAAA,EACrB,iBAAA,EAAmB,GAAA;AAAA,EACnB,YAAA,EAAc,GAAA;AAAA,EACd,sBAAA,EAAwB,GAAA;AAAA,EACxB,qBAAA,EAAuB,GAAA;AAAA,EACvB,kBAAA,EAAoB,GAAA;AAAA,EACpB,WAAA,EAAa,GAAA;AAAA,EACb,oBAAA,EAAsB,GAAA;AAAA,EACtB,MAAA,EAAQ,GAAA;AAAA,EACR,iBAAA,EAAmB,GAAA;AAAA,EACnB,SAAA,EAAW,GAAA;AAAA,EACX,gBAAA,EAAkB,GAAA;AAAA,EAClB,qBAAA,EAAuB,GAAA;AAAA,EACvB,iBAAA,EAAmB,GAAA;AAAA,EACnB,+BAAA,EAAiC,GAAA;AAAA,EACjC,6BAAA,EAA+B,GAAA;AAAA;AAAA,EAG/B,qBAAA,EAAuB,GAAA;AAAA,EACvB,eAAA,EAAiB,GAAA;AAAA,EACjB,WAAA,EAAa,GAAA;AAAA,EACb,mBAAA,EAAqB,GAAA;AAAA,EACrB,eAAA,EAAiB,GAAA;AAAA,EACjB,0BAAA,EAA4B,GAAA;AAAA,EAC5B,uBAAA,EAAyB,GAAA;AAAA,EACzB,oBAAA,EAAsB,GAAA;AAAA,EACtB,aAAA,EAAe,GAAA;AAAA,EACf,YAAA,EAAc,GAAA;AAAA,EACd,qBAAA,EAAuB;AACzB;AAqFO,IAAM,WAAA,GAAc;AAAA,EACzB,IAAA,EAAM,kBAAA;AAAA,EACN,IAAA,EAAM,WAAA;AAAA,EACN,IAAA,EAAM,YAAA;AAAA,EACN,GAAA,EAAK,iBAAA;AAAA,EACL,IAAA,EAAM,mCAAA;AAAA,EACN,SAAA,EAAW,qBAAA;AAAA,EACX,YAAA,EAAc;AAChB;;;ACnMO,IAAM,cAAA,mBAAgC,MAAA,CAAO,GAAA,CAAI,yBAAyB","file":"index.js","sourcesContent":["/**\n * @nextrush/types - HTTP Type Definitions\n *\n * Core HTTP types used across the NextRush framework.\n * These types provide a clean abstraction over HTTP primitives,\n * designed to work across multiple runtimes (Node.js, Bun, Deno, Edge).\n *\n * @packageDocumentation\n */\n\n// ============================================================================\n// HTTP Method Types\n// ============================================================================\n\n/**\n * Standard HTTP methods supported by NextRush\n */\nexport type HttpMethod =\n | 'GET'\n | 'POST'\n | 'PUT'\n | 'DELETE'\n | 'PATCH'\n | 'HEAD'\n | 'OPTIONS'\n | 'TRACE'\n | 'CONNECT';\n\n/**\n * Common HTTP methods for convenience\n */\nexport type CommonHttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';\n\n/**\n * HTTP methods as readonly tuple for iteration.\n *\n * Note: TRACE and CONNECT are intentionally excluded from this constant.\n * - TRACE enables Cross-Site Tracing (XST) attacks and is disabled by most servers.\n * - CONNECT is used for HTTP tunneling (proxies) and is not relevant to application routing.\n * Both remain in the `HttpMethod` type for completeness (e.g., custom proxy adapters).\n */\nexport const HTTP_METHODS = [\n 'GET',\n 'POST',\n 'PUT',\n 'DELETE',\n 'PATCH',\n 'HEAD',\n 'OPTIONS',\n] as const satisfies readonly HttpMethod[];\n\n// ============================================================================\n// HTTP Headers Types\n// ============================================================================\n\n/**\n * Incoming request headers (read-only)\n */\nexport type IncomingHeaders = Readonly<Record<string, string | string[] | undefined>>;\n\n/**\n * Outgoing response headers (writable)\n */\nexport type OutgoingHeaders = Record<string, string | number | string[]>;\n\n// ============================================================================\n// HTTP Status Codes\n// ============================================================================\n\n/**\n * HTTP status codes\n */\nexport const HttpStatus = {\n // 2xx Success\n OK: 200,\n CREATED: 201,\n ACCEPTED: 202,\n NO_CONTENT: 204,\n\n // 3xx Redirection\n MOVED_PERMANENTLY: 301,\n FOUND: 302,\n SEE_OTHER: 303,\n NOT_MODIFIED: 304,\n TEMPORARY_REDIRECT: 307,\n PERMANENT_REDIRECT: 308,\n\n // 4xx Client Errors\n BAD_REQUEST: 400,\n UNAUTHORIZED: 401,\n PAYMENT_REQUIRED: 402,\n FORBIDDEN: 403,\n NOT_FOUND: 404,\n METHOD_NOT_ALLOWED: 405,\n NOT_ACCEPTABLE: 406,\n PROXY_AUTH_REQUIRED: 407,\n REQUEST_TIMEOUT: 408,\n CONFLICT: 409,\n GONE: 410,\n LENGTH_REQUIRED: 411,\n PRECONDITION_FAILED: 412,\n PAYLOAD_TOO_LARGE: 413,\n URI_TOO_LONG: 414,\n UNSUPPORTED_MEDIA_TYPE: 415,\n RANGE_NOT_SATISFIABLE: 416,\n EXPECTATION_FAILED: 417,\n IM_A_TEAPOT: 418,\n UNPROCESSABLE_ENTITY: 422,\n LOCKED: 423,\n FAILED_DEPENDENCY: 424,\n TOO_EARLY: 425,\n UPGRADE_REQUIRED: 426,\n PRECONDITION_REQUIRED: 428,\n TOO_MANY_REQUESTS: 429,\n REQUEST_HEADER_FIELDS_TOO_LARGE: 431,\n UNAVAILABLE_FOR_LEGAL_REASONS: 451,\n\n // 5xx Server Errors\n INTERNAL_SERVER_ERROR: 500,\n NOT_IMPLEMENTED: 501,\n BAD_GATEWAY: 502,\n SERVICE_UNAVAILABLE: 503,\n GATEWAY_TIMEOUT: 504,\n HTTP_VERSION_NOT_SUPPORTED: 505,\n VARIANT_ALSO_NEGOTIATES: 506,\n INSUFFICIENT_STORAGE: 507,\n LOOP_DETECTED: 508,\n NOT_EXTENDED: 510,\n NETWORK_AUTH_REQUIRED: 511,\n} as const;\n\nexport type HttpStatusCode = (typeof HttpStatus)[keyof typeof HttpStatus];\n\n// ============================================================================\n// Request/Response Body Types\n// ============================================================================\n\n/**\n * Supported request body types after parsing\n */\nexport type ParsedBody =\n | string\n | Uint8Array\n | Record<string, unknown>\n | unknown[]\n | null\n | undefined;\n\n/**\n * Supported response body types\n *\n * @remarks\n * Uses structural stream interfaces to avoid coupling to any\n * specific runtime (Node.js, Bun, Deno, Edge).\n * Uint8Array and ArrayBuffer provide Web API compatibility.\n */\nexport type ResponseBody =\n | string\n | Uint8Array\n | ArrayBuffer\n | NodeStreamLike\n | WebStreamLike\n | Record<string, unknown>\n | unknown[]\n | null\n | undefined;\n\n// ============================================================================\n// Cross-Runtime Stream Types\n// ============================================================================\n\n/**\n * Structural interface for Node.js-compatible readable streams.\n * Matches Node.js `Readable` and `IncomingMessage` without importing `@types/node`.\n */\nexport interface NodeStreamLike {\n pipe(destination: unknown): unknown;\n}\n\n/**\n * Structural interface for Web API ReadableStreams.\n * Matches the global `ReadableStream<Uint8Array>` without requiring DOM lib types.\n */\nexport interface WebStreamLike {\n getReader(): unknown;\n readonly locked: boolean;\n}\n\n// ============================================================================\n// Raw HTTP Access Types\n// ============================================================================\n\n/**\n * Raw HTTP objects - generic to support multiple runtimes\n *\n * For Node.js: RawHttp<IncomingMessage, ServerResponse>\n * For Bun: RawHttp<Request, Response>\n * For Edge: RawHttp<Request, ResponseInit>\n *\n * @typeParam TReq - Raw request type for the runtime\n * @typeParam TRes - Raw response type for the runtime\n */\nexport interface RawHttp<TReq = unknown, TRes = unknown> {\n readonly req: TReq;\n readonly res: TRes;\n}\n\n// ============================================================================\n// Content Type Helpers\n// ============================================================================\n\n/**\n * Common content types\n */\nexport const ContentType = {\n JSON: 'application/json',\n HTML: 'text/html',\n TEXT: 'text/plain',\n XML: 'application/xml',\n FORM: 'application/x-www-form-urlencoded',\n MULTIPART: 'multipart/form-data',\n OCTET_STREAM: 'application/octet-stream',\n} as const;\n\nexport type ContentTypeValue = (typeof ContentType)[keyof typeof ContentType];\n","/**\n * @nextrush/types - Route Metadata Contracts\n *\n * `RouteDefinition` is the single source of truth for what a route *is and\n * means*. The router collects it once at registration; renderers\n * (`@nextrush/openapi`, and later SDK/Postman/RPC generators) read it. The\n * router itself is renderer-agnostic — it stores raw schemas and generic\n * metadata, never OpenAPI shapes.\n *\n * See docs/RFC/request-data/002-route-metadata.md.\n *\n * @packageDocumentation\n */\n\nimport type { Middleware } from './context';\nimport type { HttpMethod } from './http';\nimport type { StandardSchemaV1 } from './standard-schema';\n\n/**\n * Well-known symbol by which anything — a middleware function (e.g. `validate()`)\n * or a pure marker (e.g. `endpoint()`) — contributes metadata to the route it is\n * registered on. The router reads this symbol off every route entry at\n * registration and merges the contributions.\n *\n * `Symbol.for` (global registry) is used so the identity holds even across\n * duplicate package instances.\n */\nexport const ROUTE_METADATA: unique symbol = Symbol.for('nextrush.route.metadata');\n\n/** A partial metadata contribution; contributions merge in registration order. */\nexport type MetadataContribution = Partial<RouteMetadata>;\n\n/**\n * A pure-metadata marker carried in a route's argument list. Not a middleware —\n * it has no runtime behavior and never enters the executed chain.\n */\nexport interface RouteMetaMarker {\n readonly [ROUTE_METADATA]: MetadataContribution;\n}\n\n/** An entry in a route's argument list: behavior (`Middleware`) or pure metadata (a marker). */\nexport type RouteEntry = Middleware | RouteMetaMarker;\n\n/**\n * Generic, renderer-agnostic description of a route's request/response shapes\n * and documentation facts. Every field is a fact any renderer needs; no\n * renderer-specific artifacts (e.g. OpenAPI `operationId`) live here.\n */\nexport interface RouteMetadata {\n /** Request shapes — contributed by `validate()`; never hand-written on the golden path. */\n readonly request?: {\n readonly body?: StandardSchemaV1;\n readonly query?: StandardSchemaV1;\n readonly params?: StandardSchemaV1;\n };\n /** Response shapes by numeric status — contributed by `endpoint()`. */\n readonly responses?: Readonly<Record<number, StandardSchemaV1>>;\n readonly summary?: string;\n readonly description?: string;\n readonly tags?: readonly string[];\n readonly deprecated?: boolean;\n /** Cross-renderer intent — an `'internal'` route is excluded from public specs/SDKs. */\n readonly visibility?: 'public' | 'internal';\n}\n\n/**\n * The canonical description of a registered endpoint, produced by the router\n * and consumed by renderers.\n */\nexport interface RouteDefinition {\n /**\n * Canonical route key — `${METHOD} ${pathPattern}` (e.g. `\"GET /users/:id\"`),\n * the key the router uses internally. Deterministic and stable across\n * restarts, but it encodes the path, so it changes if the path or a param\n * name changes — a key, not a rename-stable opaque id.\n */\n readonly key: string;\n readonly method: HttpMethod;\n /** Full, mount/prefix-resolved path pattern. */\n readonly path: string;\n readonly metadata?: RouteMetadata;\n /**\n * `true` when this entry represents an any-method route (registered via\n * `router.all()` / `@All()`), matching every standard HTTP method under a\n * single introspection row rather than one row per method (T016). `method`\n * is still a real `HttpMethod` value for structural compatibility with\n * existing consumers that read `.method` unconditionally — check this flag\n * first when the distinction matters (e.g. an OpenAPI renderer expanding\n * one row into per-verb operations). Absent (`undefined`) for every\n * ordinary single-method route.\n */\n readonly isAnyMethod?: boolean;\n}\n"]}
1
+ {"version":3,"sources":["../src/http.ts","../src/route-metadata.ts","../src/security-audit.ts"],"names":[],"mappings":";AAyCO,IAAM,YAAA,GAAe;AAAA,EAC1B,KAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF;AAuBO,IAAM,UAAA,GAAa;AAAA;AAAA,EAExB,EAAA,EAAI,GAAA;AAAA,EACJ,OAAA,EAAS,GAAA;AAAA,EACT,QAAA,EAAU,GAAA;AAAA,EACV,UAAA,EAAY,GAAA;AAAA;AAAA,EAGZ,iBAAA,EAAmB,GAAA;AAAA,EACnB,KAAA,EAAO,GAAA;AAAA,EACP,SAAA,EAAW,GAAA;AAAA,EACX,YAAA,EAAc,GAAA;AAAA,EACd,kBAAA,EAAoB,GAAA;AAAA,EACpB,kBAAA,EAAoB,GAAA;AAAA;AAAA,EAGpB,WAAA,EAAa,GAAA;AAAA,EACb,YAAA,EAAc,GAAA;AAAA,EACd,gBAAA,EAAkB,GAAA;AAAA,EAClB,SAAA,EAAW,GAAA;AAAA,EACX,SAAA,EAAW,GAAA;AAAA,EACX,kBAAA,EAAoB,GAAA;AAAA,EACpB,cAAA,EAAgB,GAAA;AAAA,EAChB,mBAAA,EAAqB,GAAA;AAAA,EACrB,eAAA,EAAiB,GAAA;AAAA,EACjB,QAAA,EAAU,GAAA;AAAA,EACV,IAAA,EAAM,GAAA;AAAA,EACN,eAAA,EAAiB,GAAA;AAAA,EACjB,mBAAA,EAAqB,GAAA;AAAA,EACrB,iBAAA,EAAmB,GAAA;AAAA,EACnB,YAAA,EAAc,GAAA;AAAA,EACd,sBAAA,EAAwB,GAAA;AAAA,EACxB,qBAAA,EAAuB,GAAA;AAAA,EACvB,kBAAA,EAAoB,GAAA;AAAA,EACpB,WAAA,EAAa,GAAA;AAAA,EACb,oBAAA,EAAsB,GAAA;AAAA,EACtB,MAAA,EAAQ,GAAA;AAAA,EACR,iBAAA,EAAmB,GAAA;AAAA,EACnB,SAAA,EAAW,GAAA;AAAA,EACX,gBAAA,EAAkB,GAAA;AAAA,EAClB,qBAAA,EAAuB,GAAA;AAAA,EACvB,iBAAA,EAAmB,GAAA;AAAA,EACnB,+BAAA,EAAiC,GAAA;AAAA,EACjC,6BAAA,EAA+B,GAAA;AAAA;AAAA,EAG/B,qBAAA,EAAuB,GAAA;AAAA,EACvB,eAAA,EAAiB,GAAA;AAAA,EACjB,WAAA,EAAa,GAAA;AAAA,EACb,mBAAA,EAAqB,GAAA;AAAA,EACrB,eAAA,EAAiB,GAAA;AAAA,EACjB,0BAAA,EAA4B,GAAA;AAAA,EAC5B,uBAAA,EAAyB,GAAA;AAAA,EACzB,oBAAA,EAAsB,GAAA;AAAA,EACtB,aAAA,EAAe,GAAA;AAAA,EACf,YAAA,EAAc,GAAA;AAAA,EACd,qBAAA,EAAuB;AACzB;AAqFO,IAAM,WAAA,GAAc;AAAA,EACzB,IAAA,EAAM,kBAAA;AAAA,EACN,IAAA,EAAM,WAAA;AAAA,EACN,IAAA,EAAM,YAAA;AAAA,EACN,GAAA,EAAK,iBAAA;AAAA,EACL,IAAA,EAAM,mCAAA;AAAA,EACN,SAAA,EAAW,qBAAA;AAAA,EACX,YAAA,EAAc;AAChB;;;ACnMO,IAAM,cAAA,mBAAgC,MAAA,CAAO,GAAA,CAAI,yBAAyB;;;ACC1E,IAAM,cAAA,mBAAgC,MAAA,CAAO,GAAA,CAAI,yBAAyB","file":"index.js","sourcesContent":["/**\n * @nextrush/types - HTTP Type Definitions\n *\n * Core HTTP types used across the NextRush framework.\n * These types provide a clean abstraction over HTTP primitives,\n * designed to work across multiple runtimes (Node.js, Bun, Deno, Edge).\n *\n * @packageDocumentation\n */\n\n// ============================================================================\n// HTTP Method Types\n// ============================================================================\n\n/**\n * Standard HTTP methods supported by NextRush\n */\nexport type HttpMethod =\n | 'GET'\n | 'POST'\n | 'PUT'\n | 'DELETE'\n | 'PATCH'\n | 'HEAD'\n | 'OPTIONS'\n | 'TRACE'\n | 'CONNECT';\n\n/**\n * Common HTTP methods for convenience\n */\nexport type CommonHttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';\n\n/**\n * HTTP methods as readonly tuple for iteration.\n *\n * Note: TRACE and CONNECT are intentionally excluded from this constant.\n * - TRACE enables Cross-Site Tracing (XST) attacks and is disabled by most servers.\n * - CONNECT is used for HTTP tunneling (proxies) and is not relevant to application routing.\n * Both remain in the `HttpMethod` type for completeness (e.g., custom proxy adapters).\n */\nexport const HTTP_METHODS = [\n 'GET',\n 'POST',\n 'PUT',\n 'DELETE',\n 'PATCH',\n 'HEAD',\n 'OPTIONS',\n] as const satisfies readonly HttpMethod[];\n\n// ============================================================================\n// HTTP Headers Types\n// ============================================================================\n\n/**\n * Incoming request headers (read-only)\n */\nexport type IncomingHeaders = Readonly<Record<string, string | string[] | undefined>>;\n\n/**\n * Outgoing response headers (writable)\n */\nexport type OutgoingHeaders = Record<string, string | number | string[]>;\n\n// ============================================================================\n// HTTP Status Codes\n// ============================================================================\n\n/**\n * HTTP status codes\n */\nexport const HttpStatus = {\n // 2xx Success\n OK: 200,\n CREATED: 201,\n ACCEPTED: 202,\n NO_CONTENT: 204,\n\n // 3xx Redirection\n MOVED_PERMANENTLY: 301,\n FOUND: 302,\n SEE_OTHER: 303,\n NOT_MODIFIED: 304,\n TEMPORARY_REDIRECT: 307,\n PERMANENT_REDIRECT: 308,\n\n // 4xx Client Errors\n BAD_REQUEST: 400,\n UNAUTHORIZED: 401,\n PAYMENT_REQUIRED: 402,\n FORBIDDEN: 403,\n NOT_FOUND: 404,\n METHOD_NOT_ALLOWED: 405,\n NOT_ACCEPTABLE: 406,\n PROXY_AUTH_REQUIRED: 407,\n REQUEST_TIMEOUT: 408,\n CONFLICT: 409,\n GONE: 410,\n LENGTH_REQUIRED: 411,\n PRECONDITION_FAILED: 412,\n PAYLOAD_TOO_LARGE: 413,\n URI_TOO_LONG: 414,\n UNSUPPORTED_MEDIA_TYPE: 415,\n RANGE_NOT_SATISFIABLE: 416,\n EXPECTATION_FAILED: 417,\n IM_A_TEAPOT: 418,\n UNPROCESSABLE_ENTITY: 422,\n LOCKED: 423,\n FAILED_DEPENDENCY: 424,\n TOO_EARLY: 425,\n UPGRADE_REQUIRED: 426,\n PRECONDITION_REQUIRED: 428,\n TOO_MANY_REQUESTS: 429,\n REQUEST_HEADER_FIELDS_TOO_LARGE: 431,\n UNAVAILABLE_FOR_LEGAL_REASONS: 451,\n\n // 5xx Server Errors\n INTERNAL_SERVER_ERROR: 500,\n NOT_IMPLEMENTED: 501,\n BAD_GATEWAY: 502,\n SERVICE_UNAVAILABLE: 503,\n GATEWAY_TIMEOUT: 504,\n HTTP_VERSION_NOT_SUPPORTED: 505,\n VARIANT_ALSO_NEGOTIATES: 506,\n INSUFFICIENT_STORAGE: 507,\n LOOP_DETECTED: 508,\n NOT_EXTENDED: 510,\n NETWORK_AUTH_REQUIRED: 511,\n} as const;\n\nexport type HttpStatusCode = (typeof HttpStatus)[keyof typeof HttpStatus];\n\n// ============================================================================\n// Request/Response Body Types\n// ============================================================================\n\n/**\n * Supported request body types after parsing\n */\nexport type ParsedBody =\n | string\n | Uint8Array\n | Record<string, unknown>\n | unknown[]\n | null\n | undefined;\n\n/**\n * Supported response body types\n *\n * @remarks\n * Uses structural stream interfaces to avoid coupling to any\n * specific runtime (Node.js, Bun, Deno, Edge).\n * Uint8Array and ArrayBuffer provide Web API compatibility.\n */\nexport type ResponseBody =\n | string\n | Uint8Array\n | ArrayBuffer\n | NodeStreamLike\n | WebStreamLike\n | Record<string, unknown>\n | unknown[]\n | null\n | undefined;\n\n// ============================================================================\n// Cross-Runtime Stream Types\n// ============================================================================\n\n/**\n * Structural interface for Node.js-compatible readable streams.\n * Matches Node.js `Readable` and `IncomingMessage` without importing `@types/node`.\n */\nexport interface NodeStreamLike {\n pipe(destination: unknown): unknown;\n}\n\n/**\n * Structural interface for Web API ReadableStreams.\n * Matches the global `ReadableStream<Uint8Array>` without requiring DOM lib types.\n */\nexport interface WebStreamLike {\n getReader(): unknown;\n readonly locked: boolean;\n}\n\n// ============================================================================\n// Raw HTTP Access Types\n// ============================================================================\n\n/**\n * Raw HTTP objects - generic to support multiple runtimes\n *\n * For Node.js: RawHttp<IncomingMessage, ServerResponse>\n * For Bun: RawHttp<Request, Response>\n * For Edge: RawHttp<Request, ResponseInit>\n *\n * @typeParam TReq - Raw request type for the runtime\n * @typeParam TRes - Raw response type for the runtime\n */\nexport interface RawHttp<TReq = unknown, TRes = unknown> {\n readonly req: TReq;\n readonly res: TRes;\n}\n\n// ============================================================================\n// Content Type Helpers\n// ============================================================================\n\n/**\n * Common content types\n */\nexport const ContentType = {\n JSON: 'application/json',\n HTML: 'text/html',\n TEXT: 'text/plain',\n XML: 'application/xml',\n FORM: 'application/x-www-form-urlencoded',\n MULTIPART: 'multipart/form-data',\n OCTET_STREAM: 'application/octet-stream',\n} as const;\n\nexport type ContentTypeValue = (typeof ContentType)[keyof typeof ContentType];\n","/**\n * @nextrush/types - Route Metadata Contracts\n *\n * `RouteDefinition` is the single source of truth for what a route *is and\n * means*. The router collects it once at registration; renderers\n * (`@nextrush/openapi`, and later SDK/Postman/RPC generators) read it. The\n * router itself is renderer-agnostic — it stores raw schemas and generic\n * metadata, never OpenAPI shapes.\n *\n * See docs/RFC/request-data/002-route-metadata.md.\n *\n * @packageDocumentation\n */\n\nimport type { Middleware } from './context';\nimport type { HttpMethod } from './http';\nimport type { StandardSchemaV1 } from './standard-schema';\n\n/**\n * Well-known symbol by which anything — a middleware function (e.g. `validate()`)\n * or a pure marker (e.g. `endpoint()`) — contributes metadata to the route it is\n * registered on. The router reads this symbol off every route entry at\n * registration and merges the contributions.\n *\n * `Symbol.for` (global registry) is used so the identity holds even across\n * duplicate package instances.\n */\nexport const ROUTE_METADATA: unique symbol = Symbol.for('nextrush.route.metadata');\n\n/** A partial metadata contribution; contributions merge in registration order. */\nexport type MetadataContribution = Partial<RouteMetadata>;\n\n/**\n * A pure-metadata marker carried in a route's argument list. Not a middleware —\n * it has no runtime behavior and never enters the executed chain.\n */\nexport interface RouteMetaMarker {\n readonly [ROUTE_METADATA]: MetadataContribution;\n}\n\n/** An entry in a route's argument list: behavior (`Middleware`) or pure metadata (a marker). */\nexport type RouteEntry = Middleware | RouteMetaMarker;\n\n/**\n * Generic, renderer-agnostic description of a route's request/response shapes\n * and documentation facts. Every field is a fact any renderer needs; no\n * renderer-specific artifacts (e.g. OpenAPI `operationId`) live here.\n */\nexport interface RouteMetadata {\n /** Request shapes — contributed by `validate()`; never hand-written on the golden path. */\n readonly request?: {\n readonly body?: StandardSchemaV1;\n readonly query?: StandardSchemaV1;\n readonly params?: StandardSchemaV1;\n };\n /** Response shapes by numeric status — contributed by `endpoint()`. */\n readonly responses?: Readonly<Record<number, StandardSchemaV1>>;\n readonly summary?: string;\n readonly description?: string;\n readonly tags?: readonly string[];\n readonly deprecated?: boolean;\n /** Cross-renderer intent — an `'internal'` route is excluded from public specs/SDKs. */\n readonly visibility?: 'public' | 'internal';\n}\n\n/**\n * The canonical description of a registered endpoint, produced by the router\n * and consumed by renderers.\n */\nexport interface RouteDefinition {\n /**\n * Canonical route key — `${METHOD} ${pathPattern}` (e.g. `\"GET /users/:id\"`),\n * the key the router uses internally. Deterministic and stable across\n * restarts, but it encodes the path, so it changes if the path or a param\n * name changes — a key, not a rename-stable opaque id.\n */\n readonly key: string;\n readonly method: HttpMethod;\n /** Full, mount/prefix-resolved path pattern. */\n readonly path: string;\n readonly metadata?: RouteMetadata;\n /**\n * `true` when this entry represents an any-method route (registered via\n * `router.all()` / `@All()`), matching every standard HTTP method under a\n * single introspection row rather than one row per method (T016). `method`\n * is still a real `HttpMethod` value for structural compatibility with\n * existing consumers that read `.method` unconditionally — check this flag\n * first when the distinction matters (e.g. an OpenAPI renderer expanding\n * one row into per-verb operations). Absent (`undefined`) for every\n * ordinary single-method route.\n */\n readonly isAnyMethod?: boolean;\n}\n","/**\n * @nextrush/types - Security Audit Contribution Contract\n *\n * `core` cannot import `@nextrush/{cors,static,cookies,errors}` (lower\n * packages never import from higher ones — `architecture.instructions.md`),\n * so `Application` cannot inspect a middleware instance's configuration\n * directly. This contract lets a middleware factory (`cors()`, `serveStatic()`,\n * `cookies()`, `errorHandler()`, …) optionally attach a boot-time check to the\n * `Middleware` function it already returns from `app.use()` — the same\n * \"contribute via a well-known symbol, the owner collects it later\" shape as\n * {@link ROUTE_METADATA}, applied to production-safety auditing instead of\n * route documentation (RFC gates this in `docs/RFC/` under the\n * `security-boundaries` capability's boot-audit requirement).\n *\n * @packageDocumentation\n */\n\nimport type { Middleware } from './context';\n\n/**\n * Well-known symbol by which a middleware factory contributes a security\n * audit check to the `Middleware` function it returns. `Application.use()`\n * reads this symbol off every registered middleware and collects any checks\n * present; `app.ready()` runs the collected set once, in production only.\n *\n * `Symbol.for` (global registry) matches {@link ROUTE_METADATA}'s choice, so\n * identity holds even across duplicate package instances.\n */\nexport const SECURITY_AUDIT: unique symbol = Symbol.for('nextrush.security.audit');\n\n/**\n * The outcome of one security audit check.\n *\n * - `ok` — configuration is safe; nothing is reported.\n * - `warn` — configuration is unsafe but has a legitimate use; logged once,\n * never blocks boot.\n * - `throw` — configuration has no legitimate production use; boot fails.\n */\nexport type SecurityAuditVerdict =\n | { readonly level: 'ok' }\n | { readonly level: 'warn'; readonly message: string }\n | { readonly level: 'throw'; readonly message: string };\n\n/**\n * A middleware's self-reported boot-time safety check, invoked only when the\n * application is booting in production. Pure and synchronous — a check\n * inspects configuration already closed over at construction time, never I/O.\n */\nexport type SecurityAuditCheck = () => SecurityAuditVerdict;\n\n/** A middleware function carrying a {@link SecurityAuditCheck} contribution. */\nexport interface SecurityAudited {\n readonly [SECURITY_AUDIT]: SecurityAuditCheck;\n}\n\n/** A registered middleware, optionally carrying a security audit contribution. */\nexport type AuditableMiddleware = Middleware & Partial<SecurityAudited>;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextrush/types",
3
- "version": "4.0.0-beta.0",
3
+ "version": "4.0.0-beta.1",
4
4
  "description": "Shared TypeScript types for NextRush framework",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",