@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 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 a token matching `LUNORA_ADMIN_TOKEN`,
6446
- * constant-time compared. Closed (returns `false`) when the admin token is
6447
- * unset, mirroring `isAdminAuthorized` for the HTTP path so admin
6448
- * streaming is opt-in rather than exposed by default.
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 a token matching `LUNORA_ADMIN_TOKEN`,
6446
- * constant-time compared. Closed (returns `false`) when the admin token is
6447
- * unset, mirroring `isAdminAuthorized` for the HTTP path so admin
6448
- * streaming is opt-in rather than exposed by default.
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-Cx9HUPJj.mjs';
11
- export { materializeExternalRows, readExternalSourceBaseline, runExternalSourceTick } from './packem_shared/materializeExternalRows-CTqZisSC.mjs';
12
- export { isSourceDue, liftSourceId, pullExternalSourceTick } from './packem_shared/isSourceDue-CYkt7Ru8.mjs';
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-BYlSGY0N.mjs';
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-BA8QOChj.mjs';
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-D57CJaT9.mjs';
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-MydiuScU.mjs';
40
- export { s as subscriptionListDeltas } from './packem_shared/subscription-delivery-CWigSEr3.mjs';
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 stripLeading = (sql) => sql.replace(LEADING_NOISE, "");
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, a as awaitWsDrain, t as trySendFrame, d as decodeWire, s as subscriptionListDeltas, b as sendDeltaFrames } from './subscription-delivery-CWigSEr3.mjs';
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-BYlSGY0N.mjs';
16
- import { stableStringify } from './stableStringify-MydiuScU.mjs';
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-D57CJaT9.mjs';
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) => stableStringify({ args: args ?? {}, name });
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: entry.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: entry.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 = stableStringify(base.effectiveWhere);
863
- const baseColumns = stableStringify(base.columns);
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 && stableStringify(resolved.effectiveWhere) === baseWhere && stableStringify(resolved.columns) === baseColumns;
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
- args: shape.args ?? {},
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
- const status = this.subscribe(ws, envelope.id, envelope.query);
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, envelope.query, functionPath, isAdmin);
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: envelope.shape.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 a token matching `LUNORA_ADMIN_TOKEN`,
6346
- * constant-time compared. Closed (returns `false`) when the admin token is
6347
- * unset, mirroring `isAdminAuthorized` for the HTTP path so admin
6348
- * streaming is opt-in rather than exposed by default.
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
- return supplied !== void 0 && constantTimeEqual(supplied, adminToken);
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: this.isAdminSocket(request),
6536
+ admin,
6413
6537
  connectionId: crypto.randomUUID(),
6414
6538
  subs: {},
6415
6539
  ...expiresAt === void 0 ? {} : { expiresAt },
@@ -1,5 +1,6 @@
1
- import { stableStringify } from './stableStringify-MydiuScU.mjs';
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}:${stableStringify(args)}`;
231
+ const reactiveCacheKey = (functionPath, args, identity) => `${identity ?? "\0anon"}\0${functionPath}:${stableWireKey(args)}`;
231
232
 
232
- export { ReactiveCache, reactiveCacheKey, stableStringify };
233
+ export { ReactiveCache, reactiveCacheKey, stableWireKey };
@@ -1,4 +1,4 @@
1
- import { stableStringify } from './stableStringify-MydiuScU.mjs';
1
+ import { stableStringify } from './stableStringify-mC40mZts.mjs';
2
2
 
3
3
  const projectExternalSourceRow = (row, columns) => {
4
4
  const projected = { _id: row._id };
@@ -1,5 +1,5 @@
1
1
  import { LunoraError } from '@lunora/errors';
2
- import { runExternalSourceTick } from './materializeExternalRows-CTqZisSC.mjs';
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-Cx9HUPJj.mjs';
4
- import { stableStringify } from './stableStringify-MydiuScU.mjs';
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 (query/subscription/shape args) — pass it as a string");
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 (query/subscription/shape args) — only plain objects, arrays, and JSON primitives are supported`
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,6 @@
1
+ import { stableStringify } from './stableStringify-mC40mZts.mjs';
2
+ import { e as encodeWire } from './wire-codec-CzQc1pvf.mjs';
3
+
4
+ const stableWireKey = (value) => stableStringify(encodeWire(value));
5
+
6
+ export { stableWireKey };
@@ -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
- const ROW_ID_FIELD = "_id";
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.30",
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.4",
50
- "@lunora/fingerprint": "1.0.0-alpha.1",
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';