@daloyjs/core 1.0.0-beta.4 → 1.0.0-beta.5
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 +49 -46
- package/dist/app.d.ts +42 -21
- package/dist/app.js +100 -116
- package/dist/docs.d.ts +44 -0
- package/dist/docs.js +47 -8
- package/dist/index.d.ts +17 -17
- package/dist/index.js +5 -5
- package/dist/sbom.cdx.json +9 -9
- package/dist/sbom.spdx.json +5 -5
- package/dist/tenancy.d.ts +16 -7
- package/dist/tenancy.js +16 -7
- package/package.json +6 -5
package/dist/docs.js
CHANGED
|
@@ -49,8 +49,7 @@ function integrityAttr(integrity, crossOrigin) {
|
|
|
49
49
|
export function scalarHtml(opts) {
|
|
50
50
|
const title = escapeHtml(opts.title ?? "API Reference");
|
|
51
51
|
const url = escapeHtml(opts.specUrl);
|
|
52
|
-
const scriptUrl = escapeHtml(opts.assets?.scalarScriptUrl ??
|
|
53
|
-
`${JSDELIVR_ORIGIN}/npm/@scalar/api-reference`);
|
|
52
|
+
const scriptUrl = escapeHtml(opts.assets?.scalarScriptUrl ?? `${JSDELIVR_ORIGIN}/npm/@scalar/api-reference`);
|
|
54
53
|
const scriptSri = integrityAttr(opts.assets?.scalarScriptIntegrity, opts.assets?.crossOrigin);
|
|
55
54
|
const nonce = nonceAttr(opts.scriptNonce);
|
|
56
55
|
const configuration = scalarConfigurationAttr(opts.specUrl, opts.configuration);
|
|
@@ -62,6 +61,7 @@ export function scalarHtml(opts) {
|
|
|
62
61
|
</head><body>
|
|
63
62
|
<script id="api-reference" data-url="${url}"${configuration}${nonce}></script>
|
|
64
63
|
<script src="${scriptUrl}"${scriptSri}${nonce}></script>
|
|
64
|
+
${docsAuthLauncherHtml(opts.auth, opts.scriptNonce)}
|
|
65
65
|
</body></html>`;
|
|
66
66
|
}
|
|
67
67
|
/**
|
|
@@ -74,10 +74,8 @@ export function scalarHtml(opts) {
|
|
|
74
74
|
*/
|
|
75
75
|
export function swaggerUiHtml(opts) {
|
|
76
76
|
const title = escapeHtml(opts.title ?? "API Docs");
|
|
77
|
-
const cssUrl = escapeHtml(opts.assets?.swaggerUiCssUrl ??
|
|
78
|
-
|
|
79
|
-
const bundleUrl = escapeHtml(opts.assets?.swaggerUiBundleUrl ??
|
|
80
|
-
`${JSDELIVR_ORIGIN}/npm/swagger-ui-dist/swagger-ui-bundle.js`);
|
|
77
|
+
const cssUrl = escapeHtml(opts.assets?.swaggerUiCssUrl ?? `${JSDELIVR_ORIGIN}/npm/swagger-ui-dist/swagger-ui.css`);
|
|
78
|
+
const bundleUrl = escapeHtml(opts.assets?.swaggerUiBundleUrl ?? `${JSDELIVR_ORIGIN}/npm/swagger-ui-dist/swagger-ui-bundle.js`);
|
|
81
79
|
const cssSri = integrityAttr(opts.assets?.swaggerUiCssIntegrity, opts.assets?.crossOrigin);
|
|
82
80
|
const bundleSri = integrityAttr(opts.assets?.swaggerUiBundleIntegrity, opts.assets?.crossOrigin);
|
|
83
81
|
const nonce = nonceAttr(opts.scriptNonce);
|
|
@@ -97,6 +95,7 @@ export function swaggerUiHtml(opts) {
|
|
|
97
95
|
<div id="swagger"></div>
|
|
98
96
|
<script src="${bundleUrl}"${bundleSri}${nonce}></script>
|
|
99
97
|
<script${nonce}>window.onload=()=>SwaggerUIBundle(${configuration});</script>
|
|
98
|
+
${docsAuthLauncherHtml(opts.auth, opts.scriptNonce)}
|
|
100
99
|
</body></html>`;
|
|
101
100
|
}
|
|
102
101
|
/**
|
|
@@ -115,8 +114,7 @@ export function swaggerUiHtml(opts) {
|
|
|
115
114
|
*/
|
|
116
115
|
export function redocHtml(opts) {
|
|
117
116
|
const title = escapeHtml(opts.title ?? "API Docs");
|
|
118
|
-
const scriptUrl = escapeHtml(opts.assets?.redocScriptUrl ??
|
|
119
|
-
`${JSDELIVR_ORIGIN}/npm/redoc/bundles/redoc.standalone.js`);
|
|
117
|
+
const scriptUrl = escapeHtml(opts.assets?.redocScriptUrl ?? `${JSDELIVR_ORIGIN}/npm/redoc/bundles/redoc.standalone.js`);
|
|
120
118
|
const scriptSri = integrityAttr(opts.assets?.redocScriptIntegrity, opts.assets?.crossOrigin);
|
|
121
119
|
const nonce = nonceAttr(opts.scriptNonce);
|
|
122
120
|
const specArg = jsonForScript(opts.specUrl);
|
|
@@ -130,6 +128,7 @@ export function redocHtml(opts) {
|
|
|
130
128
|
<div id="redoc"></div>
|
|
131
129
|
<script src="${scriptUrl}"${scriptSri}${nonce}></script>
|
|
132
130
|
<script${nonce}>Redoc.init(${specArg},${optionsArg},document.getElementById("redoc"));</script>
|
|
131
|
+
${docsAuthLauncherHtml(opts.auth, opts.scriptNonce)}
|
|
133
132
|
</body></html>`;
|
|
134
133
|
}
|
|
135
134
|
/**
|
|
@@ -238,6 +237,46 @@ function escapeHtml(s) {
|
|
|
238
237
|
function jsonForScript(value) {
|
|
239
238
|
return JSON.stringify(value).replace(/[<\u2028\u2029]/g, (c) => ({ "<": "\\u003c", "\u2028": "\\u2028", "\u2029": "\\u2029" })[c]);
|
|
240
239
|
}
|
|
240
|
+
function docsAuthLauncherHtml(auth, scriptNonce) {
|
|
241
|
+
if (!auth)
|
|
242
|
+
return "";
|
|
243
|
+
const loginUrl = normalizeDocsAuthLoginUrl(auth.loginUrl);
|
|
244
|
+
const label = auth.label ?? "Authorize";
|
|
245
|
+
const description = auth.description ?? "Open login or identity provider";
|
|
246
|
+
const target = auth.target ?? "popup";
|
|
247
|
+
const popupWidth = positiveIntegerOrDefault(auth.popupWidth, 520);
|
|
248
|
+
const popupHeight = positiveIntegerOrDefault(auth.popupHeight, 720);
|
|
249
|
+
const payload = jsonForScript({
|
|
250
|
+
loginUrl,
|
|
251
|
+
target,
|
|
252
|
+
popupWidth,
|
|
253
|
+
popupHeight,
|
|
254
|
+
});
|
|
255
|
+
const nonce = nonceAttr(scriptNonce);
|
|
256
|
+
return `<style>
|
|
257
|
+
.daloy-docs-auth{position:fixed;right:16px;top:16px;z-index:2147483647;display:inline-flex;align-items:center;gap:8px;border:1px solid #1d4ed8;border-radius:6px;background:#2563eb;color:#fff;font:600 14px/1.2 system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;padding:10px 14px;box-shadow:0 8px 24px rgba(15,23,42,.18);cursor:pointer}
|
|
258
|
+
.daloy-docs-auth:focus{outline:3px solid rgba(37,99,235,.35);outline-offset:2px}
|
|
259
|
+
</style>
|
|
260
|
+
<button type="button" class="daloy-docs-auth" data-daloy-docs-auth title="${escapeHtml(description)}" aria-label="${escapeHtml(description)}">${escapeHtml(label)}</button>
|
|
261
|
+
<script${nonce}>(()=>{const o=${payload};const b=document.querySelector("[data-daloy-docs-auth]");if(!b)return;b.addEventListener("click",()=>{if(o.target==="_self"){window.location.assign(o.loginUrl);return;}if(o.target==="_blank"){window.open(o.loginUrl,"_blank","noopener,noreferrer");return;}const left=Math.max(0,Math.round((window.screenX||0)+((window.outerWidth||o.popupWidth)-o.popupWidth)/2));const top=Math.max(0,Math.round((window.screenY||0)+((window.outerHeight||o.popupHeight)-o.popupHeight)/2));const features="popup=yes,width="+o.popupWidth+",height="+o.popupHeight+",left="+left+",top="+top+",noopener,noreferrer";window.open(o.loginUrl,"daloy_docs_auth",features);});})();</script>`;
|
|
262
|
+
}
|
|
263
|
+
function normalizeDocsAuthLoginUrl(loginUrl) {
|
|
264
|
+
if (typeof loginUrl !== "string" || loginUrl.trim() === "") {
|
|
265
|
+
throw new TypeError("docs auth loginUrl must be a non-empty string");
|
|
266
|
+
}
|
|
267
|
+
const trimmed = loginUrl.trim();
|
|
268
|
+
const parsed = new URL(trimmed, "https://daloyjs.local");
|
|
269
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
270
|
+
throw new TypeError(`docs auth loginUrl must be an http(s) or relative URL; got ${JSON.stringify(loginUrl)}`);
|
|
271
|
+
}
|
|
272
|
+
return trimmed;
|
|
273
|
+
}
|
|
274
|
+
function positiveIntegerOrDefault(value, fallback) {
|
|
275
|
+
if (typeof value === "number" && Number.isInteger(value) && value > 0) {
|
|
276
|
+
return value;
|
|
277
|
+
}
|
|
278
|
+
return fallback;
|
|
279
|
+
}
|
|
241
280
|
function scalarConfigurationAttr(specUrl, configuration) {
|
|
242
281
|
if (!configuration)
|
|
243
282
|
return "";
|
package/dist/index.d.ts
CHANGED
|
@@ -11,28 +11,28 @@ export type { BehindProxyConfig, ConnInfo } from "./conn-info.js";
|
|
|
11
11
|
export { subdomains, PSL_SNAPSHOT_DATE, PSL_PUBLIC_SUFFIXES, MAX_SNAPSHOT_AGE_DAYS, } from "./subdomains.js";
|
|
12
12
|
export type { SubdomainsOptions, SubdomainsResult } from "./subdomains.js";
|
|
13
13
|
export { defineDependency, DEPENDENCY_MARKER } from "./dependency.js";
|
|
14
|
-
export type { DependencyHooks, DependencyOptions
|
|
14
|
+
export type { DependencyHooks, DependencyOptions } from "./dependency.js";
|
|
15
15
|
export type { RouteDefinition, HttpMethod, PathString, RequestSchemas, ResponsesMap, ResponseSpec, AuthSpec, Hooks, BaseContext, AppState, AuthScheme, AuthContext, HandlerReturn, InferRequest, ParamsOf, PathParams, CallbackDefinition, CallbackMap, CallbackOperation, RouteExample, RouteMeta, } from "./types.js";
|
|
16
16
|
export { HttpError, BadRequestError, ValidationError, NotFoundError, ConflictError, UnauthorizedError, ForbiddenError, MethodNotAllowedError, PayloadTooLargeError, RequestHeaderFieldsTooLargeError, UnsupportedMediaTypeError, TooManyRequestsError, RequestTimeoutError, InternalError, MessageLeakError, httpError, SAFE_CUSTOM_ERROR_RESPONSE_HEADERS, checkCustomErrorResponseHeaders, } from "./errors.js";
|
|
17
17
|
export type { ProblemDetails, ProblemRenderOptions, HttpErrorOptions } from "./errors.js";
|
|
18
18
|
export type { StandardSchemaV1 } from "./schema.js";
|
|
19
19
|
export { validate, isStandardSchema } from "./schema.js";
|
|
20
20
|
export { diffOpenAPI, hasBreakingChanges } from "./openapi-diff.js";
|
|
21
|
-
export type { ChangeSeverity, OpenAPIChange, OpenAPIDiffResult
|
|
21
|
+
export type { ChangeSeverity, OpenAPIChange, OpenAPIDiffResult } from "./openapi-diff.js";
|
|
22
22
|
export { readBodyLimited, safeJsonParse, isForbiddenObjectKey, sanitizeHeaderName, sanitizeHeaderValue, timingSafeEqual, randomId, assertNoDuplicateSingletonHeaders, assertNoReservedInternalHeaders, assertHeaderCountWithinLimit, DEFAULT_MAX_HEADER_COUNT, RESERVED_INBOUND_HEADER_PREFIXES, SMUGGLING_SINGLETON_HEADERS, verifyWebhookSignature, signWebhookPayload, WEBHOOK_DEFAULT_TOLERANCE_SECONDS, assertStrongSecret, MIN_PROD_SECRET_BYTES, WEAK_SECRET_STRINGS, sanitizeFilename, assertSafeRelativePath, hasMongoOperatorKeys, assertNoMongoOperators, } from "./security.js";
|
|
23
23
|
export type { WebhookHmacAlgorithm } from "./security.js";
|
|
24
24
|
export { requestId, secureHeaders, SECURE_HEADERS_MARKER, cors, CORS_HOOK_MARKER, CORS_ORIGIN_ALLOW_MARKER, CORS_WILDCARD_ORIGIN_MARKER, rateLimit, loginThrottle, timing, bearerAuth, basicAuth, csrf, CSRF_HOOK_MARKER, fetchMetadata, requireScopes, REQUIRE_SCOPES_AGGREGATE_KEY, REQUIRE_SCOPES_HOOK_MARKER, _resetSharedRateLimitStoresForTests, } from "./middleware.js";
|
|
25
25
|
export { etag } from "./etag.js";
|
|
26
26
|
export type { ETagOptions } from "./etag.js";
|
|
27
27
|
export { compression, COMPRESSION_HOOK_MARKER, _resetCompressionRuntimeProbeForTests, } from "./compression.js";
|
|
28
|
-
export type { CompressionEncoding, CompressionOptions
|
|
28
|
+
export type { CompressionEncoding, CompressionOptions } from "./compression.js";
|
|
29
29
|
export { createJwtSigner, createJwtVerifier, JwtError, DEFAULT_JWT_MAX_LIFETIME_SECONDS, } from "./jwt.js";
|
|
30
30
|
export type { JwtAlgorithm, JwtKeyMaterial, JwtSignerOptions, JwtVerifierOptions, JwtVerified, } from "./jwt.js";
|
|
31
31
|
export { jwk } from "./jwk.js";
|
|
32
|
-
export type { JwkAlgorithm, JwkOptions, JwkSet, JwkSource, JwkVerifyHook
|
|
32
|
+
export type { JwkAlgorithm, JwkOptions, JwkSet, JwkSource, JwkVerifyHook } from "./jwk.js";
|
|
33
33
|
export { serializeCookie, serializeClearCookie, assertCookieAttributes, readRequestCookie, } from "./cookie.js";
|
|
34
34
|
export type { CookieAttributes, CookieSameSite } from "./cookie.js";
|
|
35
|
-
export { assertTemporalClaims, TemporalClaimError
|
|
35
|
+
export { assertTemporalClaims, TemporalClaimError } from "./time-claims.js";
|
|
36
36
|
export type { TemporalClaims, TemporalClaimErrorCode, AssertTemporalClaimsOptions, } from "./time-claims.js";
|
|
37
37
|
export { every, some, except } from "./combine.js";
|
|
38
38
|
export type { ExceptPredicate } from "./combine.js";
|
|
@@ -42,24 +42,24 @@ export { fetchGuard, SsrfBlockedError } from "./fetch-guard.js";
|
|
|
42
42
|
export type { FetchGuardOptions, SsrfBlockReason } from "./fetch-guard.js";
|
|
43
43
|
export { resilientFetch, CircuitBreaker, CircuitOpenError, FetchTimeoutError, } from "./fetch-resilience.js";
|
|
44
44
|
export type { ResilientFetchOptions, CircuitBreakerOptions, CircuitState, RetryContext, } from "./fetch-resilience.js";
|
|
45
|
-
export { createWebhookSender, MemoryWebhookDeadLetterSink
|
|
45
|
+
export { createWebhookSender, MemoryWebhookDeadLetterSink } from "./webhook-delivery.js";
|
|
46
46
|
export type { WebhookEvent, WebhookSenderOptions, WebhookDeliveryResult, WebhookDeadLetter, WebhookDeadLetterSink, WebhookAttempt, } from "./webhook-delivery.js";
|
|
47
|
-
export { Scheduler, CronParseError, parseCron, nextCronRun
|
|
47
|
+
export { Scheduler, CronParseError, parseCron, nextCronRun } from "./scheduler.js";
|
|
48
48
|
export type { SchedulerOptions, SchedulerLogger, TimerFns, TaskDefinition, TaskHandler, TaskRunContext, TaskErrorInfo, TaskState, CronFields, } from "./scheduler.js";
|
|
49
49
|
export { clientCertAuth, setClientCertificate, getClientCertificate, normalizePeerCertificate, parseForwardedClientCert, } from "./mtls.js";
|
|
50
50
|
export type { ClientCertificate, ClientCertificateSource, ClientCertAuthOptions, ClientCertHeaderConfig, PeerCertificateLike, } from "./mtls.js";
|
|
51
51
|
export { signMessage, signRequest, verifyMessage, verifyRequest, httpSignatureAuth, contentDigest, verifyContentDigest, DEFAULT_SIGNATURE_LABEL, DEFAULT_MAX_SIGNATURE_AGE_SECONDS, DEFAULT_SIGNATURE_CLOCK_SKEW_SECONDS, } from "./http-signatures.js";
|
|
52
52
|
export type { HttpSignatureAlgorithm, HttpSignatureKeyMaterial, HttpSignatureKey, SignMessageOptions, SignRequestOptions, MessageSignature, VerifyMessageOptions, VerifyResult, VerifySuccess, VerifyFailure, KeyResolutionInfo, HttpSignatureAuthOptions, ContentDigestAlgorithm, } from "./http-signatures.js";
|
|
53
|
-
export { autoBan, MemoryAutoBanStore, _resetAutoBanStoresForTests
|
|
53
|
+
export { autoBan, MemoryAutoBanStore, _resetAutoBanStoresForTests } from "./auto-ban.js";
|
|
54
54
|
export type { AutoBanOptions, AutoBanStore, AutoBanRecord, AutoBanEvent, AutoBanStrikeEvent, } from "./auto-ban.js";
|
|
55
55
|
export { botGuard, GOOGLEBOT, BINGBOT, WELL_KNOWN_BOTS } from "./bot-guard.js";
|
|
56
|
-
export type { BotGuardOptions, BotGuardEvent, BotResolver, VerifiedBotRule
|
|
56
|
+
export type { BotGuardOptions, BotGuardEvent, BotResolver, VerifiedBotRule } from "./bot-guard.js";
|
|
57
57
|
export { ipReputation, urlFeed } from "./ip-reputation.js";
|
|
58
58
|
export type { IpReputationOptions, IpReputationFeed, IpReputationMatch, IpReputationController, UrlFeedOptions, } from "./ip-reputation.js";
|
|
59
59
|
export { geoBlock } from "./geo-block.js";
|
|
60
60
|
export type { GeoBlockOptions, GeoBlockDecision, GeoBlockReason, GeoState, CountryFromIp, CountryFromContext, } from "./geo-block.js";
|
|
61
61
|
export { concurrencyLimit } from "./concurrency-limit.js";
|
|
62
|
-
export type { ConcurrencyLimitOptions, ConcurrencyRejection
|
|
62
|
+
export type { ConcurrencyLimitOptions, ConcurrencyRejection } from "./concurrency-limit.js";
|
|
63
63
|
export { requestDecompression, decompressRequestBody, DecompressionBombError, UnsupportedContentEncodingError, MalformedCompressedBodyError, _resetRequestDecompressionProbeForTests, } from "./request-decompression.js";
|
|
64
64
|
export type { RequestDecompressionOptions, RequestDecompressionEncoding, DecompressionBombInfo, } from "./request-decompression.js";
|
|
65
65
|
export { waf } from "./waf.js";
|
|
@@ -67,17 +67,17 @@ export type { WafOptions, WafMode, WafRuleId, WafRuleConfig, WafInspectConfig, W
|
|
|
67
67
|
export { safeRedirect, OpenRedirectBlockedError } from "./safe-redirect.js";
|
|
68
68
|
export type { SafeRedirectOptions, SafeRedirectStatus, SafeRedirectBlockReason, } from "./safe-redirect.js";
|
|
69
69
|
export { loadShedding, LOAD_SHEDDING_MARKER } from "./load-shedding.js";
|
|
70
|
-
export type { LoadSheddingOptions, LoadSheddingSnapshot
|
|
70
|
+
export type { LoadSheddingOptions, LoadSheddingSnapshot } from "./load-shedding.js";
|
|
71
71
|
export { defineConfig, ConfigValidationError } from "./config.js";
|
|
72
|
-
export type { ConfigSource, DefineConfigOptions
|
|
72
|
+
export type { ConfigSource, DefineConfigOptions } from "./config.js";
|
|
73
73
|
export type { RequestIdOptions, SecureHeadersOptions, CspDirectivesOptions, CorsOptions, CorsOriginAllow, RateLimitOptions, RateLimitStore, LoginThrottleOptions, CsrfOptions, CsrfCookieOptions, FetchMetadataOptions, BasicAuthOptions, } from "./middleware.js";
|
|
74
74
|
export type { BearerAuthOptions, BearerAuthVerifyHook } from "./middleware.js";
|
|
75
75
|
export { createLogger, noopLogger, DEFAULT_REDACT_KEYS } from "./logger.js";
|
|
76
|
-
export type { Logger, LogLevel, ConsoleLoggerOptions, LoggerRedactionOptions
|
|
77
|
-
export type { ScalarJsonPrimitive, ScalarJsonValue, ScalarReferenceConfiguration, ScalarTheme, RedocConfiguration, RedocHtmlOptions, SwaggerUiConfiguration, SwaggerUiHtmlOptions, AsyncApiHtmlOptions, DocsAssetOptions, } from "./docs.js";
|
|
76
|
+
export type { Logger, LogLevel, ConsoleLoggerOptions, LoggerRedactionOptions } from "./logger.js";
|
|
77
|
+
export type { ScalarJsonPrimitive, ScalarJsonValue, ScalarReferenceConfiguration, ScalarTheme, RedocConfiguration, RedocHtmlOptions, SwaggerUiConfiguration, SwaggerUiHtmlOptions, AsyncApiHtmlOptions, DocsAssetOptions, DocsAuthLauncherOptions, } from "./docs.js";
|
|
78
78
|
export { formatStartupBanner, printStartupBanner } from "./banner.js";
|
|
79
79
|
export type { StartupBannerLink, StartupBannerOptions } from "./banner.js";
|
|
80
|
-
export { sseStream, sseResponse, ndjsonStream, ndjsonResponse
|
|
80
|
+
export { sseStream, sseResponse, ndjsonStream, ndjsonResponse } from "./streaming.js";
|
|
81
81
|
export type { SSEMessage, StreamOptions, SSEStreamOptions, SSEResponseOptions, NDJSONResponseOptions, } from "./streaming.js";
|
|
82
82
|
export { httpBearerScheme, httpBasicScheme, apiKeyScheme, oauth2Scheme, openIdConnectScheme, REQUIRE_PAYLOAD_AUTH_EXTENSION, securitySchemeRequiresPayloadAuth, toOpenAPISecurityScheme, } from "./security-schemes.js";
|
|
83
83
|
export type { ApiKeyLocation, ApiKeyScheme, ApiKeySchemeOptions, HttpBasicScheme, HttpBasicSchemeOptions, HttpBearerScheme, HttpBearerSchemeOptions, OAuth2AuthorizationCodeFlow, OAuth2ClientCredentialsFlow, OAuth2Flows, OAuth2ImplicitFlow, OAuth2PasswordFlow, OAuth2Scheme, OAuth2SchemeOptions, OpenIdConnectScheme, OpenIdConnectSchemeOptions, SecurityScheme, RequirePayloadAuthExtension, } from "./security-schemes.js";
|
|
@@ -88,11 +88,11 @@ export type { SessionOptions, SessionCookieOptions, SessionContext, SessionRecor
|
|
|
88
88
|
export { idempotency, MemoryIdempotencyStore, _resetSharedIdempotencyStoresForTests, } from "./idempotency.js";
|
|
89
89
|
export type { IdempotencyOptions, IdempotencyStore, IdempotencyRecord, StoredIdempotentResponse, } from "./idempotency.js";
|
|
90
90
|
export { responseCache, MemoryResponseCacheStore, _resetSharedResponseCacheStoresForTests, } from "./response-cache.js";
|
|
91
|
-
export type { ResponseCacheOptions, ResponseCacheStore, CachedResponse
|
|
91
|
+
export type { ResponseCacheOptions, ResponseCacheStore, CachedResponse } from "./response-cache.js";
|
|
92
92
|
export { encodeCursor, decodeCursor, buildLinkHeader, buildPageLinks, paginationQuery, MAX_CURSOR_LENGTH, } from "./pagination.js";
|
|
93
93
|
export type { PaginationLink, PageLinkOptions, PageLinks, PaginationQueryOptions, PaginationParams, PaginationQuerySchema, } from "./pagination.js";
|
|
94
94
|
export { MetricsRegistry, Counter, Gauge, Histogram, httpMetrics, DEFAULT_DURATION_BUCKETS, PROMETHEUS_CONTENT_TYPE, } from "./metrics.js";
|
|
95
|
-
export type { MetricLabels, MetricsRegistryOptions, HttpMetricsOptions
|
|
95
|
+
export type { MetricLabels, MetricsRegistryOptions, HttpMetricsOptions } from "./metrics.js";
|
|
96
96
|
export { fileField, multipartObject, isFileFieldSchema, isMultipartObjectSchema, } from "./multipart.js";
|
|
97
97
|
export type { FileFieldSchema, FileFieldOptions, FileMagicBytesOption, FileMagicBytesSignature, MultipartObjectOptions, MultipartShape, UploadedFile, } from "./multipart.js";
|
|
98
98
|
export { otelTracing, TRACING_SPAN_KIND_SERVER, TRACING_SPAN_STATUS_UNSET, TRACING_SPAN_STATUS_OK, TRACING_SPAN_STATUS_ERROR, } from "./tracing.js";
|
package/dist/index.js
CHANGED
|
@@ -18,16 +18,16 @@ export { compression, COMPRESSION_HOOK_MARKER, _resetCompressionRuntimeProbeForT
|
|
|
18
18
|
export { createJwtSigner, createJwtVerifier, JwtError, DEFAULT_JWT_MAX_LIFETIME_SECONDS, } from "./jwt.js";
|
|
19
19
|
export { jwk } from "./jwk.js";
|
|
20
20
|
export { serializeCookie, serializeClearCookie, assertCookieAttributes, readRequestCookie, } from "./cookie.js";
|
|
21
|
-
export { assertTemporalClaims, TemporalClaimError
|
|
21
|
+
export { assertTemporalClaims, TemporalClaimError } from "./time-claims.js";
|
|
22
22
|
export { every, some, except } from "./combine.js";
|
|
23
23
|
export { ipRestriction } from "./ip-restriction.js";
|
|
24
24
|
export { fetchGuard, SsrfBlockedError } from "./fetch-guard.js";
|
|
25
25
|
export { resilientFetch, CircuitBreaker, CircuitOpenError, FetchTimeoutError, } from "./fetch-resilience.js";
|
|
26
|
-
export { createWebhookSender, MemoryWebhookDeadLetterSink
|
|
27
|
-
export { Scheduler, CronParseError, parseCron, nextCronRun
|
|
26
|
+
export { createWebhookSender, MemoryWebhookDeadLetterSink } from "./webhook-delivery.js";
|
|
27
|
+
export { Scheduler, CronParseError, parseCron, nextCronRun } from "./scheduler.js";
|
|
28
28
|
export { clientCertAuth, setClientCertificate, getClientCertificate, normalizePeerCertificate, parseForwardedClientCert, } from "./mtls.js";
|
|
29
29
|
export { signMessage, signRequest, verifyMessage, verifyRequest, httpSignatureAuth, contentDigest, verifyContentDigest, DEFAULT_SIGNATURE_LABEL, DEFAULT_MAX_SIGNATURE_AGE_SECONDS, DEFAULT_SIGNATURE_CLOCK_SKEW_SECONDS, } from "./http-signatures.js";
|
|
30
|
-
export { autoBan, MemoryAutoBanStore, _resetAutoBanStoresForTests
|
|
30
|
+
export { autoBan, MemoryAutoBanStore, _resetAutoBanStoresForTests } from "./auto-ban.js";
|
|
31
31
|
export { botGuard, GOOGLEBOT, BINGBOT, WELL_KNOWN_BOTS } from "./bot-guard.js";
|
|
32
32
|
export { ipReputation, urlFeed } from "./ip-reputation.js";
|
|
33
33
|
export { geoBlock } from "./geo-block.js";
|
|
@@ -39,7 +39,7 @@ export { loadShedding, LOAD_SHEDDING_MARKER } from "./load-shedding.js";
|
|
|
39
39
|
export { defineConfig, ConfigValidationError } from "./config.js";
|
|
40
40
|
export { createLogger, noopLogger, DEFAULT_REDACT_KEYS } from "./logger.js";
|
|
41
41
|
export { formatStartupBanner, printStartupBanner } from "./banner.js";
|
|
42
|
-
export { sseStream, sseResponse, ndjsonStream, ndjsonResponse
|
|
42
|
+
export { sseStream, sseResponse, ndjsonStream, ndjsonResponse } from "./streaming.js";
|
|
43
43
|
export { httpBearerScheme, httpBasicScheme, apiKeyScheme, oauth2Scheme, openIdConnectScheme, REQUIRE_PAYLOAD_AUTH_EXTENSION, securitySchemeRequiresPayloadAuth, toOpenAPISecurityScheme, } from "./security-schemes.js";
|
|
44
44
|
export { discriminator, discriminatedUnion } from "./discriminator.js";
|
|
45
45
|
export { session, rotateSession, signValue, verifySignedValue, MemorySessionStore, SESSION_HOOK_MARKER, SESSION_SECRETS_MARKER, } from "./session.js";
|
package/dist/sbom.cdx.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"bomFormat": "CycloneDX",
|
|
3
3
|
"specVersion": "1.5",
|
|
4
|
-
"serialNumber": "urn:uuid:
|
|
4
|
+
"serialNumber": "urn:uuid:448a4447-0b88-5512-8ce5-485b6688ff4c",
|
|
5
5
|
"version": 1,
|
|
6
6
|
"metadata": {
|
|
7
|
-
"timestamp": "2026-
|
|
7
|
+
"timestamp": "2026-07-01T13:38:31.674Z",
|
|
8
8
|
"tools": [
|
|
9
9
|
{
|
|
10
10
|
"vendor": "DaloyJS",
|
|
11
11
|
"name": "daloy-generate-sbom",
|
|
12
|
-
"version": "1.0.0-beta.
|
|
12
|
+
"version": "1.0.0-beta.5"
|
|
13
13
|
}
|
|
14
14
|
],
|
|
15
15
|
"authors": [
|
|
@@ -19,11 +19,11 @@
|
|
|
19
19
|
],
|
|
20
20
|
"component": {
|
|
21
21
|
"type": "library",
|
|
22
|
-
"bom-ref": "pkg:npm/@daloyjs/core@1.0.0-beta.
|
|
22
|
+
"bom-ref": "pkg:npm/@daloyjs/core@1.0.0-beta.5",
|
|
23
23
|
"name": "@daloyjs/core",
|
|
24
|
-
"version": "1.0.0-beta.
|
|
24
|
+
"version": "1.0.0-beta.5",
|
|
25
25
|
"description": "DaloyJS is a runtime-portable, contract-first TypeScript web framework with built-in OpenAPI (Hey API), typed client generation, large-scale maintainability, and security-first defaults. Hono-grade portability, Elysia-grade DX, FastAPI-grade docs, Fastify-grade ops — distributed via pnpm.",
|
|
26
|
-
"purl": "pkg:npm/@daloyjs/core@1.0.0-beta.
|
|
26
|
+
"purl": "pkg:npm/@daloyjs/core@1.0.0-beta.5",
|
|
27
27
|
"licenses": [
|
|
28
28
|
{
|
|
29
29
|
"license": {
|
|
@@ -46,9 +46,9 @@
|
|
|
46
46
|
}
|
|
47
47
|
],
|
|
48
48
|
"swid": {
|
|
49
|
-
"tagId": "swidtag--daloyjs-core-1.0.0-beta.
|
|
49
|
+
"tagId": "swidtag--daloyjs-core-1.0.0-beta.5",
|
|
50
50
|
"name": "@daloyjs/core",
|
|
51
|
-
"version": "1.0.0-beta.
|
|
51
|
+
"version": "1.0.0-beta.5",
|
|
52
52
|
"tagVersion": 0,
|
|
53
53
|
"patch": false
|
|
54
54
|
}
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"components": [],
|
|
58
58
|
"dependencies": [
|
|
59
59
|
{
|
|
60
|
-
"ref": "pkg:npm/@daloyjs/core@1.0.0-beta.
|
|
60
|
+
"ref": "pkg:npm/@daloyjs/core@1.0.0-beta.5",
|
|
61
61
|
"dependsOn": []
|
|
62
62
|
}
|
|
63
63
|
]
|
package/dist/sbom.spdx.json
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"spdxVersion": "SPDX-2.3",
|
|
3
3
|
"dataLicense": "CC0-1.0",
|
|
4
4
|
"SPDXID": "SPDXRef-DOCUMENT",
|
|
5
|
-
"name": "@daloyjs/core-1.0.0-beta.
|
|
6
|
-
"documentNamespace": "https://github.com/daloyjs/daloy/sbom/@daloyjs/core-1.0.0-beta.
|
|
5
|
+
"name": "@daloyjs/core-1.0.0-beta.5",
|
|
6
|
+
"documentNamespace": "https://github.com/daloyjs/daloy/sbom/@daloyjs/core-1.0.0-beta.5-448a4447-0b88-5512-8ce5-485b6688ff4c",
|
|
7
7
|
"creationInfo": {
|
|
8
|
-
"created": "2026-
|
|
8
|
+
"created": "2026-07-01T13:38:31.674Z",
|
|
9
9
|
"creators": [
|
|
10
10
|
"Tool: daloy-generate-sbom",
|
|
11
11
|
"Organization: DaloyJS"
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
{
|
|
17
17
|
"SPDXID": "SPDXRef-Package--daloyjs-core",
|
|
18
18
|
"name": "@daloyjs/core",
|
|
19
|
-
"versionInfo": "1.0.0-beta.
|
|
19
|
+
"versionInfo": "1.0.0-beta.5",
|
|
20
20
|
"downloadLocation": "https://github.com/daloyjs/daloy",
|
|
21
21
|
"filesAnalyzed": false,
|
|
22
22
|
"licenseConcluded": "MIT",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
{
|
|
28
28
|
"referenceCategory": "PACKAGE-MANAGER",
|
|
29
29
|
"referenceType": "purl",
|
|
30
|
-
"referenceLocator": "pkg:npm/@daloyjs/core@1.0.0-beta.
|
|
30
|
+
"referenceLocator": "pkg:npm/@daloyjs/core@1.0.0-beta.5"
|
|
31
31
|
}
|
|
32
32
|
]
|
|
33
33
|
}
|
package/dist/tenancy.d.ts
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* once per request, validates and normalizes it, and exposes it on
|
|
6
6
|
* `ctx.state.tenant` for handlers and downstream middleware. It is the
|
|
7
7
|
* single source of truth for "who is this request for" so the per-tenant
|
|
8
|
-
* isolation knobs on the rest of the framework (`rateLimit`
|
|
9
|
-
* `
|
|
10
|
-
* off the same resolved value via {@link tenantScope}.
|
|
8
|
+
* isolation knobs on the rest of the framework (`rateLimit` /
|
|
9
|
+
* `responseCache` `keyGenerator`, `concurrencyLimit` / `idempotency` `scope`)
|
|
10
|
+
* can all key off the same resolved value via {@link tenantScope}.
|
|
11
11
|
*
|
|
12
12
|
* Secure-by-default posture:
|
|
13
13
|
*
|
|
@@ -227,10 +227,19 @@ export interface TenantScopeOptions {
|
|
|
227
227
|
* or poison another tenant's:
|
|
228
228
|
*
|
|
229
229
|
* ```ts
|
|
230
|
-
*
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
*
|
|
230
|
+
* const scope = tenantScope();
|
|
231
|
+
* rateLimit({ windowMs: 60_000, max: 100, keyGenerator: scope });
|
|
232
|
+
* concurrencyLimit({ maxConcurrent: 20, scope });
|
|
233
|
+
* idempotency({ scope }); // CWE-524 cross-tenant cache defense
|
|
234
|
+
* // responseCache's keyGenerator REPLACES the whole key and it takes
|
|
235
|
+
* // ttlSeconds, so fold the tenant in alongside the path yourself:
|
|
236
|
+
* responseCache({
|
|
237
|
+
* ttlSeconds: 30,
|
|
238
|
+
* keyGenerator: (ctx) => {
|
|
239
|
+
* const u = new URL(ctx.request.url);
|
|
240
|
+
* return `${scope(ctx)}:${ctx.request.method} ${u.pathname}${u.search}`;
|
|
241
|
+
* },
|
|
242
|
+
* });
|
|
234
243
|
* ```
|
|
235
244
|
*
|
|
236
245
|
* The `tenant:` prefix keeps these keys from colliding with other key spaces
|
package/dist/tenancy.js
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* once per request, validates and normalizes it, and exposes it on
|
|
6
6
|
* `ctx.state.tenant` for handlers and downstream middleware. It is the
|
|
7
7
|
* single source of truth for "who is this request for" so the per-tenant
|
|
8
|
-
* isolation knobs on the rest of the framework (`rateLimit`
|
|
9
|
-
* `
|
|
10
|
-
* off the same resolved value via {@link tenantScope}.
|
|
8
|
+
* isolation knobs on the rest of the framework (`rateLimit` /
|
|
9
|
+
* `responseCache` `keyGenerator`, `concurrencyLimit` / `idempotency` `scope`)
|
|
10
|
+
* can all key off the same resolved value via {@link tenantScope}.
|
|
11
11
|
*
|
|
12
12
|
* Secure-by-default posture:
|
|
13
13
|
*
|
|
@@ -270,10 +270,19 @@ export function tenancy(opts) {
|
|
|
270
270
|
* or poison another tenant's:
|
|
271
271
|
*
|
|
272
272
|
* ```ts
|
|
273
|
-
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
273
|
+
* const scope = tenantScope();
|
|
274
|
+
* rateLimit({ windowMs: 60_000, max: 100, keyGenerator: scope });
|
|
275
|
+
* concurrencyLimit({ maxConcurrent: 20, scope });
|
|
276
|
+
* idempotency({ scope }); // CWE-524 cross-tenant cache defense
|
|
277
|
+
* // responseCache's keyGenerator REPLACES the whole key and it takes
|
|
278
|
+
* // ttlSeconds, so fold the tenant in alongside the path yourself:
|
|
279
|
+
* responseCache({
|
|
280
|
+
* ttlSeconds: 30,
|
|
281
|
+
* keyGenerator: (ctx) => {
|
|
282
|
+
* const u = new URL(ctx.request.url);
|
|
283
|
+
* return `${scope(ctx)}:${ctx.request.method} ${u.pathname}${u.search}`;
|
|
284
|
+
* },
|
|
285
|
+
* });
|
|
277
286
|
* ```
|
|
278
287
|
*
|
|
279
288
|
* The `tenant:` prefix keeps these keys from colliding with other key spaces
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@daloyjs/core",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.5",
|
|
4
4
|
"description": "DaloyJS is a runtime-portable, contract-first TypeScript web framework with built-in OpenAPI (Hey API), typed client generation, large-scale maintainability, and security-first defaults. Hono-grade portability, Elysia-grade DX, FastAPI-grade docs, Fastify-grade ops — distributed via pnpm.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"daloy": "bin/daloy.mjs"
|
|
38
38
|
},
|
|
39
39
|
"engines": {
|
|
40
|
-
"node": "
|
|
40
|
+
"node": "^24.0.0 || >=26.0.0",
|
|
41
41
|
"pnpm": ">=11.0.0"
|
|
42
42
|
},
|
|
43
43
|
"exports": {
|
|
@@ -227,9 +227,9 @@
|
|
|
227
227
|
}
|
|
228
228
|
},
|
|
229
229
|
"devDependencies": {
|
|
230
|
-
"@hey-api/openapi-ts": "^0.
|
|
231
|
-
"@types/node": "^
|
|
232
|
-
"fast-check": "^
|
|
230
|
+
"@hey-api/openapi-ts": "^0.99.0",
|
|
231
|
+
"@types/node": "^26.0.1",
|
|
232
|
+
"fast-check": "^4.8.0",
|
|
233
233
|
"prettier": "^3.8.3",
|
|
234
234
|
"tsx": "^4.22.3",
|
|
235
235
|
"typescript": "^6.0.3",
|
|
@@ -240,6 +240,7 @@
|
|
|
240
240
|
"dev": "tsc -w -p tsconfig.json",
|
|
241
241
|
"example": "node --import tsx examples/basic.ts",
|
|
242
242
|
"bench": "node --import tsx bench/router.bench.ts",
|
|
243
|
+
"bench:serverless": "node --import tsx bench/serverless-cold-path.bench.ts",
|
|
243
244
|
"test": "node --import tsx --test tests/**/*.test.ts",
|
|
244
245
|
"test:red-team": "node --import tsx --test tests/red-team-attacks.test.ts tests/red-team-attacks-2.test.ts tests/red-team-attacks-3.test.ts tests/red-team-attacks-4.test.ts tests/red-team-attacks-5.test.ts tests/red-team-attacks-6.test.ts tests/red-team-attacks-7.test.ts tests/red-team-attacks-8.test.ts tests/red-team-attacks-9.test.ts tests/red-team-attacks-10.test.ts",
|
|
245
246
|
"red-team:live": "node --import tsx red-team-live/run.ts",
|