@lunora/do 1.0.0-alpha.30 → 1.0.0-alpha.31
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 +28 -6
- package/dist/index.d.ts +28 -6
- package/dist/index.mjs +9 -8
- package/dist/packem_shared/{MAX_SQL_ROWS-D57CJaT9.mjs → MAX_SQL_ROWS-iFAA8FbD.mjs} +32 -2
- package/dist/packem_shared/{ROOT_DO_SIZE_WARN_BYTES-BA8QOChj.mjs → ROOT_DO_SIZE_WARN_BYTES-BWz51mpB.mjs} +152 -28
- package/dist/packem_shared/{ReactiveCache-BYlSGY0N.mjs → ReactiveCache-DnSvbjil.mjs} +4 -3
- package/dist/packem_shared/{diffExternalSource-Cx9HUPJj.mjs → diffExternalSource-CovHfdyo.mjs} +1 -1
- package/dist/packem_shared/{isSourceDue-CYkt7Ru8.mjs → isSourceDue-Bj7I3v1b.mjs} +1 -1
- package/dist/packem_shared/{materializeExternalRows-CTqZisSC.mjs → materializeExternalRows-CoGmFmsY.mjs} +2 -2
- package/dist/packem_shared/{stableStringify-MydiuScU.mjs → stableStringify-mC40mZts.mjs} +2 -2
- package/dist/packem_shared/stableWireKey-DKuXO7T5.mjs +6 -0
- package/dist/packem_shared/subscriptionListDeltas-CT76bYny.mjs +126 -0
- package/dist/packem_shared/{subscription-delivery-CWigSEr3.mjs → wire-codec-CzQc1pvf.mjs} +1 -124
- package/package.json +3 -3
- package/dist/packem_shared/subscriptionListDeltas-DRLvFlM1.mjs +0 -1
package/dist/index.d.mts
CHANGED
|
@@ -614,6 +614,13 @@ declare const rankTableName: (table: string, indexName: string) => string;
|
|
|
614
614
|
* - `rowId` === `doc._id`, the `__id__` tiebreak.
|
|
615
615
|
*/
|
|
616
616
|
declare const stableStringify: (value: unknown) => string;
|
|
617
|
+
/**
|
|
618
|
+
* Stable cache/dedup key for a (possibly wire-typed) `value`: the sorted-key
|
|
619
|
+
* stable encoding of its wire form. Byte-identical to `stableStringify(value)`
|
|
620
|
+
* for pure-JSON values; deterministic tagged tokens for `bigint`/`Date`/`Map`/
|
|
621
|
+
* `Set`/`URL`/bytes; throws a `TypeError` on values the wire refuses.
|
|
622
|
+
*/
|
|
623
|
+
declare const stableWireKey: (value: unknown) => string;
|
|
617
624
|
/** A single memoized result, the deps it read, and any active subscribers. */
|
|
618
625
|
interface CacheEntry {
|
|
619
626
|
/** Approximate serialized size of `result`, charged against `maxBytes`. */
|
|
@@ -6431,7 +6438,12 @@ declare abstract class ShardDO {
|
|
|
6431
6438
|
* server logs, browser history, and `Referer` headers on any
|
|
6432
6439
|
* subresource the upgrade page loads after the handshake. Use a
|
|
6433
6440
|
* short-lived rotating token in production rather than a long-lived
|
|
6434
|
-
* secret
|
|
6441
|
+
* secret — for the ADMIN credential specifically, the worker mints one
|
|
6442
|
+
* (`POST /_lunora/admin/ws-token`) and {@link isAdminSocket} accepts it, so
|
|
6443
|
+
* the master `LUNORA_ADMIN_TOKEN` never rides the URL.
|
|
6444
|
+
*
|
|
6445
|
+
* Async because the admin fallback ({@link isAdminSocket}) verifies the
|
|
6446
|
+
* ephemeral sub-token with WebCrypto HMAC.
|
|
6435
6447
|
*/
|
|
6436
6448
|
private isUpgradeAllowed;
|
|
6437
6449
|
/**
|
|
@@ -6442,10 +6454,20 @@ declare abstract class ShardDO {
|
|
|
6442
6454
|
*/
|
|
6443
6455
|
private suppliedWsToken;
|
|
6444
6456
|
/**
|
|
6445
|
-
* Whether the upgrade presented
|
|
6446
|
-
* constant-time compared
|
|
6447
|
-
*
|
|
6448
|
-
*
|
|
6457
|
+
* Whether the upgrade presented an admin credential: the master
|
|
6458
|
+
* `LUNORA_ADMIN_TOKEN` (constant-time compared) or a short-lived sub-token
|
|
6459
|
+
* the worker minted with it (`POST /_lunora/admin/ws-token` —
|
|
6460
|
+
* HMAC-verified statelessly here, since both isolates hold the master token
|
|
6461
|
+
* in `env`). The ephemeral token is what the studio sends in `?token=`, so
|
|
6462
|
+
* the master credential stays out of URLs/logs. Closed (resolves `false`)
|
|
6463
|
+
* when the admin token is unset, mirroring `isAdminAuthorized` for the HTTP
|
|
6464
|
+
* path so admin streaming is opt-in rather than exposed by default.
|
|
6465
|
+
*
|
|
6466
|
+
* Enforcement: with `LUNORA_REQUIRE_EPHEMERAL_WS_TOKEN` set
|
|
6467
|
+
* (`1`/`true`/`on`/`yes`/`enabled`), a raw master token in the
|
|
6468
|
+
* `?token=` query parameter is rejected — the query string is exactly
|
|
6469
|
+
* where it leaks. The `Authorization` header path still takes the master
|
|
6470
|
+
* token: browsers can't set it on a WS upgrade, so it never rides a URL.
|
|
6449
6471
|
*/
|
|
6450
6472
|
private isAdminSocket;
|
|
6451
6473
|
/**
|
|
@@ -6682,4 +6704,4 @@ interface WhereSqlStrategy {
|
|
|
6682
6704
|
* `undefined` when the input imposes no constraint (empty `where`).
|
|
6683
6705
|
*/
|
|
6684
6706
|
declare const compileWhereSql: (where: WhereInput | undefined, strategy: WhereSqlStrategy) => SQL | undefined;
|
|
6685
|
-
export { ADMIN_FUNCTIONS, ADMIN_FUNCTION_PREFIX, AGGREGATE_SQL_FUNCTION, AUTH_METRICS_BUCKETS_TABLE, AUTH_METRICS_BUCKET_MS, AUTH_METRICS_BUCKET_RETENTION, AUTH_METRICS_TABLE, type AdvisoriesResult, type AdvisoryFinding, type AggregateIndexDefinitionLike, type AggregateOp, type AggregateOptions, type AggregateResult, type AggregateTally, type ApplyOnDeleteOptions, type AuditEntry, type AuditLogResult, type AuthMetrics, type AuthMetricsBucket, type BroadcastDelta, CDC_LOG_TABLE, type CacheEntry, type CapturedMailRow, type CdcChange, type Clock, type ColumnMeta, type ColumnMetaLike, ConflictError, type CountArgs, CountRlsUnsupportedError, type CtxDbOptions, DATA_MIGRATION_STATE_TABLE, DEFAULT_MAX_RELATION_KEYS, type DataMigrationDocument, type DataMigrationLike, type DataMigrationTransform, type DatabaseWriterLike, type DependencyTracker, type DeployInfo, type ExportRow, type ExportShardAdminArgs, type ExportShardArgs, type ExternalSourceDiffResult, type ExternalSourceLike, FLAGS_FUNCTION_PREFIX, FUNCTION_METRICS_BUCKETS_TABLE, FUNCTION_METRICS_BUCKET_MS, FUNCTION_METRICS_BUCKET_RETENTION, FUNCTION_METRICS_INDEX_TABLE, FUNCTION_METRICS_TABLE, type FacetColumnOptions, type FacetColumnResult, type FacetValue, type FieldOperators, type FlagEvaluation, type FlagsResult, type FunctionCallStat, type FunctionMetricBucket, type FunctionMetricIndexHit, type FunctionStatsResult, type GroupByEntry, type GroupByOptions, type HibernatableWebSocket, type IdGenerator, type ImportError, type ImportShardAdminArgs, type ImportShardArgs, type ImportShardResult, type IndexDefinitionLike, type IndexRangeBuilderLike, LogBuffer, type LogEntry, type LogEventInput, type LogLevel, type LogSink, MAIL_RETENTION, MAIL_TABLE, MAX_SQL_ROWS, MIN_ADMIN_TOKEN_LENGTH, MIN_AUTH_SECRET_LENGTH, type MaskColumnMetadata, type MaskPoliciesResult, type MaterializeResult, type MigrationDirection, type MigrationRunResult, type MigrationStatus, type MigrationStatusRow, type MutationDelta, type NestedWith, NotFoundError, NotUniqueError, type OnDeleteActionLike, type OrderByInput, type OrderKey, type PaginationOptions, type PitrBookmarkResult, type PitrRestoreArgs, type PitrRestoreResult, type PitrStorage, type QueryArgs, type QueryPage, type QueueMetadata, type QueuesResult, RANK_TIEBREAK, RELATION_FUNCTION_PREFIX, RLS_UNWRAP_SYMBOL, ROOT_DO_SIZE_WARN_BYTES, ROOT_SHARD_NAME, type RankDirection, type RankIndexDefinitionLike, type RankOptions, type RankPage, type RankPageOptions, type RankPageRow, type RankPageRowKey, type RankResult, type RankSortKeyLike, ReactiveCache, type ReactiveCacheOptions, type ReadHook, type ReadTablePageOptions, type RecordAuthEventInput, type RecordFunctionMetricInput, type RecordMailInput, type RelationDefinitionLike, type RenderedSql, type ResolveRelationPredicatesOptions, type ResolveWithOptions, type RestrictableQueryOptions, type RlsPoliciesResult, type RlsPolicyMetadata, RlsRequiredError, type RlsRoleMetadata, type RpcRequest, type RunDataMigrationOptions, type RunShardApplyCdcArgs, type RunShardApplyCdcResult, type RunShardBulkDeleteArgs, type RunShardBulkDeleteResult, type RunShardExportArgs, type RunShardImportArgs, type RunShardMigrationArgs, type RunShardRankBeforeArgs, type RunShardRankPageArgs, type RunShardWriteArgs, type RunShardWriteResult, type RunTriggersOptions, SCAN_DEP, SESSION_DO_TTL_DEFAULT, SHARD_REGISTRY_DO_NAME, type SchedulableWorkflowReferenceLike, type ScheduledFunctionDoc, type SchedulerLike, type SchemaLike, type SearchFilterBuilderLike, type SecurityAuditResult, type SecurityFinding, type SecurityFindingKind, type SecurityFindingLevel, type SelectMatchingIdsOptions, type ServerDefaultContextLike, SessionDO, type SessionRecord, type SettingEntry, type SettingKind, type SettingsResult, type ShapeSubscriptionQuery, ShardDO, type ShardDOOptions, type ShardDOState, type ShardRankPageResult, ShardRegistryDO, type SocketAttachment, type SortDirection, type SourceClientLike, type SourceRefresh, type SqlConsoleResult, type SqlCursor, type SqlEngine, type SqlExec, type StorageRuleMetadata, type StorageRulesResult, type StudioFeaturesResult, type SubscriptionEnvelope, type SubscriptionOutcome, type SubscriptionQuery, type SystemDatabaseReader, type SystemDoc, type SystemQuery, type SystemReaderOptions, type SystemReaderSchedulerLike, type SystemReaderStorageLike, type SystemTableName, type TableColumnsResult, type TableDefinitionLike, type TableIndexInfo, type TableIndexesResult, type TableInfo, type TablePage, type TableReaderLike, type TablesColumnsResult, type TransactionSqlLike, type TriggerContextLike, type TriggerDefinitionLike, type TriggerEventLike, type TriggerOpLike, type TriggerTimingLike, type ValidatorLike, type WhereInput, type WhereSqlStrategy, type WithInput, type WorkflowMetadata, type WorkflowsResult, type WriteEvent, type WriteHook, aggregateSqlFunction, aggregateTableName, applyCdcChanges, applyOnDelete, applySelect, armRestore, assertFlatPredicate, assertReadonly, assertShapeShardable, assertValidClientId, backfillAggregateIndexes, backfillRankIndexes, buildFtsMatch, buildSecurityAudit, buildSeekWhere, clearCapturedMail, coerceAggregateNumber, compileWhereSql, containsRelationPredicate, createDependencyTracker, createShardCtxDb, createSystemReader, decodeCursor, depKey, diffExternalSource, encodeAggregateKey, encodeCursor, encodePartitionKey, ensureAuthMetricsTables, ensureFunctionMetricsTables, ensureMailTable, exportShardRows, exportShardTable, facetColumn, fanOutScalarCounts, foldAggregateTally, ftsTableName, guardWriter, hasTrigger, importShardRows, isRelationPredicate, isSourceDue, liftSourceId, listTables, matchesRankStaticWhere, matchesStaticWhere, materializeExternalRows, mergeWhere, normalizeCountArgument, normalizeIdStructurally, normalizeOrderKeys, parseExportShardArgs, parseImportShardArgs, planAggregateLookup, pullExternalSourceTick, rankTableName, reactiveCacheKey, readAggregateValue, readAuthMetrics, readBookmark, readCapturedMail, readCdcChanges, readExternalSourceBaseline, readFunctionMetricBuckets, readFunctionMetricIndexHits, readFunctionMetrics, readFunctionMetricsTotals, readMigrationStatus, readTablePage, recordAuthEvent, recordCapturedMail, recordFunctionMetric, renderSql, resolveRankPartition, resolveRelationPredicates, resolveWith, runDataMigration, runExternalSourceTick, runReadonlySql, runRowValidators, runShardMigrations, runTriggers, scoreDocument, selectExportTables, selectIndexForAggregate, selectIndexForCount, selectIndexForGroupBy, selectMatchingIds, serveRelationFanout, softDeleteScope, sortColumnName, stableStringify, stringifySearchText, subscriptionListDeltas, throwingScheduler, tokenizeSearch, trimCdcChanges, validateImportRow };
|
|
6707
|
+
export { ADMIN_FUNCTIONS, ADMIN_FUNCTION_PREFIX, AGGREGATE_SQL_FUNCTION, AUTH_METRICS_BUCKETS_TABLE, AUTH_METRICS_BUCKET_MS, AUTH_METRICS_BUCKET_RETENTION, AUTH_METRICS_TABLE, type AdvisoriesResult, type AdvisoryFinding, type AggregateIndexDefinitionLike, type AggregateOp, type AggregateOptions, type AggregateResult, type AggregateTally, type ApplyOnDeleteOptions, type AuditEntry, type AuditLogResult, type AuthMetrics, type AuthMetricsBucket, type BroadcastDelta, CDC_LOG_TABLE, type CacheEntry, type CapturedMailRow, type CdcChange, type Clock, type ColumnMeta, type ColumnMetaLike, ConflictError, type CountArgs, CountRlsUnsupportedError, type CtxDbOptions, DATA_MIGRATION_STATE_TABLE, DEFAULT_MAX_RELATION_KEYS, type DataMigrationDocument, type DataMigrationLike, type DataMigrationTransform, type DatabaseWriterLike, type DependencyTracker, type DeployInfo, type ExportRow, type ExportShardAdminArgs, type ExportShardArgs, type ExternalSourceDiffResult, type ExternalSourceLike, FLAGS_FUNCTION_PREFIX, FUNCTION_METRICS_BUCKETS_TABLE, FUNCTION_METRICS_BUCKET_MS, FUNCTION_METRICS_BUCKET_RETENTION, FUNCTION_METRICS_INDEX_TABLE, FUNCTION_METRICS_TABLE, type FacetColumnOptions, type FacetColumnResult, type FacetValue, type FieldOperators, type FlagEvaluation, type FlagsResult, type FunctionCallStat, type FunctionMetricBucket, type FunctionMetricIndexHit, type FunctionStatsResult, type GroupByEntry, type GroupByOptions, type HibernatableWebSocket, type IdGenerator, type ImportError, type ImportShardAdminArgs, type ImportShardArgs, type ImportShardResult, type IndexDefinitionLike, type IndexRangeBuilderLike, LogBuffer, type LogEntry, type LogEventInput, type LogLevel, type LogSink, MAIL_RETENTION, MAIL_TABLE, MAX_SQL_ROWS, MIN_ADMIN_TOKEN_LENGTH, MIN_AUTH_SECRET_LENGTH, type MaskColumnMetadata, type MaskPoliciesResult, type MaterializeResult, type MigrationDirection, type MigrationRunResult, type MigrationStatus, type MigrationStatusRow, type MutationDelta, type NestedWith, NotFoundError, NotUniqueError, type OnDeleteActionLike, type OrderByInput, type OrderKey, type PaginationOptions, type PitrBookmarkResult, type PitrRestoreArgs, type PitrRestoreResult, type PitrStorage, type QueryArgs, type QueryPage, type QueueMetadata, type QueuesResult, RANK_TIEBREAK, RELATION_FUNCTION_PREFIX, RLS_UNWRAP_SYMBOL, ROOT_DO_SIZE_WARN_BYTES, ROOT_SHARD_NAME, type RankDirection, type RankIndexDefinitionLike, type RankOptions, type RankPage, type RankPageOptions, type RankPageRow, type RankPageRowKey, type RankResult, type RankSortKeyLike, ReactiveCache, type ReactiveCacheOptions, type ReadHook, type ReadTablePageOptions, type RecordAuthEventInput, type RecordFunctionMetricInput, type RecordMailInput, type RelationDefinitionLike, type RenderedSql, type ResolveRelationPredicatesOptions, type ResolveWithOptions, type RestrictableQueryOptions, type RlsPoliciesResult, type RlsPolicyMetadata, RlsRequiredError, type RlsRoleMetadata, type RpcRequest, type RunDataMigrationOptions, type RunShardApplyCdcArgs, type RunShardApplyCdcResult, type RunShardBulkDeleteArgs, type RunShardBulkDeleteResult, type RunShardExportArgs, type RunShardImportArgs, type RunShardMigrationArgs, type RunShardRankBeforeArgs, type RunShardRankPageArgs, type RunShardWriteArgs, type RunShardWriteResult, type RunTriggersOptions, SCAN_DEP, SESSION_DO_TTL_DEFAULT, SHARD_REGISTRY_DO_NAME, type SchedulableWorkflowReferenceLike, type ScheduledFunctionDoc, type SchedulerLike, type SchemaLike, type SearchFilterBuilderLike, type SecurityAuditResult, type SecurityFinding, type SecurityFindingKind, type SecurityFindingLevel, type SelectMatchingIdsOptions, type ServerDefaultContextLike, SessionDO, type SessionRecord, type SettingEntry, type SettingKind, type SettingsResult, type ShapeSubscriptionQuery, ShardDO, type ShardDOOptions, type ShardDOState, type ShardRankPageResult, ShardRegistryDO, type SocketAttachment, type SortDirection, type SourceClientLike, type SourceRefresh, type SqlConsoleResult, type SqlCursor, type SqlEngine, type SqlExec, type StorageRuleMetadata, type StorageRulesResult, type StudioFeaturesResult, type SubscriptionEnvelope, type SubscriptionOutcome, type SubscriptionQuery, type SystemDatabaseReader, type SystemDoc, type SystemQuery, type SystemReaderOptions, type SystemReaderSchedulerLike, type SystemReaderStorageLike, type SystemTableName, type TableColumnsResult, type TableDefinitionLike, type TableIndexInfo, type TableIndexesResult, type TableInfo, type TablePage, type TableReaderLike, type TablesColumnsResult, type TransactionSqlLike, type TriggerContextLike, type TriggerDefinitionLike, type TriggerEventLike, type TriggerOpLike, type TriggerTimingLike, type ValidatorLike, type WhereInput, type WhereSqlStrategy, type WithInput, type WorkflowMetadata, type WorkflowsResult, type WriteEvent, type WriteHook, aggregateSqlFunction, aggregateTableName, applyCdcChanges, applyOnDelete, applySelect, armRestore, assertFlatPredicate, assertReadonly, assertShapeShardable, assertValidClientId, backfillAggregateIndexes, backfillRankIndexes, buildFtsMatch, buildSecurityAudit, buildSeekWhere, clearCapturedMail, coerceAggregateNumber, compileWhereSql, containsRelationPredicate, createDependencyTracker, createShardCtxDb, createSystemReader, decodeCursor, depKey, diffExternalSource, encodeAggregateKey, encodeCursor, encodePartitionKey, ensureAuthMetricsTables, ensureFunctionMetricsTables, ensureMailTable, exportShardRows, exportShardTable, facetColumn, fanOutScalarCounts, foldAggregateTally, ftsTableName, guardWriter, hasTrigger, importShardRows, isRelationPredicate, isSourceDue, liftSourceId, listTables, matchesRankStaticWhere, matchesStaticWhere, materializeExternalRows, mergeWhere, normalizeCountArgument, normalizeIdStructurally, normalizeOrderKeys, parseExportShardArgs, parseImportShardArgs, planAggregateLookup, pullExternalSourceTick, rankTableName, reactiveCacheKey, readAggregateValue, readAuthMetrics, readBookmark, readCapturedMail, readCdcChanges, readExternalSourceBaseline, readFunctionMetricBuckets, readFunctionMetricIndexHits, readFunctionMetrics, readFunctionMetricsTotals, readMigrationStatus, readTablePage, recordAuthEvent, recordCapturedMail, recordFunctionMetric, renderSql, resolveRankPartition, resolveRelationPredicates, resolveWith, runDataMigration, runExternalSourceTick, runReadonlySql, runRowValidators, runShardMigrations, runTriggers, scoreDocument, selectExportTables, selectIndexForAggregate, selectIndexForCount, selectIndexForGroupBy, selectMatchingIds, serveRelationFanout, softDeleteScope, sortColumnName, stableStringify, stableWireKey, stringifySearchText, subscriptionListDeltas, throwingScheduler, tokenizeSearch, trimCdcChanges, validateImportRow };
|
package/dist/index.d.ts
CHANGED
|
@@ -614,6 +614,13 @@ declare const rankTableName: (table: string, indexName: string) => string;
|
|
|
614
614
|
* - `rowId` === `doc._id`, the `__id__` tiebreak.
|
|
615
615
|
*/
|
|
616
616
|
declare const stableStringify: (value: unknown) => string;
|
|
617
|
+
/**
|
|
618
|
+
* Stable cache/dedup key for a (possibly wire-typed) `value`: the sorted-key
|
|
619
|
+
* stable encoding of its wire form. Byte-identical to `stableStringify(value)`
|
|
620
|
+
* for pure-JSON values; deterministic tagged tokens for `bigint`/`Date`/`Map`/
|
|
621
|
+
* `Set`/`URL`/bytes; throws a `TypeError` on values the wire refuses.
|
|
622
|
+
*/
|
|
623
|
+
declare const stableWireKey: (value: unknown) => string;
|
|
617
624
|
/** A single memoized result, the deps it read, and any active subscribers. */
|
|
618
625
|
interface CacheEntry {
|
|
619
626
|
/** Approximate serialized size of `result`, charged against `maxBytes`. */
|
|
@@ -6431,7 +6438,12 @@ declare abstract class ShardDO {
|
|
|
6431
6438
|
* server logs, browser history, and `Referer` headers on any
|
|
6432
6439
|
* subresource the upgrade page loads after the handshake. Use a
|
|
6433
6440
|
* short-lived rotating token in production rather than a long-lived
|
|
6434
|
-
* secret
|
|
6441
|
+
* secret — for the ADMIN credential specifically, the worker mints one
|
|
6442
|
+
* (`POST /_lunora/admin/ws-token`) and {@link isAdminSocket} accepts it, so
|
|
6443
|
+
* the master `LUNORA_ADMIN_TOKEN` never rides the URL.
|
|
6444
|
+
*
|
|
6445
|
+
* Async because the admin fallback ({@link isAdminSocket}) verifies the
|
|
6446
|
+
* ephemeral sub-token with WebCrypto HMAC.
|
|
6435
6447
|
*/
|
|
6436
6448
|
private isUpgradeAllowed;
|
|
6437
6449
|
/**
|
|
@@ -6442,10 +6454,20 @@ declare abstract class ShardDO {
|
|
|
6442
6454
|
*/
|
|
6443
6455
|
private suppliedWsToken;
|
|
6444
6456
|
/**
|
|
6445
|
-
* Whether the upgrade presented
|
|
6446
|
-
* constant-time compared
|
|
6447
|
-
*
|
|
6448
|
-
*
|
|
6457
|
+
* Whether the upgrade presented an admin credential: the master
|
|
6458
|
+
* `LUNORA_ADMIN_TOKEN` (constant-time compared) or a short-lived sub-token
|
|
6459
|
+
* the worker minted with it (`POST /_lunora/admin/ws-token` —
|
|
6460
|
+
* HMAC-verified statelessly here, since both isolates hold the master token
|
|
6461
|
+
* in `env`). The ephemeral token is what the studio sends in `?token=`, so
|
|
6462
|
+
* the master credential stays out of URLs/logs. Closed (resolves `false`)
|
|
6463
|
+
* when the admin token is unset, mirroring `isAdminAuthorized` for the HTTP
|
|
6464
|
+
* path so admin streaming is opt-in rather than exposed by default.
|
|
6465
|
+
*
|
|
6466
|
+
* Enforcement: with `LUNORA_REQUIRE_EPHEMERAL_WS_TOKEN` set
|
|
6467
|
+
* (`1`/`true`/`on`/`yes`/`enabled`), a raw master token in the
|
|
6468
|
+
* `?token=` query parameter is rejected — the query string is exactly
|
|
6469
|
+
* where it leaks. The `Authorization` header path still takes the master
|
|
6470
|
+
* token: browsers can't set it on a WS upgrade, so it never rides a URL.
|
|
6449
6471
|
*/
|
|
6450
6472
|
private isAdminSocket;
|
|
6451
6473
|
/**
|
|
@@ -6682,4 +6704,4 @@ interface WhereSqlStrategy {
|
|
|
6682
6704
|
* `undefined` when the input imposes no constraint (empty `where`).
|
|
6683
6705
|
*/
|
|
6684
6706
|
declare const compileWhereSql: (where: WhereInput | undefined, strategy: WhereSqlStrategy) => SQL | undefined;
|
|
6685
|
-
export { ADMIN_FUNCTIONS, ADMIN_FUNCTION_PREFIX, AGGREGATE_SQL_FUNCTION, AUTH_METRICS_BUCKETS_TABLE, AUTH_METRICS_BUCKET_MS, AUTH_METRICS_BUCKET_RETENTION, AUTH_METRICS_TABLE, type AdvisoriesResult, type AdvisoryFinding, type AggregateIndexDefinitionLike, type AggregateOp, type AggregateOptions, type AggregateResult, type AggregateTally, type ApplyOnDeleteOptions, type AuditEntry, type AuditLogResult, type AuthMetrics, type AuthMetricsBucket, type BroadcastDelta, CDC_LOG_TABLE, type CacheEntry, type CapturedMailRow, type CdcChange, type Clock, type ColumnMeta, type ColumnMetaLike, ConflictError, type CountArgs, CountRlsUnsupportedError, type CtxDbOptions, DATA_MIGRATION_STATE_TABLE, DEFAULT_MAX_RELATION_KEYS, type DataMigrationDocument, type DataMigrationLike, type DataMigrationTransform, type DatabaseWriterLike, type DependencyTracker, type DeployInfo, type ExportRow, type ExportShardAdminArgs, type ExportShardArgs, type ExternalSourceDiffResult, type ExternalSourceLike, FLAGS_FUNCTION_PREFIX, FUNCTION_METRICS_BUCKETS_TABLE, FUNCTION_METRICS_BUCKET_MS, FUNCTION_METRICS_BUCKET_RETENTION, FUNCTION_METRICS_INDEX_TABLE, FUNCTION_METRICS_TABLE, type FacetColumnOptions, type FacetColumnResult, type FacetValue, type FieldOperators, type FlagEvaluation, type FlagsResult, type FunctionCallStat, type FunctionMetricBucket, type FunctionMetricIndexHit, type FunctionStatsResult, type GroupByEntry, type GroupByOptions, type HibernatableWebSocket, type IdGenerator, type ImportError, type ImportShardAdminArgs, type ImportShardArgs, type ImportShardResult, type IndexDefinitionLike, type IndexRangeBuilderLike, LogBuffer, type LogEntry, type LogEventInput, type LogLevel, type LogSink, MAIL_RETENTION, MAIL_TABLE, MAX_SQL_ROWS, MIN_ADMIN_TOKEN_LENGTH, MIN_AUTH_SECRET_LENGTH, type MaskColumnMetadata, type MaskPoliciesResult, type MaterializeResult, type MigrationDirection, type MigrationRunResult, type MigrationStatus, type MigrationStatusRow, type MutationDelta, type NestedWith, NotFoundError, NotUniqueError, type OnDeleteActionLike, type OrderByInput, type OrderKey, type PaginationOptions, type PitrBookmarkResult, type PitrRestoreArgs, type PitrRestoreResult, type PitrStorage, type QueryArgs, type QueryPage, type QueueMetadata, type QueuesResult, RANK_TIEBREAK, RELATION_FUNCTION_PREFIX, RLS_UNWRAP_SYMBOL, ROOT_DO_SIZE_WARN_BYTES, ROOT_SHARD_NAME, type RankDirection, type RankIndexDefinitionLike, type RankOptions, type RankPage, type RankPageOptions, type RankPageRow, type RankPageRowKey, type RankResult, type RankSortKeyLike, ReactiveCache, type ReactiveCacheOptions, type ReadHook, type ReadTablePageOptions, type RecordAuthEventInput, type RecordFunctionMetricInput, type RecordMailInput, type RelationDefinitionLike, type RenderedSql, type ResolveRelationPredicatesOptions, type ResolveWithOptions, type RestrictableQueryOptions, type RlsPoliciesResult, type RlsPolicyMetadata, RlsRequiredError, type RlsRoleMetadata, type RpcRequest, type RunDataMigrationOptions, type RunShardApplyCdcArgs, type RunShardApplyCdcResult, type RunShardBulkDeleteArgs, type RunShardBulkDeleteResult, type RunShardExportArgs, type RunShardImportArgs, type RunShardMigrationArgs, type RunShardRankBeforeArgs, type RunShardRankPageArgs, type RunShardWriteArgs, type RunShardWriteResult, type RunTriggersOptions, SCAN_DEP, SESSION_DO_TTL_DEFAULT, SHARD_REGISTRY_DO_NAME, type SchedulableWorkflowReferenceLike, type ScheduledFunctionDoc, type SchedulerLike, type SchemaLike, type SearchFilterBuilderLike, type SecurityAuditResult, type SecurityFinding, type SecurityFindingKind, type SecurityFindingLevel, type SelectMatchingIdsOptions, type ServerDefaultContextLike, SessionDO, type SessionRecord, type SettingEntry, type SettingKind, type SettingsResult, type ShapeSubscriptionQuery, ShardDO, type ShardDOOptions, type ShardDOState, type ShardRankPageResult, ShardRegistryDO, type SocketAttachment, type SortDirection, type SourceClientLike, type SourceRefresh, type SqlConsoleResult, type SqlCursor, type SqlEngine, type SqlExec, type StorageRuleMetadata, type StorageRulesResult, type StudioFeaturesResult, type SubscriptionEnvelope, type SubscriptionOutcome, type SubscriptionQuery, type SystemDatabaseReader, type SystemDoc, type SystemQuery, type SystemReaderOptions, type SystemReaderSchedulerLike, type SystemReaderStorageLike, type SystemTableName, type TableColumnsResult, type TableDefinitionLike, type TableIndexInfo, type TableIndexesResult, type TableInfo, type TablePage, type TableReaderLike, type TablesColumnsResult, type TransactionSqlLike, type TriggerContextLike, type TriggerDefinitionLike, type TriggerEventLike, type TriggerOpLike, type TriggerTimingLike, type ValidatorLike, type WhereInput, type WhereSqlStrategy, type WithInput, type WorkflowMetadata, type WorkflowsResult, type WriteEvent, type WriteHook, aggregateSqlFunction, aggregateTableName, applyCdcChanges, applyOnDelete, applySelect, armRestore, assertFlatPredicate, assertReadonly, assertShapeShardable, assertValidClientId, backfillAggregateIndexes, backfillRankIndexes, buildFtsMatch, buildSecurityAudit, buildSeekWhere, clearCapturedMail, coerceAggregateNumber, compileWhereSql, containsRelationPredicate, createDependencyTracker, createShardCtxDb, createSystemReader, decodeCursor, depKey, diffExternalSource, encodeAggregateKey, encodeCursor, encodePartitionKey, ensureAuthMetricsTables, ensureFunctionMetricsTables, ensureMailTable, exportShardRows, exportShardTable, facetColumn, fanOutScalarCounts, foldAggregateTally, ftsTableName, guardWriter, hasTrigger, importShardRows, isRelationPredicate, isSourceDue, liftSourceId, listTables, matchesRankStaticWhere, matchesStaticWhere, materializeExternalRows, mergeWhere, normalizeCountArgument, normalizeIdStructurally, normalizeOrderKeys, parseExportShardArgs, parseImportShardArgs, planAggregateLookup, pullExternalSourceTick, rankTableName, reactiveCacheKey, readAggregateValue, readAuthMetrics, readBookmark, readCapturedMail, readCdcChanges, readExternalSourceBaseline, readFunctionMetricBuckets, readFunctionMetricIndexHits, readFunctionMetrics, readFunctionMetricsTotals, readMigrationStatus, readTablePage, recordAuthEvent, recordCapturedMail, recordFunctionMetric, renderSql, resolveRankPartition, resolveRelationPredicates, resolveWith, runDataMigration, runExternalSourceTick, runReadonlySql, runRowValidators, runShardMigrations, runTriggers, scoreDocument, selectExportTables, selectIndexForAggregate, selectIndexForCount, selectIndexForGroupBy, selectMatchingIds, serveRelationFanout, softDeleteScope, sortColumnName, stableStringify, stringifySearchText, subscriptionListDeltas, throwingScheduler, tokenizeSearch, trimCdcChanges, validateImportRow };
|
|
6707
|
+
export { ADMIN_FUNCTIONS, ADMIN_FUNCTION_PREFIX, AGGREGATE_SQL_FUNCTION, AUTH_METRICS_BUCKETS_TABLE, AUTH_METRICS_BUCKET_MS, AUTH_METRICS_BUCKET_RETENTION, AUTH_METRICS_TABLE, type AdvisoriesResult, type AdvisoryFinding, type AggregateIndexDefinitionLike, type AggregateOp, type AggregateOptions, type AggregateResult, type AggregateTally, type ApplyOnDeleteOptions, type AuditEntry, type AuditLogResult, type AuthMetrics, type AuthMetricsBucket, type BroadcastDelta, CDC_LOG_TABLE, type CacheEntry, type CapturedMailRow, type CdcChange, type Clock, type ColumnMeta, type ColumnMetaLike, ConflictError, type CountArgs, CountRlsUnsupportedError, type CtxDbOptions, DATA_MIGRATION_STATE_TABLE, DEFAULT_MAX_RELATION_KEYS, type DataMigrationDocument, type DataMigrationLike, type DataMigrationTransform, type DatabaseWriterLike, type DependencyTracker, type DeployInfo, type ExportRow, type ExportShardAdminArgs, type ExportShardArgs, type ExternalSourceDiffResult, type ExternalSourceLike, FLAGS_FUNCTION_PREFIX, FUNCTION_METRICS_BUCKETS_TABLE, FUNCTION_METRICS_BUCKET_MS, FUNCTION_METRICS_BUCKET_RETENTION, FUNCTION_METRICS_INDEX_TABLE, FUNCTION_METRICS_TABLE, type FacetColumnOptions, type FacetColumnResult, type FacetValue, type FieldOperators, type FlagEvaluation, type FlagsResult, type FunctionCallStat, type FunctionMetricBucket, type FunctionMetricIndexHit, type FunctionStatsResult, type GroupByEntry, type GroupByOptions, type HibernatableWebSocket, type IdGenerator, type ImportError, type ImportShardAdminArgs, type ImportShardArgs, type ImportShardResult, type IndexDefinitionLike, type IndexRangeBuilderLike, LogBuffer, type LogEntry, type LogEventInput, type LogLevel, type LogSink, MAIL_RETENTION, MAIL_TABLE, MAX_SQL_ROWS, MIN_ADMIN_TOKEN_LENGTH, MIN_AUTH_SECRET_LENGTH, type MaskColumnMetadata, type MaskPoliciesResult, type MaterializeResult, type MigrationDirection, type MigrationRunResult, type MigrationStatus, type MigrationStatusRow, type MutationDelta, type NestedWith, NotFoundError, NotUniqueError, type OnDeleteActionLike, type OrderByInput, type OrderKey, type PaginationOptions, type PitrBookmarkResult, type PitrRestoreArgs, type PitrRestoreResult, type PitrStorage, type QueryArgs, type QueryPage, type QueueMetadata, type QueuesResult, RANK_TIEBREAK, RELATION_FUNCTION_PREFIX, RLS_UNWRAP_SYMBOL, ROOT_DO_SIZE_WARN_BYTES, ROOT_SHARD_NAME, type RankDirection, type RankIndexDefinitionLike, type RankOptions, type RankPage, type RankPageOptions, type RankPageRow, type RankPageRowKey, type RankResult, type RankSortKeyLike, ReactiveCache, type ReactiveCacheOptions, type ReadHook, type ReadTablePageOptions, type RecordAuthEventInput, type RecordFunctionMetricInput, type RecordMailInput, type RelationDefinitionLike, type RenderedSql, type ResolveRelationPredicatesOptions, type ResolveWithOptions, type RestrictableQueryOptions, type RlsPoliciesResult, type RlsPolicyMetadata, RlsRequiredError, type RlsRoleMetadata, type RpcRequest, type RunDataMigrationOptions, type RunShardApplyCdcArgs, type RunShardApplyCdcResult, type RunShardBulkDeleteArgs, type RunShardBulkDeleteResult, type RunShardExportArgs, type RunShardImportArgs, type RunShardMigrationArgs, type RunShardRankBeforeArgs, type RunShardRankPageArgs, type RunShardWriteArgs, type RunShardWriteResult, type RunTriggersOptions, SCAN_DEP, SESSION_DO_TTL_DEFAULT, SHARD_REGISTRY_DO_NAME, type SchedulableWorkflowReferenceLike, type ScheduledFunctionDoc, type SchedulerLike, type SchemaLike, type SearchFilterBuilderLike, type SecurityAuditResult, type SecurityFinding, type SecurityFindingKind, type SecurityFindingLevel, type SelectMatchingIdsOptions, type ServerDefaultContextLike, SessionDO, type SessionRecord, type SettingEntry, type SettingKind, type SettingsResult, type ShapeSubscriptionQuery, ShardDO, type ShardDOOptions, type ShardDOState, type ShardRankPageResult, ShardRegistryDO, type SocketAttachment, type SortDirection, type SourceClientLike, type SourceRefresh, type SqlConsoleResult, type SqlCursor, type SqlEngine, type SqlExec, type StorageRuleMetadata, type StorageRulesResult, type StudioFeaturesResult, type SubscriptionEnvelope, type SubscriptionOutcome, type SubscriptionQuery, type SystemDatabaseReader, type SystemDoc, type SystemQuery, type SystemReaderOptions, type SystemReaderSchedulerLike, type SystemReaderStorageLike, type SystemTableName, type TableColumnsResult, type TableDefinitionLike, type TableIndexInfo, type TableIndexesResult, type TableInfo, type TablePage, type TableReaderLike, type TablesColumnsResult, type TransactionSqlLike, type TriggerContextLike, type TriggerDefinitionLike, type TriggerEventLike, type TriggerOpLike, type TriggerTimingLike, type ValidatorLike, type WhereInput, type WhereSqlStrategy, type WithInput, type WorkflowMetadata, type WorkflowsResult, type WriteEvent, type WriteHook, aggregateSqlFunction, aggregateTableName, applyCdcChanges, applyOnDelete, applySelect, armRestore, assertFlatPredicate, assertReadonly, assertShapeShardable, assertValidClientId, backfillAggregateIndexes, backfillRankIndexes, buildFtsMatch, buildSecurityAudit, buildSeekWhere, clearCapturedMail, coerceAggregateNumber, compileWhereSql, containsRelationPredicate, createDependencyTracker, createShardCtxDb, createSystemReader, decodeCursor, depKey, diffExternalSource, encodeAggregateKey, encodeCursor, encodePartitionKey, ensureAuthMetricsTables, ensureFunctionMetricsTables, ensureMailTable, exportShardRows, exportShardTable, facetColumn, fanOutScalarCounts, foldAggregateTally, ftsTableName, guardWriter, hasTrigger, importShardRows, isRelationPredicate, isSourceDue, liftSourceId, listTables, matchesRankStaticWhere, matchesStaticWhere, materializeExternalRows, mergeWhere, normalizeCountArgument, normalizeIdStructurally, normalizeOrderKeys, parseExportShardArgs, parseImportShardArgs, planAggregateLookup, pullExternalSourceTick, rankTableName, reactiveCacheKey, readAggregateValue, readAuthMetrics, readBookmark, readCapturedMail, readCdcChanges, readExternalSourceBaseline, readFunctionMetricBuckets, readFunctionMetricIndexHits, readFunctionMetrics, readFunctionMetricsTotals, readMigrationStatus, readTablePage, recordAuthEvent, recordCapturedMail, recordFunctionMetric, renderSql, resolveRankPartition, resolveRelationPredicates, resolveWith, runDataMigration, runExternalSourceTick, runReadonlySql, runRowValidators, runShardMigrations, runTriggers, scoreDocument, selectExportTables, selectIndexForAggregate, selectIndexForCount, selectIndexForGroupBy, selectMatchingIds, serveRelationFanout, softDeleteScope, sortColumnName, stableStringify, stableWireKey, stringifySearchText, subscriptionListDeltas, throwingScheduler, tokenizeSearch, trimCdcChanges, validateImportRow };
|
package/dist/index.mjs
CHANGED
|
@@ -7,9 +7,9 @@ export { NotUniqueError, assertValidClientId, createShardCtxDb, normalizeIdStruc
|
|
|
7
7
|
export { DATA_MIGRATION_STATE_TABLE, readMigrationStatus, runDataMigration } from './packem_shared/DATA_MIGRATION_STATE_TABLE-CYwBpyTr.mjs';
|
|
8
8
|
export { SCAN_DEP, createDependencyTracker, depKey } from './packem_shared/SCAN_DEP-DLJF8dsj.mjs';
|
|
9
9
|
export { renderSql } from './packem_shared/renderSql-D6eUcn2N.mjs';
|
|
10
|
-
export { diffExternalSource } from './packem_shared/diffExternalSource-
|
|
11
|
-
export { materializeExternalRows, readExternalSourceBaseline, runExternalSourceTick } from './packem_shared/materializeExternalRows-
|
|
12
|
-
export { isSourceDue, liftSourceId, pullExternalSourceTick } from './packem_shared/isSourceDue-
|
|
10
|
+
export { diffExternalSource } from './packem_shared/diffExternalSource-CovHfdyo.mjs';
|
|
11
|
+
export { materializeExternalRows, readExternalSourceBaseline, runExternalSourceTick } from './packem_shared/materializeExternalRows-CoGmFmsY.mjs';
|
|
12
|
+
export { isSourceDue, liftSourceId, pullExternalSourceTick } from './packem_shared/isSourceDue-Bj7I3v1b.mjs';
|
|
13
13
|
export { FUNCTION_METRICS_BUCKETS_TABLE, FUNCTION_METRICS_BUCKET_MS, FUNCTION_METRICS_BUCKET_RETENTION, FUNCTION_METRICS_INDEX_TABLE, FUNCTION_METRICS_TABLE, ensureFunctionMetricsTables, readFunctionMetricBuckets, readFunctionMetricIndexHits, readFunctionMetrics, readFunctionMetricsTotals, recordFunctionMetric } from './packem_shared/FUNCTION_METRICS_BUCKETS_TABLE-UDNVD7FS.mjs';
|
|
14
14
|
export { ADMIN_FUNCTIONS, ADMIN_FUNCTION_PREFIX, FLAGS_FUNCTION_PREFIX, RELATION_FUNCTION_PREFIX, facetColumn, listTables, readTablePage, selectMatchingIds } from './packem_shared/ADMIN_FUNCTIONS-CAHLZMj8.mjs';
|
|
15
15
|
export { LogBuffer } from './packem_shared/LogBuffer-B_Ezju_N.mjs';
|
|
@@ -18,7 +18,7 @@ export { default as NotFoundError } from './packem_shared/NotFoundError-C70b9hLw
|
|
|
18
18
|
export { armRestore, readBookmark } from './packem_shared/armRestore-4Px61hHS.mjs';
|
|
19
19
|
export { applySelect, buildSeekWhere, decodeCursor, encodeCursor, normalizeOrderKeys, softDeleteScope } from './packem_shared/applySelect-WQY8m62C.mjs';
|
|
20
20
|
export { RANK_TIEBREAK, encodePartitionKey, matchesRankStaticWhere, rankTableName, resolveRankPartition, sortColumnName } from './packem_shared/RANK_TIEBREAK-CXhdcA1o.mjs';
|
|
21
|
-
export { ReactiveCache, reactiveCacheKey } from './packem_shared/ReactiveCache-
|
|
21
|
+
export { ReactiveCache, reactiveCacheKey } from './packem_shared/ReactiveCache-DnSvbjil.mjs';
|
|
22
22
|
export { serveRelationFanout } from './packem_shared/serveRelationFanout-BgaNg3Hu.mjs';
|
|
23
23
|
export { DEFAULT_MAX_RELATION_KEYS, assertFlatPredicate, assertShapeShardable, containsRelationPredicate, isRelationPredicate, resolveRelationPredicates } from './packem_shared/DEFAULT_MAX_RELATION_KEYS-BEan1CRD.mjs';
|
|
24
24
|
export { applyOnDelete, fanOutScalarCounts, resolveWith, runRowValidators } from './packem_shared/applyOnDelete-BXSq3S70.mjs';
|
|
@@ -26,9 +26,9 @@ export { RLS_UNWRAP_SYMBOL, RlsRequiredError, guardWriter } from './packem_share
|
|
|
26
26
|
export { buildFtsMatch, ftsTableName, scoreDocument, stringifySearchText, tokenizeSearch } from './packem_shared/buildFtsMatch-BLEMawrp.mjs';
|
|
27
27
|
export { M as MIN_ADMIN_TOKEN_LENGTH, a as MIN_AUTH_SECRET_LENGTH, b as buildSecurityAudit } from './packem_shared/security-audit-CucgBice.mjs';
|
|
28
28
|
export { SESSION_DO_TTL_DEFAULT, SessionDO } from './packem_shared/SESSION_DO_TTL_DEFAULT-BnSKgVO4.mjs';
|
|
29
|
-
export { ROOT_DO_SIZE_WARN_BYTES, ROOT_SHARD_NAME, ShardDO } from './packem_shared/ROOT_DO_SIZE_WARN_BYTES-
|
|
29
|
+
export { ROOT_DO_SIZE_WARN_BYTES, ROOT_SHARD_NAME, ShardDO } from './packem_shared/ROOT_DO_SIZE_WARN_BYTES-BWz51mpB.mjs';
|
|
30
30
|
export { SHARD_REGISTRY_DO_NAME, ShardRegistryDO } from './packem_shared/SHARD_REGISTRY_DO_NAME-D99roc-r.mjs';
|
|
31
|
-
export { MAX_SQL_ROWS, assertReadonly, runReadonlySql } from './packem_shared/MAX_SQL_ROWS-
|
|
31
|
+
export { MAX_SQL_ROWS, assertReadonly, runReadonlySql } from './packem_shared/MAX_SQL_ROWS-iFAA8FbD.mjs';
|
|
32
32
|
export { createSystemReader } from './packem_shared/createSystemReader-D12eNH13.mjs';
|
|
33
33
|
export { ConflictError } from './packem_shared/ConflictError-CLoq37xH.mjs';
|
|
34
34
|
export { hasTrigger, runTriggers } from './packem_shared/hasTrigger-5N6_Fx0A.mjs';
|
|
@@ -36,5 +36,6 @@ export { compileWhereSql } from './packem_shared/compileWhereSql-DE6yfRcQ.mjs';
|
|
|
36
36
|
export { CDC_LOG_TABLE, applyCdcChanges, readCdcChanges, trimCdcChanges } from './packem_shared/CDC_LOG_TABLE-DjJEHiM2.mjs';
|
|
37
37
|
export { backfillAggregateIndexes, backfillRankIndexes } from './packem_shared/backfillAggregateIndexes-DDoT-UUI.mjs';
|
|
38
38
|
export { runShardMigrations } from './packem_shared/runShardMigrations-BGx4v2B6.mjs';
|
|
39
|
-
export { stableStringify } from './packem_shared/stableStringify-
|
|
40
|
-
export {
|
|
39
|
+
export { stableStringify } from './packem_shared/stableStringify-mC40mZts.mjs';
|
|
40
|
+
export { stableWireKey } from './packem_shared/stableWireKey-DKuXO7T5.mjs';
|
|
41
|
+
export { subscriptionListDeltas } from './packem_shared/subscriptionListDeltas-CT76bYny.mjs';
|
|
@@ -3,9 +3,39 @@ import { LunoraError } from '@lunora/errors';
|
|
|
3
3
|
const MAX_SQL_ROWS = 1e3;
|
|
4
4
|
const READONLY_LEAD = /^(?:explain\s+(?:query\s+plan\s+)?)?(?:select|with)\b/iu;
|
|
5
5
|
const FORBIDDEN_KEYWORD = /\b(?:alter|attach|create|delete|detach|drop|insert|pragma|reindex|replace|truncate|update|vacuum)\b/iu;
|
|
6
|
-
const LEADING_NOISE = /^(?:\s|--[^\n]*\n?|\/\*[\s\S]*?\*\/)+/u;
|
|
7
6
|
const TRAILING_SEMICOLON = /;\s*$/u;
|
|
8
|
-
const
|
|
7
|
+
const WHITESPACE = /\s/u;
|
|
8
|
+
const skipLineComment = (sql, from) => {
|
|
9
|
+
let index = from + 2;
|
|
10
|
+
while (index < sql.length && sql[index] !== "\n") {
|
|
11
|
+
index += 1;
|
|
12
|
+
}
|
|
13
|
+
return index;
|
|
14
|
+
};
|
|
15
|
+
const skipBlockComment = (sql, from) => {
|
|
16
|
+
const close = sql.indexOf("*/", from + 2);
|
|
17
|
+
return close === -1 ? -1 : close + 2;
|
|
18
|
+
};
|
|
19
|
+
const stripLeading = (sql) => {
|
|
20
|
+
let index = 0;
|
|
21
|
+
while (index < sql.length) {
|
|
22
|
+
const char = sql[index];
|
|
23
|
+
if (char !== void 0 && WHITESPACE.test(char)) {
|
|
24
|
+
index += 1;
|
|
25
|
+
} else if (char === "-" && sql[index + 1] === "-") {
|
|
26
|
+
index = skipLineComment(sql, index);
|
|
27
|
+
} else if (char === "/" && sql[index + 1] === "*") {
|
|
28
|
+
const next = skipBlockComment(sql, index);
|
|
29
|
+
if (next === -1) {
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
index = next;
|
|
33
|
+
} else {
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return sql.slice(index);
|
|
38
|
+
};
|
|
9
39
|
const sqlError = (message, code) => new LunoraError(code, message, { status: 400 });
|
|
10
40
|
const assertReadonly = (query) => {
|
|
11
41
|
const trimmed = stripLeading(query).trim();
|
|
@@ -2,7 +2,7 @@ import { LunoraError, toErrorBody } from '@lunora/errors';
|
|
|
2
2
|
import { drizzle } from 'drizzle-orm/durable-sqlite';
|
|
3
3
|
import { c as constantTimeEqual } from './constant-time-equal-BVRWZgES.mjs';
|
|
4
4
|
import { j as jsonResponse } from './json-response-BdbtpOhm.mjs';
|
|
5
|
-
import { e as encodeWire,
|
|
5
|
+
import { e as encodeWire, d as decodeWire } from './wire-codec-CzQc1pvf.mjs';
|
|
6
6
|
import { parseExportShardArgs, parseImportShardArgs } from './exportShardRows-Dy3oFZ26.mjs';
|
|
7
7
|
import { recordAuthEvent, readAuthMetrics } from './AUTH_METRICS_BUCKETS_TABLE-CiHHYeJi.mjs';
|
|
8
8
|
import { DATA_MIGRATION_STATE_TABLE, readMigrationStatus } from './DATA_MIGRATION_STATE_TABLE-CYwBpyTr.mjs';
|
|
@@ -12,19 +12,84 @@ import { createFanoutCounters, ADMIN_FUNCTION_PREFIX, RELATION_FUNCTION_PREFIX,
|
|
|
12
12
|
import { LogBuffer } from './LogBuffer-B_Ezju_N.mjs';
|
|
13
13
|
import { recordCapturedMail, clearCapturedMail, readCapturedMail, MAIL_TABLE } from './MAIL_RETENTION-CPpgl-dX.mjs';
|
|
14
14
|
import { readBookmark, armRestore } from './armRestore-4Px61hHS.mjs';
|
|
15
|
-
import { ReactiveCache, reactiveCacheKey } from './ReactiveCache-
|
|
16
|
-
import {
|
|
15
|
+
import { ReactiveCache, reactiveCacheKey } from './ReactiveCache-DnSvbjil.mjs';
|
|
16
|
+
import { stableWireKey } from './stableWireKey-DKuXO7T5.mjs';
|
|
17
|
+
import { awaitWsDrain, trySendFrame, subscriptionListDeltas, sendDeltaFrames } from './subscriptionListDeltas-CT76bYny.mjs';
|
|
17
18
|
import { fingerprintError } from '@lunora/fingerprint';
|
|
18
19
|
import { redact, standardRules } from '@visulima/redact';
|
|
19
20
|
import { i as isDevEnvironment, c as buildSettings, b as buildSecurityAudit } from './security-audit-CucgBice.mjs';
|
|
20
|
-
import { runReadonlySql } from './MAX_SQL_ROWS-
|
|
21
|
+
import { runReadonlySql } from './MAX_SQL_ROWS-iFAA8FbD.mjs';
|
|
21
22
|
import { ConflictError } from './ConflictError-CLoq37xH.mjs';
|
|
22
23
|
import { e as deleteGlobalShapeSnapshotsForConnection, g as readIdempotent, h as writeIdempotent, t as trimIdempotent, r as readClientWatermark, m as migrateClientWatermark, c as advanceClientWatermark, d as deleteGlobalShapeSnapshot, f as readGlobalShapeSnapshot, w as writeGlobalShapeSnapshot } from './ctx-db-idempotency-BdcNpvY4.mjs';
|
|
23
24
|
import { CDC_LOG_TABLE, readCdcChanges, readCdcCursor, readCdcEpoch, minCdcSeq, bumpCdcEpoch } from './CDC_LOG_TABLE-DjJEHiM2.mjs';
|
|
25
|
+
import { stableStringify } from './stableStringify-mC40mZts.mjs';
|
|
24
26
|
import { a as selectShapeMemberIds, s as selectShapeRows } from './ctx-db-shapes-Cz9dHyh1.mjs';
|
|
25
27
|
|
|
26
28
|
const MAX_BATCH_ENTRIES = 500;
|
|
27
29
|
|
|
30
|
+
const evictOldestEntry = (map, capacity) => {
|
|
31
|
+
if (map.size < capacity) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const oldest = map.keys().next().value;
|
|
35
|
+
if (oldest !== void 0) {
|
|
36
|
+
map.delete(oldest);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const textEncoder = new TextEncoder();
|
|
41
|
+
const fromBase64Url = (input) => {
|
|
42
|
+
const padded = input.replaceAll("-", "+").replaceAll("_", "/") + "===".slice((input.length + 3) % 4);
|
|
43
|
+
const binary = atob(padded);
|
|
44
|
+
const bytes = new Uint8Array(binary.length);
|
|
45
|
+
for (let index = 0; index < binary.length; index += 1) {
|
|
46
|
+
bytes[index] = binary.codePointAt(index) ?? 0;
|
|
47
|
+
}
|
|
48
|
+
return bytes;
|
|
49
|
+
};
|
|
50
|
+
const KEY_CACHE_MAX = 64;
|
|
51
|
+
const keyCache = /* @__PURE__ */ new Map();
|
|
52
|
+
const importHmacKey = async (secret) => {
|
|
53
|
+
const cached = keyCache.get(secret);
|
|
54
|
+
if (cached) {
|
|
55
|
+
return cached;
|
|
56
|
+
}
|
|
57
|
+
evictOldestEntry(keyCache, KEY_CACHE_MAX);
|
|
58
|
+
const keyPromise = crypto.subtle.importKey("raw", textEncoder.encode(secret), { hash: "SHA-256", name: "HMAC" }, false, ["sign", "verify"]);
|
|
59
|
+
keyCache.set(secret, keyPromise);
|
|
60
|
+
return keyPromise;
|
|
61
|
+
};
|
|
62
|
+
const verifyCanonical = async (secret, canonical, sigBytes) => {
|
|
63
|
+
const cryptoKey = await importHmacKey(secret);
|
|
64
|
+
return crypto.subtle.verify("HMAC", cryptoKey, sigBytes, textEncoder.encode(canonical));
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const WS_ADMIN_TOKEN_VERSION = "v1";
|
|
68
|
+
const verifyWsAdminToken = async (secret, token, now = Date.now()) => {
|
|
69
|
+
if (secret.length === 0 || token.length === 0) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
const parts = token.split(".");
|
|
73
|
+
if (parts.length !== 3) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
const [version, expString, signature] = parts;
|
|
77
|
+
if (version !== WS_ADMIN_TOKEN_VERSION || signature.length === 0) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
const expiresAtMs = Number(expString);
|
|
81
|
+
if (!Number.isFinite(expiresAtMs) || expiresAtMs <= now) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
let signatureBytes;
|
|
85
|
+
try {
|
|
86
|
+
signatureBytes = fromBase64Url(signature);
|
|
87
|
+
} catch {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
return verifyCanonical(secret, `${version}.${expString}`, signatureBytes);
|
|
91
|
+
};
|
|
92
|
+
|
|
28
93
|
const AUDIT_LOG_TABLE = "__lunora_audit__";
|
|
29
94
|
const AUDIT_LOG_RETENTION = 1e3;
|
|
30
95
|
const runSql$3 = (sql, query, ...params) => {
|
|
@@ -321,7 +386,7 @@ const parseRelayName = (name) => {
|
|
|
321
386
|
return { ownerKey, relayIndex };
|
|
322
387
|
};
|
|
323
388
|
|
|
324
|
-
const shapeRoutingKey = (name, args) =>
|
|
389
|
+
const shapeRoutingKey = (name, args) => stableWireKey({ args: args ?? {}, name });
|
|
325
390
|
const DEFAULT_PROMOTION_THRESHOLDS = { tDown: 4e3, tUp: 8e3 };
|
|
326
391
|
const nextPromotionState = (current, subscribers, thresholds = DEFAULT_PROMOTION_THRESHOLDS) => {
|
|
327
392
|
if (thresholds.tDown >= thresholds.tUp) {
|
|
@@ -480,12 +545,12 @@ class RelayLink {
|
|
|
480
545
|
case "relay_shape_poke": {
|
|
481
546
|
const iterated = this.host.getWebSockets().length;
|
|
482
547
|
const startMs = Date.now();
|
|
483
|
-
const delivered = this.onShapePoke(message);
|
|
548
|
+
const delivered = this.onShapePoke({ ...message, args: decodeWire(message.args) });
|
|
484
549
|
this.host.recordShapePokeFanout(iterated, delivered, Date.now() - startMs);
|
|
485
550
|
return noContent();
|
|
486
551
|
}
|
|
487
552
|
case "relay_shape_subscribe": {
|
|
488
|
-
return jsonRelayResponse(this.onShapeSubscribe(message));
|
|
553
|
+
return jsonRelayResponse(this.onShapeSubscribe({ ...message, args: decodeWire(message.args) }));
|
|
489
554
|
}
|
|
490
555
|
default: {
|
|
491
556
|
return assertNeverFrame(message);
|
|
@@ -677,7 +742,9 @@ class OwnerRelay extends RelayLink {
|
|
|
677
742
|
}
|
|
678
743
|
entry.cursor = frameCursor;
|
|
679
744
|
const poke = {
|
|
680
|
-
args
|
|
745
|
+
// `args` wire-encoded for the same reason as `rowsPatch` below; the
|
|
746
|
+
// relay decodes them at `handleControl` before the routing match.
|
|
747
|
+
args: encodeWire(entry.args),
|
|
681
748
|
checkpoint: frameCursor,
|
|
682
749
|
epoch,
|
|
683
750
|
fromCursor,
|
|
@@ -724,7 +791,9 @@ class OwnerRelay extends RelayLink {
|
|
|
724
791
|
}
|
|
725
792
|
entry.cursor = frameCursor;
|
|
726
793
|
const poke = {
|
|
727
|
-
args
|
|
794
|
+
// `args` wire-encoded like `rowsPatch`; decoded relay-side at
|
|
795
|
+
// `handleControl` before the routing match.
|
|
796
|
+
args: encodeWire(entry.args),
|
|
728
797
|
checkpoint: frameCursor,
|
|
729
798
|
epoch,
|
|
730
799
|
fromCursor,
|
|
@@ -859,8 +928,8 @@ class OwnerRelay extends RelayLink {
|
|
|
859
928
|
if (this.tableHasAnyMask(base.table)) {
|
|
860
929
|
return false;
|
|
861
930
|
}
|
|
862
|
-
const baseWhere =
|
|
863
|
-
const baseColumns =
|
|
931
|
+
const baseWhere = stableWireKey(base.effectiveWhere);
|
|
932
|
+
const baseColumns = stableWireKey(base.columns);
|
|
864
933
|
let enumerated = false;
|
|
865
934
|
const populate = (side) => {
|
|
866
935
|
const backing = { groups: [`grp_${side}`], roles: [side], sub: `__lunora_probe_${side}__` };
|
|
@@ -890,7 +959,7 @@ class OwnerRelay extends RelayLink {
|
|
|
890
959
|
} catch {
|
|
891
960
|
return false;
|
|
892
961
|
}
|
|
893
|
-
return resolved !== void 0 && resolved.global !== true && resolved.table === base.table &&
|
|
962
|
+
return resolved !== void 0 && resolved.global !== true && resolved.table === base.table && stableWireKey(resolved.effectiveWhere) === baseWhere && stableWireKey(resolved.columns) === baseColumns;
|
|
894
963
|
});
|
|
895
964
|
return matches && !enumerated;
|
|
896
965
|
}
|
|
@@ -938,7 +1007,10 @@ class RelayMember extends RelayLink {
|
|
|
938
1007
|
}
|
|
939
1008
|
await this.announce();
|
|
940
1009
|
const request = {
|
|
941
|
-
|
|
1010
|
+
// Wire-encode before the relay->owner `JSON.stringify` hop: the shard
|
|
1011
|
+
// decoded these args at its `shape_subscribe` entry point, so a
|
|
1012
|
+
// `bigint`/`Date`/bytes arg would otherwise throw (or corrupt) here.
|
|
1013
|
+
args: encodeWire(shape.args ?? {}),
|
|
942
1014
|
connectionId: this.host.readAttachment(ws).connectionId,
|
|
943
1015
|
identity: identity.identity,
|
|
944
1016
|
name: shape.name,
|
|
@@ -1420,6 +1492,7 @@ const findDanglingReferences = (sql, storageColumns, liveKeys) => {
|
|
|
1420
1492
|
|
|
1421
1493
|
const WS_KEEPALIVE_PING = "lunora-ping";
|
|
1422
1494
|
const WS_KEEPALIVE_PONG = "lunora-pong";
|
|
1495
|
+
const REQUIRE_EPHEMERAL_ENV_VALUES = /* @__PURE__ */ new Set(["1", "enabled", "on", "true", "yes"]);
|
|
1423
1496
|
const UNDELIVERED_BASELINE = "<undelivered>";
|
|
1424
1497
|
const ROOT_DO_SIZE_WARN_BYTES = 1073741824;
|
|
1425
1498
|
const CDC_RESUME_SCAN_LIMIT = 1e4;
|
|
@@ -2512,7 +2585,24 @@ class ShardDO {
|
|
|
2512
2585
|
ws.send(JSON.stringify({ id: envelope.id, message: "admin subscription requires admin authorization", type: "error" }));
|
|
2513
2586
|
return;
|
|
2514
2587
|
}
|
|
2515
|
-
|
|
2588
|
+
let query;
|
|
2589
|
+
try {
|
|
2590
|
+
query = envelope.query.args === void 0 ? envelope.query : { ...envelope.query, args: decodeWire(envelope.query.args) };
|
|
2591
|
+
} catch {
|
|
2592
|
+
try {
|
|
2593
|
+
ws.send(
|
|
2594
|
+
JSON.stringify({
|
|
2595
|
+
code: "BAD_SUBSCRIPTION_ARGS",
|
|
2596
|
+
error: { code: "BAD_SUBSCRIPTION_ARGS", message: "subscription args failed wire decoding" },
|
|
2597
|
+
id: envelope.id,
|
|
2598
|
+
type: "error"
|
|
2599
|
+
})
|
|
2600
|
+
);
|
|
2601
|
+
} catch {
|
|
2602
|
+
}
|
|
2603
|
+
return;
|
|
2604
|
+
}
|
|
2605
|
+
const status = this.subscribe(ws, envelope.id, query);
|
|
2516
2606
|
if (status !== "ok") {
|
|
2517
2607
|
const code = status === "too_many" ? "TOO_MANY_SUBSCRIPTIONS" : "SUBSCRIPTION_PERSIST_FAILED";
|
|
2518
2608
|
const errorMessage = status === "too_many" ? `subscription cap of ${String(ShardDO.MAX_SUBSCRIPTIONS_PER_SOCKET)} reached on this socket` : "failed to persist subscription attachment";
|
|
@@ -2524,13 +2614,20 @@ class ShardDO {
|
|
|
2524
2614
|
}
|
|
2525
2615
|
ws.send(JSON.stringify({ id: envelope.id, type: "ack" }));
|
|
2526
2616
|
if (functionPath) {
|
|
2527
|
-
await this.seedSubscription(ws, envelope.id,
|
|
2617
|
+
await this.seedSubscription(ws, envelope.id, query, functionPath, isAdmin);
|
|
2528
2618
|
}
|
|
2529
2619
|
return;
|
|
2530
2620
|
}
|
|
2531
2621
|
if (envelope.type === "shape_subscribe" && envelope.shape) {
|
|
2622
|
+
let shapeArgs;
|
|
2623
|
+
try {
|
|
2624
|
+
shapeArgs = envelope.shape.args === void 0 ? void 0 : decodeWire(envelope.shape.args);
|
|
2625
|
+
} catch {
|
|
2626
|
+
this.sendShapeSubscribeError(ws, envelope.id, "BAD_SUBSCRIPTION_ARGS", "shape args failed wire decoding");
|
|
2627
|
+
return;
|
|
2628
|
+
}
|
|
2532
2629
|
await this.handleShapeSubscribe(ws, envelope.id, {
|
|
2533
|
-
args:
|
|
2630
|
+
args: shapeArgs,
|
|
2534
2631
|
name: envelope.shape.name,
|
|
2535
2632
|
sinceEpoch: envelope.sinceEpoch,
|
|
2536
2633
|
sinceSeq: envelope.sinceCheckpoint
|
|
@@ -6303,9 +6400,14 @@ class ShardDO {
|
|
|
6303
6400
|
* server logs, browser history, and `Referer` headers on any
|
|
6304
6401
|
* subresource the upgrade page loads after the handshake. Use a
|
|
6305
6402
|
* short-lived rotating token in production rather than a long-lived
|
|
6306
|
-
* secret
|
|
6403
|
+
* secret — for the ADMIN credential specifically, the worker mints one
|
|
6404
|
+
* (`POST /_lunora/admin/ws-token`) and {@link isAdminSocket} accepts it, so
|
|
6405
|
+
* the master `LUNORA_ADMIN_TOKEN` never rides the URL.
|
|
6406
|
+
*
|
|
6407
|
+
* Async because the admin fallback ({@link isAdminSocket}) verifies the
|
|
6408
|
+
* ephemeral sub-token with WebCrypto HMAC.
|
|
6307
6409
|
*/
|
|
6308
|
-
isUpgradeAllowed(request) {
|
|
6410
|
+
async isUpgradeAllowed(request) {
|
|
6309
6411
|
const env = this.env ?? {};
|
|
6310
6412
|
const allowedOrigins = env.LUNORA_ALLOWED_ORIGINS;
|
|
6311
6413
|
if (allowedOrigins && allowedOrigins.trim() !== "") {
|
|
@@ -6321,7 +6423,7 @@ class ShardDO {
|
|
|
6321
6423
|
const expectedBearer = env.LUNORA_WS_BEARER;
|
|
6322
6424
|
if (expectedBearer && expectedBearer.length > 0) {
|
|
6323
6425
|
const supplied = this.suppliedWsToken(request);
|
|
6324
|
-
if (!supplied || !constantTimeEqual(supplied, expectedBearer) && !this.isAdminSocket(request)) {
|
|
6426
|
+
if (!supplied || !constantTimeEqual(supplied, expectedBearer) && !await this.isAdminSocket(request)) {
|
|
6325
6427
|
return false;
|
|
6326
6428
|
}
|
|
6327
6429
|
}
|
|
@@ -6342,19 +6444,40 @@ class ShardDO {
|
|
|
6342
6444
|
return new URL(request.url).searchParams.get("token") ?? void 0;
|
|
6343
6445
|
}
|
|
6344
6446
|
/**
|
|
6345
|
-
* Whether the upgrade presented
|
|
6346
|
-
* constant-time compared
|
|
6347
|
-
*
|
|
6348
|
-
*
|
|
6447
|
+
* Whether the upgrade presented an admin credential: the master
|
|
6448
|
+
* `LUNORA_ADMIN_TOKEN` (constant-time compared) or a short-lived sub-token
|
|
6449
|
+
* the worker minted with it (`POST /_lunora/admin/ws-token` —
|
|
6450
|
+
* HMAC-verified statelessly here, since both isolates hold the master token
|
|
6451
|
+
* in `env`). The ephemeral token is what the studio sends in `?token=`, so
|
|
6452
|
+
* the master credential stays out of URLs/logs. Closed (resolves `false`)
|
|
6453
|
+
* when the admin token is unset, mirroring `isAdminAuthorized` for the HTTP
|
|
6454
|
+
* path so admin streaming is opt-in rather than exposed by default.
|
|
6455
|
+
*
|
|
6456
|
+
* Enforcement: with `LUNORA_REQUIRE_EPHEMERAL_WS_TOKEN` set
|
|
6457
|
+
* (`1`/`true`/`on`/`yes`/`enabled`), a raw master token in the
|
|
6458
|
+
* `?token=` query parameter is rejected — the query string is exactly
|
|
6459
|
+
* where it leaks. The `Authorization` header path still takes the master
|
|
6460
|
+
* token: browsers can't set it on a WS upgrade, so it never rides a URL.
|
|
6349
6461
|
*/
|
|
6350
|
-
isAdminSocket(request) {
|
|
6462
|
+
async isAdminSocket(request) {
|
|
6351
6463
|
const env = this.env ?? {};
|
|
6352
6464
|
const adminToken = env.LUNORA_ADMIN_TOKEN;
|
|
6353
6465
|
if (!adminToken || adminToken.length === 0) {
|
|
6354
6466
|
return false;
|
|
6355
6467
|
}
|
|
6356
6468
|
const supplied = this.suppliedWsToken(request);
|
|
6357
|
-
|
|
6469
|
+
if (supplied === void 0) {
|
|
6470
|
+
return false;
|
|
6471
|
+
}
|
|
6472
|
+
if (await verifyWsAdminToken(adminToken, supplied)) {
|
|
6473
|
+
return true;
|
|
6474
|
+
}
|
|
6475
|
+
const fromQuery = extractBearerToken(request.headers.get("authorization")) === void 0;
|
|
6476
|
+
const requireEphemeral = REQUIRE_EPHEMERAL_ENV_VALUES.has((env.LUNORA_REQUIRE_EPHEMERAL_WS_TOKEN ?? "").trim().toLowerCase());
|
|
6477
|
+
if (fromQuery && requireEphemeral) {
|
|
6478
|
+
return false;
|
|
6479
|
+
}
|
|
6480
|
+
return constantTimeEqual(supplied, adminToken);
|
|
6358
6481
|
}
|
|
6359
6482
|
/**
|
|
6360
6483
|
* Register the hibernation-safe ping/pong keepalive. The runtime answers a
|
|
@@ -6396,10 +6519,11 @@ class ShardDO {
|
|
|
6396
6519
|
}
|
|
6397
6520
|
return void 0;
|
|
6398
6521
|
}
|
|
6399
|
-
handleWebSocketUpgrade(request) {
|
|
6400
|
-
if (!this.isUpgradeAllowed(request)) {
|
|
6522
|
+
async handleWebSocketUpgrade(request) {
|
|
6523
|
+
if (!await this.isUpgradeAllowed(request)) {
|
|
6401
6524
|
return new Response("Forbidden", { status: 403 });
|
|
6402
6525
|
}
|
|
6526
|
+
const admin = await this.isAdminSocket(request);
|
|
6403
6527
|
const pair = new WebSocketPair();
|
|
6404
6528
|
const client = pair[0];
|
|
6405
6529
|
const server = pair[1];
|
|
@@ -6409,7 +6533,7 @@ class ShardDO {
|
|
|
6409
6533
|
const expiresAtRaw = Number(request.headers.get("x-lunora-identity-exp"));
|
|
6410
6534
|
const expiresAt = Number.isFinite(expiresAtRaw) && expiresAtRaw > 0 ? expiresAtRaw : void 0;
|
|
6411
6535
|
server.serializeAttachment?.({
|
|
6412
|
-
admin
|
|
6536
|
+
admin,
|
|
6413
6537
|
connectionId: crypto.randomUUID(),
|
|
6414
6538
|
subs: {},
|
|
6415
6539
|
...expiresAt === void 0 ? {} : { expiresAt },
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { stableWireKey } from './stableWireKey-DKuXO7T5.mjs';
|
|
2
2
|
import { depKey, SCAN_DEP } from './SCAN_DEP-DLJF8dsj.mjs';
|
|
3
|
+
export { stableStringify } from './stableStringify-mC40mZts.mjs';
|
|
3
4
|
|
|
4
5
|
const DEFAULT_MAX_ENTRIES = 1e3;
|
|
5
6
|
const DEFAULT_MAX_BYTES = 4 * 1024 * 1024;
|
|
@@ -227,6 +228,6 @@ class ReactiveCache {
|
|
|
227
228
|
}
|
|
228
229
|
}
|
|
229
230
|
}
|
|
230
|
-
const reactiveCacheKey = (functionPath, args, identity) => `${identity ?? "\0anon"}\0${functionPath}:${
|
|
231
|
+
const reactiveCacheKey = (functionPath, args, identity) => `${identity ?? "\0anon"}\0${functionPath}:${stableWireKey(args)}`;
|
|
231
232
|
|
|
232
|
-
export { ReactiveCache, reactiveCacheKey,
|
|
233
|
+
export { ReactiveCache, reactiveCacheKey, stableWireKey };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LunoraError } from '@lunora/errors';
|
|
2
|
-
import { runExternalSourceTick } from './materializeExternalRows-
|
|
2
|
+
import { runExternalSourceTick } from './materializeExternalRows-CoGmFmsY.mjs';
|
|
3
3
|
|
|
4
4
|
const liftSourceId = (row, options = {}) => {
|
|
5
5
|
const { idColumn = "id", map } = options;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { applyCdcChanges } from './CDC_LOG_TABLE-DjJEHiM2.mjs';
|
|
2
2
|
import { s as selectShapeRows } from './ctx-db-shapes-Cz9dHyh1.mjs';
|
|
3
|
-
import { diffExternalSource, projectExternalSourceRow } from './diffExternalSource-
|
|
4
|
-
import { stableStringify } from './stableStringify-
|
|
3
|
+
import { diffExternalSource, projectExternalSourceRow } from './diffExternalSource-CovHfdyo.mjs';
|
|
4
|
+
import { stableStringify } from './stableStringify-mC40mZts.mjs';
|
|
5
5
|
|
|
6
6
|
const materializeExternalRows = async (writer, pulled, baseline, options) => {
|
|
7
7
|
const { changes, nextBaseline } = diffExternalSource(pulled, baseline, options);
|
|
@@ -9,7 +9,7 @@ const stableStringify = (value) => {
|
|
|
9
9
|
return "null";
|
|
10
10
|
}
|
|
11
11
|
if (typeof value === "bigint") {
|
|
12
|
-
throw new TypeError("stableStringify: cannot use a bigint in a cache key
|
|
12
|
+
throw new TypeError("stableStringify: cannot use a bigint in a stable JSON cache key — pass it as a string, or use stableWireKey");
|
|
13
13
|
}
|
|
14
14
|
if (value === null || typeof value !== "object") {
|
|
15
15
|
return JSON.stringify(value);
|
|
@@ -21,7 +21,7 @@ const stableStringify = (value) => {
|
|
|
21
21
|
if (proto !== null && proto !== Object.prototype) {
|
|
22
22
|
const name = value.constructor?.name ?? "value";
|
|
23
23
|
throw new TypeError(
|
|
24
|
-
`stableStringify: cannot use a ${name} in a cache key
|
|
24
|
+
`stableStringify: cannot use a ${name} in a stable JSON cache key — only plain objects, arrays, and JSON primitives are supported (wire-typed values key via stableWireKey)`
|
|
25
25
|
);
|
|
26
26
|
}
|
|
27
27
|
const record = value;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { e as encodeWire } from './wire-codec-CzQc1pvf.mjs';
|
|
2
|
+
|
|
3
|
+
const ROW_ID_FIELD = "_id";
|
|
4
|
+
const DELTA_FALLBACK_TABLE = "__lunora__";
|
|
5
|
+
const readRowId = (row) => {
|
|
6
|
+
if (typeof row !== "object" || row === null || Array.isArray(row)) {
|
|
7
|
+
return void 0;
|
|
8
|
+
}
|
|
9
|
+
const id = row[ROW_ID_FIELD];
|
|
10
|
+
return typeof id === "string" ? id : void 0;
|
|
11
|
+
};
|
|
12
|
+
const indexRowsById = (rows) => {
|
|
13
|
+
const byId = /* @__PURE__ */ new Map();
|
|
14
|
+
const order = [];
|
|
15
|
+
for (const row of rows) {
|
|
16
|
+
const id = readRowId(row);
|
|
17
|
+
if (id === void 0 || byId.has(id)) {
|
|
18
|
+
return void 0;
|
|
19
|
+
}
|
|
20
|
+
byId.set(id, row);
|
|
21
|
+
order.push(id);
|
|
22
|
+
}
|
|
23
|
+
return { byId, order };
|
|
24
|
+
};
|
|
25
|
+
const survivorsKeepOrder = (previous, next) => {
|
|
26
|
+
const survivingPrevious = previous.order.filter((id) => next.byId.has(id));
|
|
27
|
+
const survivingNext = next.order.filter((id) => previous.byId.has(id));
|
|
28
|
+
if (survivingPrevious.length !== survivingNext.length) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
return survivingPrevious.every((id, index) => survivingNext[index] === id);
|
|
32
|
+
};
|
|
33
|
+
const collectDeleteDeltas = (previous, next, deltaTable, tableJson) => {
|
|
34
|
+
const out = [];
|
|
35
|
+
for (const id of previous.order) {
|
|
36
|
+
if (!next.byId.has(id)) {
|
|
37
|
+
out.push({
|
|
38
|
+
delta: { key: id, op: "delete", table: deltaTable },
|
|
39
|
+
frame: `{"key":${JSON.stringify(id)},"op":"delete","table":${tableJson}}`
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return out;
|
|
44
|
+
};
|
|
45
|
+
const collectUpsertDeltas = (previous, next, deltaTable, tableJson) => {
|
|
46
|
+
const out = [];
|
|
47
|
+
for (const id of next.order) {
|
|
48
|
+
const nextRow = next.byId.get(id);
|
|
49
|
+
const previousRow = previous.byId.get(id);
|
|
50
|
+
const nextFingerprint = JSON.stringify(encodeWire(nextRow));
|
|
51
|
+
const previousFingerprint = previousRow === void 0 ? void 0 : JSON.stringify(previousRow);
|
|
52
|
+
if (previousFingerprint === nextFingerprint) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
const op = previousFingerprint === void 0 ? "insert" : "update";
|
|
56
|
+
out.push({
|
|
57
|
+
delta: { key: id, op, row: nextRow, table: deltaTable },
|
|
58
|
+
frame: `{"key":${JSON.stringify(id)},"op":"${op}","row":${nextFingerprint},"table":${tableJson}}`
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return out;
|
|
62
|
+
};
|
|
63
|
+
const subscriptionListDeltas = (previousJson, nextResult, table, frames) => {
|
|
64
|
+
let parsed;
|
|
65
|
+
try {
|
|
66
|
+
parsed = JSON.parse(previousJson);
|
|
67
|
+
} catch {
|
|
68
|
+
return void 0;
|
|
69
|
+
}
|
|
70
|
+
if (!Array.isArray(parsed) || !Array.isArray(nextResult)) {
|
|
71
|
+
return void 0;
|
|
72
|
+
}
|
|
73
|
+
const previous = indexRowsById(parsed);
|
|
74
|
+
const next = indexRowsById(nextResult);
|
|
75
|
+
if (previous === void 0 || next === void 0) {
|
|
76
|
+
return void 0;
|
|
77
|
+
}
|
|
78
|
+
if (!survivorsKeepOrder(previous, next)) {
|
|
79
|
+
return void 0;
|
|
80
|
+
}
|
|
81
|
+
const deltaTable = table === "" ? DELTA_FALLBACK_TABLE : table;
|
|
82
|
+
const tableJson = JSON.stringify(deltaTable);
|
|
83
|
+
const framed = [...collectDeleteDeltas(previous, next, deltaTable, tableJson), ...collectUpsertDeltas(previous, next, deltaTable, tableJson)];
|
|
84
|
+
if (framed.length > next.order.length) {
|
|
85
|
+
return void 0;
|
|
86
|
+
}
|
|
87
|
+
if (frames !== void 0) {
|
|
88
|
+
for (const { frame } of framed) {
|
|
89
|
+
frames.push(frame);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return framed.map(({ delta }) => delta);
|
|
93
|
+
};
|
|
94
|
+
const trySendFrame = (ws, frame) => {
|
|
95
|
+
try {
|
|
96
|
+
ws.send(frame);
|
|
97
|
+
return true;
|
|
98
|
+
} catch {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
const sendDeltaFrames = (ws, subId, deltaFrames, cursorSuffix) => {
|
|
103
|
+
const idJson = JSON.stringify(subId);
|
|
104
|
+
let delivered = true;
|
|
105
|
+
for (const deltaBody of deltaFrames) {
|
|
106
|
+
if (!trySendFrame(ws, `{"type":"delta","id":${idJson},"delta":${deltaBody}${cursorSuffix}}`)) {
|
|
107
|
+
delivered = false;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return delivered;
|
|
111
|
+
};
|
|
112
|
+
const awaitWsDrain = async (ws) => {
|
|
113
|
+
let attempts = 0;
|
|
114
|
+
while (attempts < 100) {
|
|
115
|
+
attempts += 1;
|
|
116
|
+
const buffered = ws.bufferedAmount;
|
|
117
|
+
if (typeof buffered !== "number" || buffered < 1048576) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
await new Promise((resolve) => {
|
|
121
|
+
setTimeout(resolve, 20);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export { awaitWsDrain, sendDeltaFrames, subscriptionListDeltas, trySendFrame };
|
|
@@ -222,127 +222,4 @@ const decodeWire = (value, depth = 0) => {
|
|
|
222
222
|
return result;
|
|
223
223
|
};
|
|
224
224
|
|
|
225
|
-
|
|
226
|
-
const DELTA_FALLBACK_TABLE = "__lunora__";
|
|
227
|
-
const readRowId = (row) => {
|
|
228
|
-
if (typeof row !== "object" || row === null || Array.isArray(row)) {
|
|
229
|
-
return void 0;
|
|
230
|
-
}
|
|
231
|
-
const id = row[ROW_ID_FIELD];
|
|
232
|
-
return typeof id === "string" ? id : void 0;
|
|
233
|
-
};
|
|
234
|
-
const indexRowsById = (rows) => {
|
|
235
|
-
const byId = /* @__PURE__ */ new Map();
|
|
236
|
-
const order = [];
|
|
237
|
-
for (const row of rows) {
|
|
238
|
-
const id = readRowId(row);
|
|
239
|
-
if (id === void 0 || byId.has(id)) {
|
|
240
|
-
return void 0;
|
|
241
|
-
}
|
|
242
|
-
byId.set(id, row);
|
|
243
|
-
order.push(id);
|
|
244
|
-
}
|
|
245
|
-
return { byId, order };
|
|
246
|
-
};
|
|
247
|
-
const survivorsKeepOrder = (previous, next) => {
|
|
248
|
-
const survivingPrevious = previous.order.filter((id) => next.byId.has(id));
|
|
249
|
-
const survivingNext = next.order.filter((id) => previous.byId.has(id));
|
|
250
|
-
if (survivingPrevious.length !== survivingNext.length) {
|
|
251
|
-
return false;
|
|
252
|
-
}
|
|
253
|
-
return survivingPrevious.every((id, index) => survivingNext[index] === id);
|
|
254
|
-
};
|
|
255
|
-
const collectDeleteDeltas = (previous, next, deltaTable, tableJson) => {
|
|
256
|
-
const out = [];
|
|
257
|
-
for (const id of previous.order) {
|
|
258
|
-
if (!next.byId.has(id)) {
|
|
259
|
-
out.push({
|
|
260
|
-
delta: { key: id, op: "delete", table: deltaTable },
|
|
261
|
-
frame: `{"key":${JSON.stringify(id)},"op":"delete","table":${tableJson}}`
|
|
262
|
-
});
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
return out;
|
|
266
|
-
};
|
|
267
|
-
const collectUpsertDeltas = (previous, next, deltaTable, tableJson) => {
|
|
268
|
-
const out = [];
|
|
269
|
-
for (const id of next.order) {
|
|
270
|
-
const nextRow = next.byId.get(id);
|
|
271
|
-
const previousRow = previous.byId.get(id);
|
|
272
|
-
const nextFingerprint = JSON.stringify(encodeWire(nextRow));
|
|
273
|
-
const previousFingerprint = previousRow === void 0 ? void 0 : JSON.stringify(previousRow);
|
|
274
|
-
if (previousFingerprint === nextFingerprint) {
|
|
275
|
-
continue;
|
|
276
|
-
}
|
|
277
|
-
const op = previousFingerprint === void 0 ? "insert" : "update";
|
|
278
|
-
out.push({
|
|
279
|
-
delta: { key: id, op, row: nextRow, table: deltaTable },
|
|
280
|
-
frame: `{"key":${JSON.stringify(id)},"op":"${op}","row":${nextFingerprint},"table":${tableJson}}`
|
|
281
|
-
});
|
|
282
|
-
}
|
|
283
|
-
return out;
|
|
284
|
-
};
|
|
285
|
-
const subscriptionListDeltas = (previousJson, nextResult, table, frames) => {
|
|
286
|
-
let parsed;
|
|
287
|
-
try {
|
|
288
|
-
parsed = JSON.parse(previousJson);
|
|
289
|
-
} catch {
|
|
290
|
-
return void 0;
|
|
291
|
-
}
|
|
292
|
-
if (!Array.isArray(parsed) || !Array.isArray(nextResult)) {
|
|
293
|
-
return void 0;
|
|
294
|
-
}
|
|
295
|
-
const previous = indexRowsById(parsed);
|
|
296
|
-
const next = indexRowsById(nextResult);
|
|
297
|
-
if (previous === void 0 || next === void 0) {
|
|
298
|
-
return void 0;
|
|
299
|
-
}
|
|
300
|
-
if (!survivorsKeepOrder(previous, next)) {
|
|
301
|
-
return void 0;
|
|
302
|
-
}
|
|
303
|
-
const deltaTable = table === "" ? DELTA_FALLBACK_TABLE : table;
|
|
304
|
-
const tableJson = JSON.stringify(deltaTable);
|
|
305
|
-
const framed = [...collectDeleteDeltas(previous, next, deltaTable, tableJson), ...collectUpsertDeltas(previous, next, deltaTable, tableJson)];
|
|
306
|
-
if (framed.length > next.order.length) {
|
|
307
|
-
return void 0;
|
|
308
|
-
}
|
|
309
|
-
if (frames !== void 0) {
|
|
310
|
-
for (const { frame } of framed) {
|
|
311
|
-
frames.push(frame);
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
return framed.map(({ delta }) => delta);
|
|
315
|
-
};
|
|
316
|
-
const trySendFrame = (ws, frame) => {
|
|
317
|
-
try {
|
|
318
|
-
ws.send(frame);
|
|
319
|
-
return true;
|
|
320
|
-
} catch {
|
|
321
|
-
return false;
|
|
322
|
-
}
|
|
323
|
-
};
|
|
324
|
-
const sendDeltaFrames = (ws, subId, deltaFrames, cursorSuffix) => {
|
|
325
|
-
const idJson = JSON.stringify(subId);
|
|
326
|
-
let delivered = true;
|
|
327
|
-
for (const deltaBody of deltaFrames) {
|
|
328
|
-
if (!trySendFrame(ws, `{"type":"delta","id":${idJson},"delta":${deltaBody}${cursorSuffix}}`)) {
|
|
329
|
-
delivered = false;
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
return delivered;
|
|
333
|
-
};
|
|
334
|
-
const awaitWsDrain = async (ws) => {
|
|
335
|
-
let attempts = 0;
|
|
336
|
-
while (attempts < 100) {
|
|
337
|
-
attempts += 1;
|
|
338
|
-
const buffered = ws.bufferedAmount;
|
|
339
|
-
if (typeof buffered !== "number" || buffered < 1048576) {
|
|
340
|
-
return;
|
|
341
|
-
}
|
|
342
|
-
await new Promise((resolve) => {
|
|
343
|
-
setTimeout(resolve, 20);
|
|
344
|
-
});
|
|
345
|
-
}
|
|
346
|
-
};
|
|
347
|
-
|
|
348
|
-
export { awaitWsDrain as a, sendDeltaFrames as b, decodeWire as d, encodeWire as e, subscriptionListDeltas as s, trySendFrame as t };
|
|
225
|
+
export { decodeWire as d, encodeWire as e };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/do",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.31",
|
|
4
4
|
"description": "Lunora Durable Objects: ShardDO (SQLite, OCC, hibernated WebSocket subscriptions) and SessionDO",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"access": "public"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@lunora/errors": "1.0.0-alpha.
|
|
50
|
-
"@lunora/fingerprint": "1.0.0-alpha.
|
|
49
|
+
"@lunora/errors": "1.0.0-alpha.5",
|
|
50
|
+
"@lunora/fingerprint": "1.0.0-alpha.2",
|
|
51
51
|
"@visulima/redact": "3.0.0",
|
|
52
52
|
"drizzle-orm": "^0.45.2"
|
|
53
53
|
},
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { a as awaitWsDrain, b as sendDeltaFrames, s as subscriptionListDeltas, t as trySendFrame } from './subscription-delivery-CWigSEr3.mjs';
|