@lunora/runtime 1.0.0-alpha.14 → 1.0.0-alpha.16
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.mts +88 -10
- package/dist/index.d.ts +88 -10
- package/dist/index.mjs +2 -2
- package/dist/packem_shared/{composeWorker-M4mPqTJx.mjs → composeWorker-BnZf6iRH.mjs} +132 -4
- package/dist/packem_shared/{decorateResponse-HRXo-oOD.mjs → decorateResponse-igd8FJqk.mjs} +4 -5
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -446,6 +446,72 @@ interface IdentityContractLike {
|
|
|
446
446
|
* the wrapped resolver; the admin path keeps the raw one (admin is gated by the
|
|
447
447
|
* bearer / Access, not the app's identity contract).
|
|
448
448
|
*/
|
|
449
|
+
/** One KV namespace as the studio's KV browser surfaces it. */
|
|
450
|
+
interface KvNamespaceSummary {
|
|
451
|
+
/** The wrangler/env binding name, e.g. `"MY_KV"`. */
|
|
452
|
+
binding: string;
|
|
453
|
+
}
|
|
454
|
+
/** One key entry as the KV admin browser surfaces it. */
|
|
455
|
+
interface KvKeyEntry {
|
|
456
|
+
/** Absolute expiration (Unix seconds), when set. */
|
|
457
|
+
expiration?: number;
|
|
458
|
+
/** Per-key metadata set at write time, or absent when none. */
|
|
459
|
+
metadata?: unknown;
|
|
460
|
+
/** The key name. */
|
|
461
|
+
name: string;
|
|
462
|
+
}
|
|
463
|
+
/** A paginated page of KV keys as the admin browser returns it. */
|
|
464
|
+
interface KvKeyListResult {
|
|
465
|
+
/** Opaque cursor for the next page; absent when the listing is complete. */
|
|
466
|
+
cursor?: string;
|
|
467
|
+
/** The keys on this page. */
|
|
468
|
+
keys: KvKeyEntry[];
|
|
469
|
+
/** True when this is the final page. */
|
|
470
|
+
listComplete: boolean;
|
|
471
|
+
}
|
|
472
|
+
/** A KV value together with its stored metadata. */
|
|
473
|
+
interface KvValueResult {
|
|
474
|
+
/** Per-key metadata, or `null` when none. */
|
|
475
|
+
metadata: unknown;
|
|
476
|
+
/** The stored value as a string, or `null` when the key is absent. */
|
|
477
|
+
value: null | string;
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* The introspector the worker wires for the studio's KV browser. Build it from
|
|
481
|
+
* the env's bound KV namespaces. Omit it and the `/_lunora/admin/kv/*`
|
|
482
|
+
* endpoints respond `KV_NOT_CONFIGURED`.
|
|
483
|
+
*/
|
|
484
|
+
interface KvIntrospector {
|
|
485
|
+
/** Delete a key from a namespace. No-op when the key is absent. */
|
|
486
|
+
deleteKey: (options: {
|
|
487
|
+
key: string;
|
|
488
|
+
namespace: string;
|
|
489
|
+
}) => Promise<void>;
|
|
490
|
+
/** Read a value (as text) and its metadata from a namespace key. */
|
|
491
|
+
getValue: (options: {
|
|
492
|
+
key: string;
|
|
493
|
+
namespace: string;
|
|
494
|
+
}) => Promise<KvValueResult>;
|
|
495
|
+
/** List keys in a namespace, optionally filtered by prefix and paginated. */
|
|
496
|
+
listKeys: (options: {
|
|
497
|
+
cursor?: string;
|
|
498
|
+
limit?: number;
|
|
499
|
+
namespace: string;
|
|
500
|
+
prefix?: string;
|
|
501
|
+
}) => Promise<KvKeyListResult>;
|
|
502
|
+
/** List the registered KV namespaces (binding names). */
|
|
503
|
+
listNamespaces: () => Promise<KvNamespaceSummary[]>;
|
|
504
|
+
/** Write a value (as text) with optional absolute expiration / relative TTL and metadata. */
|
|
505
|
+
putValue: (options: {
|
|
506
|
+
expiration?: number;
|
|
507
|
+
expirationTtl?: number;
|
|
508
|
+
key: string;
|
|
509
|
+
metadata?: unknown;
|
|
510
|
+
namespace: string;
|
|
511
|
+
value: string;
|
|
512
|
+
}) => Promise<void>;
|
|
513
|
+
}
|
|
514
|
+
/** The worker internals the KV routes reach through injection rather than closure. */
|
|
449
515
|
/**
|
|
450
516
|
* Observability hooks for the Lunora runtime.
|
|
451
517
|
*
|
|
@@ -1742,15 +1808,19 @@ interface WorkerOptions {
|
|
|
1742
1808
|
/**
|
|
1743
1809
|
* Opt into an authorization-open posture for sharded and fan-out access.
|
|
1744
1810
|
*
|
|
1745
|
-
* By default (this flag unset/`false`) the runtime FAILS CLOSED
|
|
1746
|
-
*
|
|
1747
|
-
*
|
|
1748
|
-
*
|
|
1749
|
-
* (`
|
|
1750
|
-
*
|
|
1751
|
-
*
|
|
1752
|
-
*
|
|
1753
|
-
*
|
|
1811
|
+
* By default (this flag unset/`false`) the runtime FAILS CLOSED per
|
|
1812
|
+
* operation: naming a non-default shard (a potential cross-tenant hop) is
|
|
1813
|
+
* rejected with a `403` (`FORBIDDEN_SHARD`) unless
|
|
1814
|
+
* {@link WorkerOptions.authorizeShard} is configured, and a fan-out
|
|
1815
|
+
* envelope is rejected (`FORBIDDEN_FANOUT`) unless
|
|
1816
|
+
* {@link WorkerOptions.authorizeFanOut} is. Set this to `true` to allow
|
|
1817
|
+
* such requests from any caller (including unauthenticated ones) —
|
|
1818
|
+
* appropriate only when every table is protected by per-row RLS. The
|
|
1819
|
+
* runtime then emits a single `console.warn` so the open posture stays
|
|
1820
|
+
* visible in logs. The flag is consulted per operation: it has no effect
|
|
1821
|
+
* on an operation whose own `authorize*` callback is configured (that
|
|
1822
|
+
* callback gates directly), but configuring only one of the two callbacks
|
|
1823
|
+
* does NOT cover the other operation.
|
|
1754
1824
|
*
|
|
1755
1825
|
* NOTE: this is a behaviour change from earlier alphas, where the same
|
|
1756
1826
|
* situation was warn-once-then-allow. Apps that relied on client-chosen
|
|
@@ -1958,6 +2028,14 @@ interface WorkerOptions {
|
|
|
1958
2028
|
*/
|
|
1959
2029
|
jurisdiction?: DurableObjectJurisdiction;
|
|
1960
2030
|
/**
|
|
2031
|
+
* Introspector for Workers KV namespaces, backing the studio's KV browser
|
|
2032
|
+
* via `GET /_lunora/admin/kv/namespaces`, `GET /_lunora/admin/kv/keys`,
|
|
2033
|
+
* `GET|PUT|DELETE /_lunora/admin/kv/value`. Build it from the env's bound
|
|
2034
|
+
* KV namespaces with `createKvIntrospector` from `@lunora/bindings/kv`.
|
|
2035
|
+
* Omit it and those endpoints respond `KV_NOT_CONFIGURED`.
|
|
2036
|
+
*/
|
|
2037
|
+
kvIntrospector?: KvIntrospector;
|
|
2038
|
+
/**
|
|
1961
2039
|
* Optional telemetry sink. When supplied, the worker emits one
|
|
1962
2040
|
* `onRpc` event per dispatched RPC (single-shard forward or fan-out)
|
|
1963
2041
|
* with duration / ok / error / shardKey or fanOut metadata. Sink
|
|
@@ -2541,4 +2619,4 @@ declare const analyticsEngineSink: (options: AnalyticsEngineSinkOptions) => Obse
|
|
|
2541
2619
|
*/
|
|
2542
2620
|
declare const combineSinks: (...sinks: ObservabilitySink[]) => ObservabilitySink;
|
|
2543
2621
|
declare const VERSION: string;
|
|
2544
|
-
export { type AdminTableResolver, type AirbyteMessage, type AnalyticsEngineDataPointLike, type AnalyticsEngineDatasetLike, type AnalyticsEngineSinkOptions, type AuthAdmin, type AuthCapabilities, type AuthImpersonation, type AuthIntrospector, type AuthPage, type AuthSession, type AuthUser, type BackupManifest, type BackupStore, type ComposeIdentityResolversErrorMode, type ComposeIdentityResolversOptions, type ConnectorChange, type ConnectorSyncPage, type CorsOptions, type CronHandler, type CronJobDispatch, type CronJobInfo, type CrossShardCounter, type CrossShardReader, type CrossShardRelationCapabilities, type CrossShardRelationOptions, type CsrfOptions, DEFAULT_REGISTRY_CACHE_TTL_MS, type DurableObjectJurisdiction, type DynamicShardRegistry, type DynamicShardRegistryOptions, type ExecutionContextLike, type ExportFanOutRequest, type ExportFanOutResult, type FanOutRequest, type FanOutResult, type FanOutSpec, type FivetranResponse, type FrameworkHostHandler, type FrameworkWorkerOptions, type FrameworkWorkerOptionsInput, type FunctionDescriptor, type FunctionRegistryEntry, type FunctionRegistryLike, type GlobalExportFunction as GlobalExportFn, type GlobalImportFunction as GlobalImportFn, type GlobalIntrospector, type GlobalTableInfo as GlobalTableInfoMeta, type GlobalTablePage as GlobalTablePageMeta, type HttpActionContext, type HttpActionLike, type HttpRouterLike, type IdentityContractLike, type IdentityResolver, type IdentityValidation, type ImportFanOutRequest, type ImportFanOutResult, type ListAuthUsersOptions, type LogEvent, type LogLevel, LunoraError, type LunoraErrorBody, type LunoraHandlerOptions, type LunoraWorker, type MergeStrategy, type MigrationFanOutRequest, type MigrationFanOutResult, NOOP_EXECUTION_CONTEXT, type ObservabilityEvent, type ObservabilitySink, type ObservabilitySinkContext, type QueryCoordinator, type QueryCoordinatorOptions, type RankFanOutRequest, type RankFanOutResult, type RankPageFanOutRequest, type RankPageFanOutResult, type ResolvedSecurity, type ResolvedShard, type Route, type RpcContext, type RpcEnvelope, SHARD_REGISTRY_DO_NAME, type ScheduledControllerLike, type SecurityHeadersOptions, type SecurityOptions, type SentrySinkOptions, type ShardError, type ShardExportOutcome, type ShardImportOutcome, type ShardMigrationOutcome, type ShardNamespaceLike, type ShardRankOutcome, type ShardRankPageOutcome, type ShardRegistry, type ShardTrafficEntry, type ShardTrafficFanOutRequest, type ShardTrafficFanOutResult, type ShardingInfo, type StorageListFunction as StorageListFn, type StorageObject, VERSION, type VectorIndexSummary, type VectorIntrospector, type VectorQueryMatch, type WebhookSinkOptions, type WorkerOptions, analyticsEngineSink, applyJurisdiction, combineSinks, composeIdentityResolvers, composeWorker, consoleSink, createCrossShardRelationCapabilities, createDynamicShardRegistry, createLunoraHandler, createQueryCoordinator, createStaticShardRegistry, createWorker, decorateResponse, defineRpcEnvelope, emitLogEvent, emitRpcEvent, enforceOrigin, handleCorsPreflight, mergeStrategyForAggregate, resolveLunoraOptions, resolveSecurity, resolveShard, routeIdentityResolvers, sentrySink, toAirbyteMessages, toErrorResponse, toFivetranResponse, webhookSink, withFrameworkWorker };
|
|
2622
|
+
export { type AdminTableResolver, type AirbyteMessage, type AnalyticsEngineDataPointLike, type AnalyticsEngineDatasetLike, type AnalyticsEngineSinkOptions, type AuthAdmin, type AuthCapabilities, type AuthImpersonation, type AuthIntrospector, type AuthPage, type AuthSession, type AuthUser, type BackupManifest, type BackupStore, type ComposeIdentityResolversErrorMode, type ComposeIdentityResolversOptions, type ConnectorChange, type ConnectorSyncPage, type CorsOptions, type CronHandler, type CronJobDispatch, type CronJobInfo, type CrossShardCounter, type CrossShardReader, type CrossShardRelationCapabilities, type CrossShardRelationOptions, type CsrfOptions, DEFAULT_REGISTRY_CACHE_TTL_MS, type DurableObjectJurisdiction, type DynamicShardRegistry, type DynamicShardRegistryOptions, type ExecutionContextLike, type ExportFanOutRequest, type ExportFanOutResult, type FanOutRequest, type FanOutResult, type FanOutSpec, type FivetranResponse, type FrameworkHostHandler, type FrameworkWorkerOptions, type FrameworkWorkerOptionsInput, type FunctionDescriptor, type FunctionRegistryEntry, type FunctionRegistryLike, type GlobalExportFunction as GlobalExportFn, type GlobalImportFunction as GlobalImportFn, type GlobalIntrospector, type GlobalTableInfo as GlobalTableInfoMeta, type GlobalTablePage as GlobalTablePageMeta, type HttpActionContext, type HttpActionLike, type HttpRouterLike, type IdentityContractLike, type IdentityResolver, type IdentityValidation, type ImportFanOutRequest, type ImportFanOutResult, type KvIntrospector, type KvKeyEntry, type KvKeyListResult, type KvNamespaceSummary, type KvValueResult, type ListAuthUsersOptions, type LogEvent, type LogLevel, LunoraError, type LunoraErrorBody, type LunoraHandlerOptions, type LunoraWorker, type MergeStrategy, type MigrationFanOutRequest, type MigrationFanOutResult, NOOP_EXECUTION_CONTEXT, type ObservabilityEvent, type ObservabilitySink, type ObservabilitySinkContext, type QueryCoordinator, type QueryCoordinatorOptions, type RankFanOutRequest, type RankFanOutResult, type RankPageFanOutRequest, type RankPageFanOutResult, type ResolvedSecurity, type ResolvedShard, type Route, type RpcContext, type RpcEnvelope, SHARD_REGISTRY_DO_NAME, type ScheduledControllerLike, type SecurityHeadersOptions, type SecurityOptions, type SentrySinkOptions, type ShardError, type ShardExportOutcome, type ShardImportOutcome, type ShardMigrationOutcome, type ShardNamespaceLike, type ShardRankOutcome, type ShardRankPageOutcome, type ShardRegistry, type ShardTrafficEntry, type ShardTrafficFanOutRequest, type ShardTrafficFanOutResult, type ShardingInfo, type StorageListFunction as StorageListFn, type StorageObject, VERSION, type VectorIndexSummary, type VectorIntrospector, type VectorQueryMatch, type WebhookSinkOptions, type WorkerOptions, analyticsEngineSink, applyJurisdiction, combineSinks, composeIdentityResolvers, composeWorker, consoleSink, createCrossShardRelationCapabilities, createDynamicShardRegistry, createLunoraHandler, createQueryCoordinator, createStaticShardRegistry, createWorker, decorateResponse, defineRpcEnvelope, emitLogEvent, emitRpcEvent, enforceOrigin, handleCorsPreflight, mergeStrategyForAggregate, resolveLunoraOptions, resolveSecurity, resolveShard, routeIdentityResolvers, sentrySink, toAirbyteMessages, toErrorResponse, toFivetranResponse, webhookSink, withFrameworkWorker };
|
package/dist/index.d.ts
CHANGED
|
@@ -446,6 +446,72 @@ interface IdentityContractLike {
|
|
|
446
446
|
* the wrapped resolver; the admin path keeps the raw one (admin is gated by the
|
|
447
447
|
* bearer / Access, not the app's identity contract).
|
|
448
448
|
*/
|
|
449
|
+
/** One KV namespace as the studio's KV browser surfaces it. */
|
|
450
|
+
interface KvNamespaceSummary {
|
|
451
|
+
/** The wrangler/env binding name, e.g. `"MY_KV"`. */
|
|
452
|
+
binding: string;
|
|
453
|
+
}
|
|
454
|
+
/** One key entry as the KV admin browser surfaces it. */
|
|
455
|
+
interface KvKeyEntry {
|
|
456
|
+
/** Absolute expiration (Unix seconds), when set. */
|
|
457
|
+
expiration?: number;
|
|
458
|
+
/** Per-key metadata set at write time, or absent when none. */
|
|
459
|
+
metadata?: unknown;
|
|
460
|
+
/** The key name. */
|
|
461
|
+
name: string;
|
|
462
|
+
}
|
|
463
|
+
/** A paginated page of KV keys as the admin browser returns it. */
|
|
464
|
+
interface KvKeyListResult {
|
|
465
|
+
/** Opaque cursor for the next page; absent when the listing is complete. */
|
|
466
|
+
cursor?: string;
|
|
467
|
+
/** The keys on this page. */
|
|
468
|
+
keys: KvKeyEntry[];
|
|
469
|
+
/** True when this is the final page. */
|
|
470
|
+
listComplete: boolean;
|
|
471
|
+
}
|
|
472
|
+
/** A KV value together with its stored metadata. */
|
|
473
|
+
interface KvValueResult {
|
|
474
|
+
/** Per-key metadata, or `null` when none. */
|
|
475
|
+
metadata: unknown;
|
|
476
|
+
/** The stored value as a string, or `null` when the key is absent. */
|
|
477
|
+
value: null | string;
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* The introspector the worker wires for the studio's KV browser. Build it from
|
|
481
|
+
* the env's bound KV namespaces. Omit it and the `/_lunora/admin/kv/*`
|
|
482
|
+
* endpoints respond `KV_NOT_CONFIGURED`.
|
|
483
|
+
*/
|
|
484
|
+
interface KvIntrospector {
|
|
485
|
+
/** Delete a key from a namespace. No-op when the key is absent. */
|
|
486
|
+
deleteKey: (options: {
|
|
487
|
+
key: string;
|
|
488
|
+
namespace: string;
|
|
489
|
+
}) => Promise<void>;
|
|
490
|
+
/** Read a value (as text) and its metadata from a namespace key. */
|
|
491
|
+
getValue: (options: {
|
|
492
|
+
key: string;
|
|
493
|
+
namespace: string;
|
|
494
|
+
}) => Promise<KvValueResult>;
|
|
495
|
+
/** List keys in a namespace, optionally filtered by prefix and paginated. */
|
|
496
|
+
listKeys: (options: {
|
|
497
|
+
cursor?: string;
|
|
498
|
+
limit?: number;
|
|
499
|
+
namespace: string;
|
|
500
|
+
prefix?: string;
|
|
501
|
+
}) => Promise<KvKeyListResult>;
|
|
502
|
+
/** List the registered KV namespaces (binding names). */
|
|
503
|
+
listNamespaces: () => Promise<KvNamespaceSummary[]>;
|
|
504
|
+
/** Write a value (as text) with optional absolute expiration / relative TTL and metadata. */
|
|
505
|
+
putValue: (options: {
|
|
506
|
+
expiration?: number;
|
|
507
|
+
expirationTtl?: number;
|
|
508
|
+
key: string;
|
|
509
|
+
metadata?: unknown;
|
|
510
|
+
namespace: string;
|
|
511
|
+
value: string;
|
|
512
|
+
}) => Promise<void>;
|
|
513
|
+
}
|
|
514
|
+
/** The worker internals the KV routes reach through injection rather than closure. */
|
|
449
515
|
/**
|
|
450
516
|
* Observability hooks for the Lunora runtime.
|
|
451
517
|
*
|
|
@@ -1742,15 +1808,19 @@ interface WorkerOptions {
|
|
|
1742
1808
|
/**
|
|
1743
1809
|
* Opt into an authorization-open posture for sharded and fan-out access.
|
|
1744
1810
|
*
|
|
1745
|
-
* By default (this flag unset/`false`) the runtime FAILS CLOSED
|
|
1746
|
-
*
|
|
1747
|
-
*
|
|
1748
|
-
*
|
|
1749
|
-
* (`
|
|
1750
|
-
*
|
|
1751
|
-
*
|
|
1752
|
-
*
|
|
1753
|
-
*
|
|
1811
|
+
* By default (this flag unset/`false`) the runtime FAILS CLOSED per
|
|
1812
|
+
* operation: naming a non-default shard (a potential cross-tenant hop) is
|
|
1813
|
+
* rejected with a `403` (`FORBIDDEN_SHARD`) unless
|
|
1814
|
+
* {@link WorkerOptions.authorizeShard} is configured, and a fan-out
|
|
1815
|
+
* envelope is rejected (`FORBIDDEN_FANOUT`) unless
|
|
1816
|
+
* {@link WorkerOptions.authorizeFanOut} is. Set this to `true` to allow
|
|
1817
|
+
* such requests from any caller (including unauthenticated ones) —
|
|
1818
|
+
* appropriate only when every table is protected by per-row RLS. The
|
|
1819
|
+
* runtime then emits a single `console.warn` so the open posture stays
|
|
1820
|
+
* visible in logs. The flag is consulted per operation: it has no effect
|
|
1821
|
+
* on an operation whose own `authorize*` callback is configured (that
|
|
1822
|
+
* callback gates directly), but configuring only one of the two callbacks
|
|
1823
|
+
* does NOT cover the other operation.
|
|
1754
1824
|
*
|
|
1755
1825
|
* NOTE: this is a behaviour change from earlier alphas, where the same
|
|
1756
1826
|
* situation was warn-once-then-allow. Apps that relied on client-chosen
|
|
@@ -1958,6 +2028,14 @@ interface WorkerOptions {
|
|
|
1958
2028
|
*/
|
|
1959
2029
|
jurisdiction?: DurableObjectJurisdiction;
|
|
1960
2030
|
/**
|
|
2031
|
+
* Introspector for Workers KV namespaces, backing the studio's KV browser
|
|
2032
|
+
* via `GET /_lunora/admin/kv/namespaces`, `GET /_lunora/admin/kv/keys`,
|
|
2033
|
+
* `GET|PUT|DELETE /_lunora/admin/kv/value`. Build it from the env's bound
|
|
2034
|
+
* KV namespaces with `createKvIntrospector` from `@lunora/bindings/kv`.
|
|
2035
|
+
* Omit it and those endpoints respond `KV_NOT_CONFIGURED`.
|
|
2036
|
+
*/
|
|
2037
|
+
kvIntrospector?: KvIntrospector;
|
|
2038
|
+
/**
|
|
1961
2039
|
* Optional telemetry sink. When supplied, the worker emits one
|
|
1962
2040
|
* `onRpc` event per dispatched RPC (single-shard forward or fan-out)
|
|
1963
2041
|
* with duration / ok / error / shardKey or fanOut metadata. Sink
|
|
@@ -2541,4 +2619,4 @@ declare const analyticsEngineSink: (options: AnalyticsEngineSinkOptions) => Obse
|
|
|
2541
2619
|
*/
|
|
2542
2620
|
declare const combineSinks: (...sinks: ObservabilitySink[]) => ObservabilitySink;
|
|
2543
2621
|
declare const VERSION: string;
|
|
2544
|
-
export { type AdminTableResolver, type AirbyteMessage, type AnalyticsEngineDataPointLike, type AnalyticsEngineDatasetLike, type AnalyticsEngineSinkOptions, type AuthAdmin, type AuthCapabilities, type AuthImpersonation, type AuthIntrospector, type AuthPage, type AuthSession, type AuthUser, type BackupManifest, type BackupStore, type ComposeIdentityResolversErrorMode, type ComposeIdentityResolversOptions, type ConnectorChange, type ConnectorSyncPage, type CorsOptions, type CronHandler, type CronJobDispatch, type CronJobInfo, type CrossShardCounter, type CrossShardReader, type CrossShardRelationCapabilities, type CrossShardRelationOptions, type CsrfOptions, DEFAULT_REGISTRY_CACHE_TTL_MS, type DurableObjectJurisdiction, type DynamicShardRegistry, type DynamicShardRegistryOptions, type ExecutionContextLike, type ExportFanOutRequest, type ExportFanOutResult, type FanOutRequest, type FanOutResult, type FanOutSpec, type FivetranResponse, type FrameworkHostHandler, type FrameworkWorkerOptions, type FrameworkWorkerOptionsInput, type FunctionDescriptor, type FunctionRegistryEntry, type FunctionRegistryLike, type GlobalExportFunction as GlobalExportFn, type GlobalImportFunction as GlobalImportFn, type GlobalIntrospector, type GlobalTableInfo as GlobalTableInfoMeta, type GlobalTablePage as GlobalTablePageMeta, type HttpActionContext, type HttpActionLike, type HttpRouterLike, type IdentityContractLike, type IdentityResolver, type IdentityValidation, type ImportFanOutRequest, type ImportFanOutResult, type ListAuthUsersOptions, type LogEvent, type LogLevel, LunoraError, type LunoraErrorBody, type LunoraHandlerOptions, type LunoraWorker, type MergeStrategy, type MigrationFanOutRequest, type MigrationFanOutResult, NOOP_EXECUTION_CONTEXT, type ObservabilityEvent, type ObservabilitySink, type ObservabilitySinkContext, type QueryCoordinator, type QueryCoordinatorOptions, type RankFanOutRequest, type RankFanOutResult, type RankPageFanOutRequest, type RankPageFanOutResult, type ResolvedSecurity, type ResolvedShard, type Route, type RpcContext, type RpcEnvelope, SHARD_REGISTRY_DO_NAME, type ScheduledControllerLike, type SecurityHeadersOptions, type SecurityOptions, type SentrySinkOptions, type ShardError, type ShardExportOutcome, type ShardImportOutcome, type ShardMigrationOutcome, type ShardNamespaceLike, type ShardRankOutcome, type ShardRankPageOutcome, type ShardRegistry, type ShardTrafficEntry, type ShardTrafficFanOutRequest, type ShardTrafficFanOutResult, type ShardingInfo, type StorageListFunction as StorageListFn, type StorageObject, VERSION, type VectorIndexSummary, type VectorIntrospector, type VectorQueryMatch, type WebhookSinkOptions, type WorkerOptions, analyticsEngineSink, applyJurisdiction, combineSinks, composeIdentityResolvers, composeWorker, consoleSink, createCrossShardRelationCapabilities, createDynamicShardRegistry, createLunoraHandler, createQueryCoordinator, createStaticShardRegistry, createWorker, decorateResponse, defineRpcEnvelope, emitLogEvent, emitRpcEvent, enforceOrigin, handleCorsPreflight, mergeStrategyForAggregate, resolveLunoraOptions, resolveSecurity, resolveShard, routeIdentityResolvers, sentrySink, toAirbyteMessages, toErrorResponse, toFivetranResponse, webhookSink, withFrameworkWorker };
|
|
2622
|
+
export { type AdminTableResolver, type AirbyteMessage, type AnalyticsEngineDataPointLike, type AnalyticsEngineDatasetLike, type AnalyticsEngineSinkOptions, type AuthAdmin, type AuthCapabilities, type AuthImpersonation, type AuthIntrospector, type AuthPage, type AuthSession, type AuthUser, type BackupManifest, type BackupStore, type ComposeIdentityResolversErrorMode, type ComposeIdentityResolversOptions, type ConnectorChange, type ConnectorSyncPage, type CorsOptions, type CronHandler, type CronJobDispatch, type CronJobInfo, type CrossShardCounter, type CrossShardReader, type CrossShardRelationCapabilities, type CrossShardRelationOptions, type CsrfOptions, DEFAULT_REGISTRY_CACHE_TTL_MS, type DurableObjectJurisdiction, type DynamicShardRegistry, type DynamicShardRegistryOptions, type ExecutionContextLike, type ExportFanOutRequest, type ExportFanOutResult, type FanOutRequest, type FanOutResult, type FanOutSpec, type FivetranResponse, type FrameworkHostHandler, type FrameworkWorkerOptions, type FrameworkWorkerOptionsInput, type FunctionDescriptor, type FunctionRegistryEntry, type FunctionRegistryLike, type GlobalExportFunction as GlobalExportFn, type GlobalImportFunction as GlobalImportFn, type GlobalIntrospector, type GlobalTableInfo as GlobalTableInfoMeta, type GlobalTablePage as GlobalTablePageMeta, type HttpActionContext, type HttpActionLike, type HttpRouterLike, type IdentityContractLike, type IdentityResolver, type IdentityValidation, type ImportFanOutRequest, type ImportFanOutResult, type KvIntrospector, type KvKeyEntry, type KvKeyListResult, type KvNamespaceSummary, type KvValueResult, type ListAuthUsersOptions, type LogEvent, type LogLevel, LunoraError, type LunoraErrorBody, type LunoraHandlerOptions, type LunoraWorker, type MergeStrategy, type MigrationFanOutRequest, type MigrationFanOutResult, NOOP_EXECUTION_CONTEXT, type ObservabilityEvent, type ObservabilitySink, type ObservabilitySinkContext, type QueryCoordinator, type QueryCoordinatorOptions, type RankFanOutRequest, type RankFanOutResult, type RankPageFanOutRequest, type RankPageFanOutResult, type ResolvedSecurity, type ResolvedShard, type Route, type RpcContext, type RpcEnvelope, SHARD_REGISTRY_DO_NAME, type ScheduledControllerLike, type SecurityHeadersOptions, type SecurityOptions, type SentrySinkOptions, type ShardError, type ShardExportOutcome, type ShardImportOutcome, type ShardMigrationOutcome, type ShardNamespaceLike, type ShardRankOutcome, type ShardRankPageOutcome, type ShardRegistry, type ShardTrafficEntry, type ShardTrafficFanOutRequest, type ShardTrafficFanOutResult, type ShardingInfo, type StorageListFunction as StorageListFn, type StorageObject, VERSION, type VectorIndexSummary, type VectorIntrospector, type VectorQueryMatch, type WebhookSinkOptions, type WorkerOptions, analyticsEngineSink, applyJurisdiction, combineSinks, composeIdentityResolvers, composeWorker, consoleSink, createCrossShardRelationCapabilities, createDynamicShardRegistry, createLunoraHandler, createQueryCoordinator, createStaticShardRegistry, createWorker, decorateResponse, defineRpcEnvelope, emitLogEvent, emitRpcEvent, enforceOrigin, handleCorsPreflight, mergeStrategyForAggregate, resolveLunoraOptions, resolveSecurity, resolveShard, routeIdentityResolvers, sentrySink, toAirbyteMessages, toErrorResponse, toFivetranResponse, webhookSink, withFrameworkWorker };
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { toAirbyteMessages, toFivetranResponse } from './packem_shared/toAirbyteMessages-DrHdplb4.mjs';
|
|
2
|
-
export { composeWorker, createLunoraHandler, createWorker, defineRpcEnvelope, resolveLunoraOptions, withFrameworkWorker } from './packem_shared/composeWorker-
|
|
2
|
+
export { composeWorker, createLunoraHandler, createWorker, defineRpcEnvelope, resolveLunoraOptions, withFrameworkWorker } from './packem_shared/composeWorker-BnZf6iRH.mjs';
|
|
3
3
|
export { createCrossShardRelationCapabilities } from './packem_shared/createCrossShardRelationCapabilities-C0KOf7er.mjs';
|
|
4
4
|
export { DEFAULT_REGISTRY_CACHE_TTL_MS, SHARD_REGISTRY_DO_NAME, createDynamicShardRegistry } from './packem_shared/DEFAULT_REGISTRY_CACHE_TTL_MS-ocax8v0n.mjs';
|
|
5
5
|
export { LunoraError, toErrorResponse } from './packem_shared/LunoraError-CL0aOtpo.mjs';
|
|
@@ -7,7 +7,7 @@ export { emitLogEvent, emitRpcEvent } from './packem_shared/emitLogEvent-pEdtqAK
|
|
|
7
7
|
export { analyticsEngineSink, combineSinks, consoleSink, sentrySink, webhookSink } from './packem_shared/analyticsEngineSink-DqEvrQs0.mjs';
|
|
8
8
|
export { createQueryCoordinator, createStaticShardRegistry, mergeStrategyForAggregate } from './packem_shared/createQueryCoordinator-ZeZYUPNu.mjs';
|
|
9
9
|
export { applyJurisdiction, resolveShard } from './packem_shared/applyJurisdiction-BkZtTkct.mjs';
|
|
10
|
-
export { decorateResponse, enforceOrigin, handleCorsPreflight, resolveSecurity } from './packem_shared/decorateResponse-
|
|
10
|
+
export { decorateResponse, enforceOrigin, handleCorsPreflight, resolveSecurity } from './packem_shared/decorateResponse-igd8FJqk.mjs';
|
|
11
11
|
export { NOOP_EXECUTION_CONTEXT } from './packem_shared/NOOP_EXECUTION_CONTEXT-CCTu0Bf1.mjs';
|
|
12
12
|
export { composeIdentityResolvers, routeIdentityResolvers } from './packem_shared/composeIdentityResolvers-YjvUKisc.mjs';
|
|
13
13
|
|
|
@@ -4,7 +4,7 @@ import { wrapResolverWithContract } from './composeIdentityResolvers-YjvUKisc.mj
|
|
|
4
4
|
export { composeIdentityResolvers, routeIdentityResolvers } from './composeIdentityResolvers-YjvUKisc.mjs';
|
|
5
5
|
import { emitRpcEvent } from './emitLogEvent-pEdtqAK8.mjs';
|
|
6
6
|
import { resolveShard, applyJurisdiction } from './applyJurisdiction-BkZtTkct.mjs';
|
|
7
|
-
import { resolveSecurity, handleCorsPreflight, enforceOrigin, decorateResponse, enforceWebSocketOrigin } from './decorateResponse-
|
|
7
|
+
import { resolveSecurity, handleCorsPreflight, enforceOrigin, decorateResponse, enforceWebSocketOrigin } from './decorateResponse-igd8FJqk.mjs';
|
|
8
8
|
|
|
9
9
|
const RELAY_NAME_INFIX = "::relay::";
|
|
10
10
|
const relayName = (ownerKey, index) => `${ownerKey}${RELAY_NAME_INFIX}${String(index)}`;
|
|
@@ -251,7 +251,7 @@ const buildAuthAdminRoutes = (deps) => {
|
|
|
251
251
|
const candidate = error;
|
|
252
252
|
const code = typeof candidate.code === "string" ? candidate.code : "AUTH_ADMIN_ERROR";
|
|
253
253
|
console.error("[lunora] auth admin operation failed:", error);
|
|
254
|
-
throw new LunoraError("auth admin operation failed", { code, status: AUTH_ADMIN_ERROR_STATUS[code] ??
|
|
254
|
+
throw new LunoraError("auth admin operation failed", { code, status: AUTH_ADMIN_ERROR_STATUS[code] ?? 500 });
|
|
255
255
|
}
|
|
256
256
|
};
|
|
257
257
|
const handle = async (request, descriptor) => {
|
|
@@ -380,9 +380,9 @@ const readBodyBytesWithLimit = async (request, limit = MAX_BODY_BYTES) => {
|
|
|
380
380
|
}
|
|
381
381
|
return out.buffer;
|
|
382
382
|
};
|
|
383
|
-
const readJsonBodyWithLimit = async (request) => {
|
|
383
|
+
const readJsonBodyWithLimit = async (request, limit = MAX_BODY_BYTES) => {
|
|
384
384
|
try {
|
|
385
|
-
const text = await readBodyTextWithLimit(request);
|
|
385
|
+
const text = await readBodyTextWithLimit(request, limit);
|
|
386
386
|
return text === "" ? {} : JSON.parse(text);
|
|
387
387
|
} catch (error) {
|
|
388
388
|
if (error instanceof LunoraError) {
|
|
@@ -1011,6 +1011,128 @@ const buildIntrospectionAdminRoutes = (deps) => {
|
|
|
1011
1011
|
};
|
|
1012
1012
|
};
|
|
1013
1013
|
|
|
1014
|
+
const KV_NAMESPACES_PATH = "/_lunora/admin/kv/namespaces";
|
|
1015
|
+
const KV_KEYS_PATH = "/_lunora/admin/kv/keys";
|
|
1016
|
+
const KV_VALUE_PATH = "/_lunora/admin/kv/value";
|
|
1017
|
+
const KV_VALUE_MAX_BODY_BYTES = 32 * 1048576;
|
|
1018
|
+
const KV_MIN_EXPIRATION_SECONDS = 60;
|
|
1019
|
+
const buildKvAdminRoutes = (deps) => {
|
|
1020
|
+
const { readJsonBody, requireAdminOption } = deps;
|
|
1021
|
+
const gate = (request) => requireAdminOption(request, deps.kvIntrospector, {
|
|
1022
|
+
code: "KV_NOT_CONFIGURED",
|
|
1023
|
+
message: "KV endpoints require a `kvIntrospector` on the worker"
|
|
1024
|
+
});
|
|
1025
|
+
const ok = (payload) => Response.json(payload, { headers: { "content-type": "application/json" }, status: 200 });
|
|
1026
|
+
const requireNamespaceAndKey = (request, verb) => {
|
|
1027
|
+
const url = new URL(request.url);
|
|
1028
|
+
const namespace = url.searchParams.get("namespace") ?? "";
|
|
1029
|
+
const key = url.searchParams.get("key") ?? "";
|
|
1030
|
+
if (namespace === "") {
|
|
1031
|
+
throw new LunoraError(`KV-value ${verb} request requires a \`namespace\` query parameter`, { code: "BAD_REQUEST", status: 400 });
|
|
1032
|
+
}
|
|
1033
|
+
if (key === "") {
|
|
1034
|
+
throw new LunoraError(`KV-value ${verb} request requires a \`key\` query parameter`, { code: "BAD_REQUEST", status: 400 });
|
|
1035
|
+
}
|
|
1036
|
+
return { key, namespace };
|
|
1037
|
+
};
|
|
1038
|
+
const requireKnownNamespace = async (introspector, namespace) => {
|
|
1039
|
+
const namespaces = await introspector.listNamespaces();
|
|
1040
|
+
if (!namespaces.some((entry) => entry.binding === namespace)) {
|
|
1041
|
+
throw new LunoraError(`Unknown KV namespace binding \`${namespace}\``, { code: "NOT_FOUND", status: 404 });
|
|
1042
|
+
}
|
|
1043
|
+
};
|
|
1044
|
+
const handleKvNamespaces = async (request) => {
|
|
1045
|
+
if (request.method !== "GET") {
|
|
1046
|
+
throw new LunoraError("KV-namespaces endpoint requires GET", { code: "METHOD_NOT_ALLOWED", status: 405 });
|
|
1047
|
+
}
|
|
1048
|
+
return ok({ namespaces: await gate(request).listNamespaces() });
|
|
1049
|
+
};
|
|
1050
|
+
const handleKvKeys = async (request) => {
|
|
1051
|
+
if (request.method !== "GET") {
|
|
1052
|
+
throw new LunoraError("KV-keys endpoint requires GET", { code: "METHOD_NOT_ALLOWED", status: 405 });
|
|
1053
|
+
}
|
|
1054
|
+
const introspector = gate(request);
|
|
1055
|
+
const url = new URL(request.url);
|
|
1056
|
+
const namespace = url.searchParams.get("namespace") ?? "";
|
|
1057
|
+
if (namespace === "") {
|
|
1058
|
+
throw new LunoraError("KV-keys request requires a `namespace` query parameter", { code: "BAD_REQUEST", status: 400 });
|
|
1059
|
+
}
|
|
1060
|
+
const prefix = url.searchParams.get("prefix") ?? void 0;
|
|
1061
|
+
const cursor = url.searchParams.get("cursor") ?? void 0;
|
|
1062
|
+
const limitRaw = url.searchParams.get("limit");
|
|
1063
|
+
const parsedLimit = limitRaw === null ? void 0 : Number.parseInt(limitRaw, 10);
|
|
1064
|
+
if (parsedLimit !== void 0 && (!Number.isInteger(parsedLimit) || parsedLimit < 1)) {
|
|
1065
|
+
throw new LunoraError("KV-keys `limit` must be a positive integer", { code: "BAD_REQUEST", status: 400 });
|
|
1066
|
+
}
|
|
1067
|
+
const limit = parsedLimit === void 0 ? void 0 : Math.min(parsedLimit, 1e3);
|
|
1068
|
+
await requireKnownNamespace(introspector, namespace);
|
|
1069
|
+
return ok(await introspector.listKeys({ cursor, limit, namespace, prefix }));
|
|
1070
|
+
};
|
|
1071
|
+
const handleKvValueGet = async (request) => {
|
|
1072
|
+
const introspector = gate(request);
|
|
1073
|
+
const params = requireNamespaceAndKey(request, "GET");
|
|
1074
|
+
await requireKnownNamespace(introspector, params.namespace);
|
|
1075
|
+
return ok(await introspector.getValue(params));
|
|
1076
|
+
};
|
|
1077
|
+
const handleKvValuePut = async (request) => {
|
|
1078
|
+
const introspector = gate(request);
|
|
1079
|
+
const candidate = await readJsonBody(request, KV_VALUE_MAX_BODY_BYTES);
|
|
1080
|
+
if (typeof candidate.namespace !== "string" || candidate.namespace === "") {
|
|
1081
|
+
throw new LunoraError("KV-value PUT request requires a `namespace` string", { code: "BAD_REQUEST", status: 400 });
|
|
1082
|
+
}
|
|
1083
|
+
if (typeof candidate.key !== "string" || candidate.key === "") {
|
|
1084
|
+
throw new LunoraError("KV-value PUT request requires a `key` string", { code: "BAD_REQUEST", status: 400 });
|
|
1085
|
+
}
|
|
1086
|
+
if (typeof candidate.value !== "string") {
|
|
1087
|
+
throw new LunoraError("KV-value PUT request requires a `value` string", { code: "BAD_REQUEST", status: 400 });
|
|
1088
|
+
}
|
|
1089
|
+
if (candidate.expirationTtl !== void 0 && (typeof candidate.expirationTtl !== "number" || !Number.isInteger(candidate.expirationTtl) || candidate.expirationTtl < KV_MIN_EXPIRATION_SECONDS)) {
|
|
1090
|
+
throw new LunoraError("KV-value PUT `expirationTtl` must be an integer ≥ 60", { code: "BAD_REQUEST", status: 400 });
|
|
1091
|
+
}
|
|
1092
|
+
const minExpiration = Math.floor(Date.now() / 1e3) + KV_MIN_EXPIRATION_SECONDS;
|
|
1093
|
+
if (candidate.expiration !== void 0 && (typeof candidate.expiration !== "number" || !Number.isInteger(candidate.expiration) || candidate.expiration < minExpiration)) {
|
|
1094
|
+
throw new LunoraError("KV-value PUT `expiration` must be a Unix-seconds timestamp at least 60 seconds in the future", {
|
|
1095
|
+
code: "BAD_REQUEST",
|
|
1096
|
+
status: 400
|
|
1097
|
+
});
|
|
1098
|
+
}
|
|
1099
|
+
await requireKnownNamespace(introspector, candidate.namespace);
|
|
1100
|
+
await introspector.putValue({
|
|
1101
|
+
expiration: candidate.expiration,
|
|
1102
|
+
expirationTtl: candidate.expirationTtl,
|
|
1103
|
+
key: candidate.key,
|
|
1104
|
+
metadata: candidate.metadata,
|
|
1105
|
+
namespace: candidate.namespace,
|
|
1106
|
+
value: candidate.value
|
|
1107
|
+
});
|
|
1108
|
+
return ok({ ok: true });
|
|
1109
|
+
};
|
|
1110
|
+
const handleKvValueDelete = async (request) => {
|
|
1111
|
+
const introspector = gate(request);
|
|
1112
|
+
const params = requireNamespaceAndKey(request, "DELETE");
|
|
1113
|
+
await requireKnownNamespace(introspector, params.namespace);
|
|
1114
|
+
await introspector.deleteKey(params);
|
|
1115
|
+
return ok({ deleted: true });
|
|
1116
|
+
};
|
|
1117
|
+
const kvValueHandlers = {
|
|
1118
|
+
DELETE: handleKvValueDelete,
|
|
1119
|
+
GET: handleKvValueGet,
|
|
1120
|
+
PUT: handleKvValuePut
|
|
1121
|
+
};
|
|
1122
|
+
const handleKvValue = (request) => {
|
|
1123
|
+
const handler = kvValueHandlers[request.method];
|
|
1124
|
+
if (!handler) {
|
|
1125
|
+
throw new LunoraError("KV-value endpoint requires GET, PUT, or DELETE", { code: "METHOD_NOT_ALLOWED", status: 405 });
|
|
1126
|
+
}
|
|
1127
|
+
return handler(request);
|
|
1128
|
+
};
|
|
1129
|
+
return {
|
|
1130
|
+
[KV_NAMESPACES_PATH]: handleKvNamespaces,
|
|
1131
|
+
[KV_KEYS_PATH]: handleKvKeys,
|
|
1132
|
+
[KV_VALUE_PATH]: handleKvValue
|
|
1133
|
+
};
|
|
1134
|
+
};
|
|
1135
|
+
|
|
1014
1136
|
const MIGRATE_PATH$1 = "/_lunora/migrate";
|
|
1015
1137
|
const PITR_PATH = "/_lunora/admin/pitr";
|
|
1016
1138
|
const RANK_PATH = "/_lunora/admin/rank";
|
|
@@ -2113,6 +2235,11 @@ const createWorker = (options) => {
|
|
|
2113
2235
|
requireAdminOption,
|
|
2114
2236
|
vectorIntrospector: options.vectorIntrospector
|
|
2115
2237
|
});
|
|
2238
|
+
const kvAdminRoutes = buildKvAdminRoutes({
|
|
2239
|
+
kvIntrospector: options.kvIntrospector,
|
|
2240
|
+
readJsonBody: readJsonBodyWithLimit,
|
|
2241
|
+
requireAdminOption
|
|
2242
|
+
});
|
|
2116
2243
|
const introspectionAdminRoutes = buildIntrospectionAdminRoutes({
|
|
2117
2244
|
assertAdmin: assertAdminAuthorized,
|
|
2118
2245
|
options: {
|
|
@@ -2656,6 +2783,7 @@ const createWorker = (options) => {
|
|
|
2656
2783
|
...workflowsAdminRoutes,
|
|
2657
2784
|
...storageAdminRoutes,
|
|
2658
2785
|
...vectorAdminRoutes,
|
|
2786
|
+
...kvAdminRoutes,
|
|
2659
2787
|
...introspectionAdminRoutes,
|
|
2660
2788
|
// `/_lunora/admin/auth/*` — the whole user-management plane, one route per
|
|
2661
2789
|
// `AuthAdmin` op, dispatched by the descriptor table in `./auth-admin-routes`.
|
|
@@ -75,11 +75,10 @@ const resolveCors = (input) => {
|
|
|
75
75
|
if (typeof origins === "function") {
|
|
76
76
|
isAllowed = origins;
|
|
77
77
|
isExplicitlyAllowed = origins;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
78
|
+
const credentialsNote = allowCredentials ? " AND reflects matching origins with credentials (`allowCredentials: true`)" : "";
|
|
79
|
+
console.warn(
|
|
80
|
+
`@lunora/runtime: security.cors uses a custom \`allowedOrigins\` predicate. It is trusted by the CSRF and WebSocket origin checks${credentialsNote} — ensure it matches ONLY trusted origins by exact equality; an over-broad predicate (e.g. \`() => true\`, or \`endsWith\`/\`includes\` checks) defeats the allowlist.`
|
|
81
|
+
);
|
|
83
82
|
} else {
|
|
84
83
|
const originsList = origins;
|
|
85
84
|
if (originsList.includes("*") && allowCredentials) {
|