@lunora/do 1.0.0-alpha.7 → 1.0.0-alpha.8

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
@@ -596,6 +596,7 @@ declare const rankTableName: (table: string, indexName: string) => string;
596
596
  * - `sortValues[i]` === `serializeSqlValue(doc[index.sortBy[i].field])` — the same transform `syncRankIndexEntry` applies to the stored `__sort_k<i>__` column, so the comparison is byte-for-byte (and JSON-safe for the cross-shard wire) regardless of which shard owns the row. `rankBefore` re-applies it idempotently, so a direct caller passing raw values still works.
597
597
  * - `rowId` === `doc._id`, the `__id__` tiebreak.
598
598
  */
599
+ declare const stableStringify: (value: unknown) => string;
599
600
  /** A single memoized result, the deps it read, and any active subscribers. */
600
601
  interface CacheEntry {
601
602
  /** Approximate serialized size of `result`, charged against `maxBytes`. */
@@ -728,16 +729,6 @@ declare class ReactiveCache {
728
729
  private evict;
729
730
  }
730
731
  /**
731
- * Stable, sorted JSON encoding of `args` for use in a cache key. Object keys
732
- * are visited in lexical order at every depth so `{ a: 1, b: 2 }` and
733
- * `{ b: 2, a: 1 }` hash to the same string. Arrays preserve their order
734
- * (the index IS the key). `undefined` values are skipped at the object level
735
- * so `{ a: undefined }` collides with `{}` — matches Convex behavior and
736
- * avoids spurious cache misses on optional args. Inside arrays `undefined`
737
- * encodes as `null` to keep positional semantics.
738
- */
739
- declare const stableStringify: (value: unknown) => string;
740
- /**
741
732
  * Compose a cache key from a function path, a stably-encoded args object, and
742
733
  * the caller's identity discriminator. Exported so the wiring layer and tests
743
734
  * build identical keys without each side reinventing the format.
@@ -2262,6 +2253,19 @@ declare const ADMIN_FUNCTION_PREFIX = "__lunora_admin__:";
2262
2253
  */
2263
2254
  declare const RELATION_FUNCTION_PREFIX = "__lunora_relation__:";
2264
2255
  /**
2256
+ * Reserved `functionPath` prefix for live feature-flag reads. The React client's
2257
+ * `useFlag`/`useFlags` subscribe to `__lunora_flags__:eval` over the same WS
2258
+ * channel as a user query; `ShardDO` intercepts it before user dispatch and
2259
+ * serves it from the codegen-overridden flag-subscription read hook, which
2260
+ * evaluates the flag through the app's OpenFeature provider under the socket's
2261
+ * verified identity. Like the other reserved prefixes it is NOT admin-gated (a
2262
+ * flag read is public, scoped to the subscriber's own targeting context), and
2263
+ * the `__lunora_` namespace is reserved so a real `<file>:<function>` can't
2264
+ * collide. Re-evaluated on every write-flush so values stay live within a
2265
+ * session (provider-side flips with no intervening write surface on reconnect).
2266
+ */
2267
+ declare const FLAGS_FUNCTION_PREFIX = "__lunora_flags__:";
2268
+ /**
2265
2269
  * Fully-qualified reserved paths the data browser invokes. The
2266
2270
  * `__lunora_admin__:` prefix is spelled out inline rather than interpolated so
2267
2271
  * the values stay emittable under `--isolatedDeclarations`.
@@ -2292,6 +2296,7 @@ declare const ADMIN_FUNCTIONS: {
2292
2296
  readonly getSettings: "__lunora_admin__:getSettings";
2293
2297
  readonly getWorkflowInstanceStatus: "__lunora_admin__:getWorkflowInstanceStatus";
2294
2298
  readonly importShard: "__lunora_admin__:importShard";
2299
+ readonly listFlags: "__lunora_admin__:listFlags";
2295
2300
  readonly listQueues: "__lunora_admin__:listQueues";
2296
2301
  readonly listTables: "__lunora_admin__:listTables";
2297
2302
  readonly listWorkflows: "__lunora_admin__:listWorkflows";
@@ -2572,6 +2577,8 @@ interface StorageRulesResult {
2572
2577
  * package's tests and the studio's fails the build if the two key sets diverge.
2573
2578
  */
2574
2579
  interface StudioFeaturesResult {
2580
+ /** `@lunora/flags` / `ctx.flags` is used, or it is a declared dependency. */
2581
+ flags: boolean;
2575
2582
  /** `@lunora/mail` is imported by a `lunora/` source or a declared dependency. */
2576
2583
  mail: boolean;
2577
2584
  /** `@lunora/payment` is used (import or `ctx.payments`) or a declared dependency. */
@@ -2588,6 +2595,40 @@ interface StudioFeaturesResult {
2588
2595
  workflows: boolean;
2589
2596
  }
2590
2597
  /**
2598
+ * One feature flag evaluated under a supplied targeting context, surfaced by
2599
+ * `__lunora_admin__:listFlags` for the studio's read-only Flags page. The `key`
2600
+ * and `type` are statically discovered by `@lunora/codegen` from the app's
2601
+ * `ctx.flags.<type>("key", …)` reads; `value`/`reason`/`variant`/`errorCode`
2602
+ * come from the live OpenFeature evaluation (the codegen subclass overrides the
2603
+ * base `evaluateFlags` hook). `value` is the resolved flag value as JSON.
2604
+ */
2605
+ interface FlagEvaluation {
2606
+ /** OpenFeature `errorCode` when the evaluation failed (the value falls back to the default). */
2607
+ errorCode?: string;
2608
+ /** The discovered flag key (the first argument of a `ctx.flags.<type>(...)` read). */
2609
+ key: string;
2610
+ /** OpenFeature `reason` for the resolution (`TARGETING_MATCH`, `DEFAULT`, `ERROR`, …). */
2611
+ reason?: string;
2612
+ /** The flag's value type, derived from which `ctx.flags.<type>` method read it. */
2613
+ type: "boolean" | "number" | "object" | "string";
2614
+ /** The resolved value (JSON), or the type default when unconfigured / on error. */
2615
+ value: unknown;
2616
+ /** OpenFeature `variant` identifier when the provider reports one. */
2617
+ variant?: string;
2618
+ }
2619
+ /**
2620
+ * Payload of a `__lunora_admin__:listFlags` call: every statically-discovered
2621
+ * flag evaluated under the supplied targeting context. `configured` is `false`
2622
+ * when the app wires no `@lunora/flags` provider (the base hook), so the studio
2623
+ * can distinguish "no flags configured" from "configured but zero flags read".
2624
+ */
2625
+ interface FlagsResult {
2626
+ /** `true` when an `@lunora/flags` provider is wired (the codegen override ran). */
2627
+ configured: boolean;
2628
+ /** Each discovered flag evaluated under the request's targeting context. */
2629
+ flags: FlagEvaluation[];
2630
+ }
2631
+ /**
2591
2632
  * One declared Cloudflare Workflow, surfaced by `__lunora_admin__:listWorkflows`
2592
2633
  * for the studio's Workflows page. Statically discovered by `@lunora/codegen`
2593
2634
  * from `lunora/workflows.ts` (the codegen subclass overrides the base hook);
@@ -4520,6 +4561,26 @@ declare abstract class ShardDO {
4520
4561
  */
4521
4562
  protected studioFeatures(): StudioFeaturesResult;
4522
4563
  /**
4564
+ * Evaluate every statically-discovered feature flag under `context` for the
4565
+ * studio's read-only Flags page (`__lunora_admin__:listFlags`). The flag keys
4566
+ * + value types are discovered by `@lunora/codegen` from the app's
4567
+ * `ctx.flags.<type>("key", …)` reads and evaluated through the configured
4568
+ * `@lunora/flags` provider — work only the codegen subclass can do, so it
4569
+ * overrides this. The base class wires no provider and reports
4570
+ * `configured: false` with zero flags (an un-generated `ShardDO` has none).
4571
+ */
4572
+ protected evaluateFlags(_context?: Record<string, unknown>): Promise<FlagsResult>;
4573
+ /**
4574
+ * Serve one reserved {@link FLAGS_FUNCTION_PREFIX} live flag read for the
4575
+ * React client's `useFlag`/`useFlags`. `functionPath` carries the flag key +
4576
+ * type and `args` the per-subscriber targeting context; the codegen subclass
4577
+ * overrides this to evaluate the flag through the app's `@lunora/flags`
4578
+ * provider under `identity` and return the resolved value. The base class
4579
+ * wires no provider, so it returns `null` — `resolveReactiveOutcome` reads
4580
+ * `null` as "nothing to deliver" and the subscriber keeps its default.
4581
+ */
4582
+ protected runFlagSubscriptionRead(_functionPath: string, _arguments: Record<string, unknown>, _identity?: SubscriptionIdentity): Promise<unknown>;
4583
+ /**
4523
4584
  * The Cloudflare Queues declared by this app, surfaced via
4524
4585
  * `__lunora_admin__:listQueues` for the studio's Queues page. Queues are NOT
4525
4586
  * Durable Objects and hold no shard state, so this is pure declaration
@@ -5031,6 +5092,16 @@ declare abstract class ShardDO {
5031
5092
  */
5032
5093
  private handleGetWorkflowInstanceStatus;
5033
5094
  /**
5095
+ * Serve `__lunora_admin__:listFlags` — the studio's read-only Flags page.
5096
+ * Evaluates every statically-discovered feature flag under an optional
5097
+ * `args.context` targeting context (the studio's editable context editor)
5098
+ * via the {@link evaluateFlags} hook, which the codegen subclass overrides
5099
+ * with live OpenFeature evaluation. Read-only: a flag lookup mutates no shard
5100
+ * state, so nothing is flushed or audited. Admin-gated by `handleAdminRpc`'s
5101
+ * caller.
5102
+ */
5103
+ private handleListFlags;
5104
+ /**
5034
5105
  * Run `run()` with the per-request identity pinned to (`userId`, `identity`),
5035
5106
  * then restore the prior values in a `finally` (even if `run()` throws), so the
5036
5107
  * forced identity can never leak into a later dispatch on this DO instance. The
@@ -5290,6 +5361,16 @@ declare abstract class ShardDO {
5290
5361
  */
5291
5362
  private executeAdminSubscription;
5292
5363
  /**
5364
+ * Resolve one subscription (seed or refresh) to its {@link SubscriptionOutcome}
5365
+ * by routing the `functionPath` to the right read path — shared by
5366
+ * {@link seedSubscription} and {@link refreshSubscriptions} so both branch
5367
+ * identically:
5368
+ * - `__lunora_admin__:*` → {@link executeAdminSubscription} (raw SQLite read).
5369
+ * - {@link FLAGS_FUNCTION_PREFIX} → {@link runFlagSubscriptionRead} (the codegen subclass evaluates the flag through the configured provider). The value isn't bound to any table, so it is tagged with the {@link ADMIN_WILDCARD} dep — re-evaluated on every write-flush so a live `useFlag` stays current within a session. A `null` read means "nothing to deliver" (no provider, or a flag that resolved to `null`).
5370
+ * - everything else → {@link executeSubscription} (the user query, under the socket's own by-value identity).
5371
+ */
5372
+ private resolveReactiveOutcome;
5373
+ /**
5293
5374
  * Constant-time bearer check against `env.LUNORA_ADMIN_TOKEN`. Returns
5294
5375
  * `false` (closed) when the token is unset so admin introspection is
5295
5376
  * opt-in rather than exposed by default.
@@ -5718,4 +5799,4 @@ interface WhereSqlStrategy {
5718
5799
  * `undefined` when the input imposes no constraint (empty `where`).
5719
5800
  */
5720
5801
  declare const compileWhereSql: (where: WhereInput | undefined, strategy: WhereSqlStrategy) => SQL | undefined;
5721
- 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, 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 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 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 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, ShardDO, type ShardDOOptions, type ShardDOState, type ShardRankPageResult, ShardRegistryDO, type SocketAttachment, type SortDirection, 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, assertValidClientId, backfillAggregateIndexes, backfillRankIndexes, buildFtsMatch, buildSecurityAudit, buildSeekWhere, clearCapturedMail, coerceAggregateNumber, compileWhereSql, containsRelationPredicate, createDependencyTracker, createShardCtxDb, createSystemReader, decodeCursor, depKey, encodeAggregateKey, encodeCursor, encodePartitionKey, ensureAuthMetricsTables, ensureFunctionMetricsTables, ensureMailTable, exportShardRows, exportShardTable, facetColumn, foldAggregateTally, ftsTableName, guardWriter, hasTrigger, importShardRows, isRelationPredicate, listTables, matchesRankStaticWhere, matchesStaticWhere, mergeWhere, normalizeCountArgument, normalizeIdStructurally, normalizeOrderKeys, parseExportShardArgs, parseImportShardArgs, planAggregateLookup, rankTableName, reactiveCacheKey, readAggregateValue, readAuthMetrics, readBookmark, readCapturedMail, readCdcChanges, readFunctionMetricBuckets, readFunctionMetricIndexHits, readFunctionMetrics, readFunctionMetricsTotals, readMigrationStatus, readTablePage, recordAuthEvent, recordCapturedMail, recordFunctionMetric, renderSql, resolveRankPartition, resolveRelationPredicates, resolveWith, runDataMigration, runReadonlySql, runRowValidators, runShardMigrations, runTriggers, scoreDocument, selectExportTables, selectIndexForAggregate, selectIndexForCount, selectIndexForGroupBy, selectMatchingIds, serveRelationFanout, softDeleteScope, sortColumnName, stableStringify, stringifySearchText, subscriptionListDeltas, throwingScheduler, tokenizeSearch, trimCdcChanges, validateImportRow };
5802
+ 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, 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 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 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, ShardDO, type ShardDOOptions, type ShardDOState, type ShardRankPageResult, ShardRegistryDO, type SocketAttachment, type SortDirection, 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, assertValidClientId, backfillAggregateIndexes, backfillRankIndexes, buildFtsMatch, buildSecurityAudit, buildSeekWhere, clearCapturedMail, coerceAggregateNumber, compileWhereSql, containsRelationPredicate, createDependencyTracker, createShardCtxDb, createSystemReader, decodeCursor, depKey, encodeAggregateKey, encodeCursor, encodePartitionKey, ensureAuthMetricsTables, ensureFunctionMetricsTables, ensureMailTable, exportShardRows, exportShardTable, facetColumn, foldAggregateTally, ftsTableName, guardWriter, hasTrigger, importShardRows, isRelationPredicate, listTables, matchesRankStaticWhere, matchesStaticWhere, mergeWhere, normalizeCountArgument, normalizeIdStructurally, normalizeOrderKeys, parseExportShardArgs, parseImportShardArgs, planAggregateLookup, rankTableName, reactiveCacheKey, readAggregateValue, readAuthMetrics, readBookmark, readCapturedMail, readCdcChanges, readFunctionMetricBuckets, readFunctionMetricIndexHits, readFunctionMetrics, readFunctionMetricsTotals, readMigrationStatus, readTablePage, recordAuthEvent, recordCapturedMail, recordFunctionMetric, renderSql, resolveRankPartition, resolveRelationPredicates, resolveWith, runDataMigration, runReadonlySql, runRowValidators, runShardMigrations, runTriggers, scoreDocument, selectExportTables, selectIndexForAggregate, selectIndexForCount, selectIndexForGroupBy, selectMatchingIds, serveRelationFanout, softDeleteScope, sortColumnName, stableStringify, stringifySearchText, subscriptionListDeltas, throwingScheduler, tokenizeSearch, trimCdcChanges, validateImportRow };
package/dist/index.d.ts CHANGED
@@ -596,6 +596,7 @@ declare const rankTableName: (table: string, indexName: string) => string;
596
596
  * - `sortValues[i]` === `serializeSqlValue(doc[index.sortBy[i].field])` — the same transform `syncRankIndexEntry` applies to the stored `__sort_k&lt;i>__` column, so the comparison is byte-for-byte (and JSON-safe for the cross-shard wire) regardless of which shard owns the row. `rankBefore` re-applies it idempotently, so a direct caller passing raw values still works.
597
597
  * - `rowId` === `doc._id`, the `__id__` tiebreak.
598
598
  */
599
+ declare const stableStringify: (value: unknown) => string;
599
600
  /** A single memoized result, the deps it read, and any active subscribers. */
600
601
  interface CacheEntry {
601
602
  /** Approximate serialized size of `result`, charged against `maxBytes`. */
@@ -728,16 +729,6 @@ declare class ReactiveCache {
728
729
  private evict;
729
730
  }
730
731
  /**
731
- * Stable, sorted JSON encoding of `args` for use in a cache key. Object keys
732
- * are visited in lexical order at every depth so `{ a: 1, b: 2 }` and
733
- * `{ b: 2, a: 1 }` hash to the same string. Arrays preserve their order
734
- * (the index IS the key). `undefined` values are skipped at the object level
735
- * so `{ a: undefined }` collides with `{}` — matches Convex behavior and
736
- * avoids spurious cache misses on optional args. Inside arrays `undefined`
737
- * encodes as `null` to keep positional semantics.
738
- */
739
- declare const stableStringify: (value: unknown) => string;
740
- /**
741
732
  * Compose a cache key from a function path, a stably-encoded args object, and
742
733
  * the caller's identity discriminator. Exported so the wiring layer and tests
743
734
  * build identical keys without each side reinventing the format.
@@ -2262,6 +2253,19 @@ declare const ADMIN_FUNCTION_PREFIX = "__lunora_admin__:";
2262
2253
  */
2263
2254
  declare const RELATION_FUNCTION_PREFIX = "__lunora_relation__:";
2264
2255
  /**
2256
+ * Reserved `functionPath` prefix for live feature-flag reads. The React client's
2257
+ * `useFlag`/`useFlags` subscribe to `__lunora_flags__:eval` over the same WS
2258
+ * channel as a user query; `ShardDO` intercepts it before user dispatch and
2259
+ * serves it from the codegen-overridden flag-subscription read hook, which
2260
+ * evaluates the flag through the app's OpenFeature provider under the socket's
2261
+ * verified identity. Like the other reserved prefixes it is NOT admin-gated (a
2262
+ * flag read is public, scoped to the subscriber's own targeting context), and
2263
+ * the `__lunora_` namespace is reserved so a real `&lt;file>:&lt;function>` can't
2264
+ * collide. Re-evaluated on every write-flush so values stay live within a
2265
+ * session (provider-side flips with no intervening write surface on reconnect).
2266
+ */
2267
+ declare const FLAGS_FUNCTION_PREFIX = "__lunora_flags__:";
2268
+ /**
2265
2269
  * Fully-qualified reserved paths the data browser invokes. The
2266
2270
  * `__lunora_admin__:` prefix is spelled out inline rather than interpolated so
2267
2271
  * the values stay emittable under `--isolatedDeclarations`.
@@ -2292,6 +2296,7 @@ declare const ADMIN_FUNCTIONS: {
2292
2296
  readonly getSettings: "__lunora_admin__:getSettings";
2293
2297
  readonly getWorkflowInstanceStatus: "__lunora_admin__:getWorkflowInstanceStatus";
2294
2298
  readonly importShard: "__lunora_admin__:importShard";
2299
+ readonly listFlags: "__lunora_admin__:listFlags";
2295
2300
  readonly listQueues: "__lunora_admin__:listQueues";
2296
2301
  readonly listTables: "__lunora_admin__:listTables";
2297
2302
  readonly listWorkflows: "__lunora_admin__:listWorkflows";
@@ -2572,6 +2577,8 @@ interface StorageRulesResult {
2572
2577
  * package's tests and the studio's fails the build if the two key sets diverge.
2573
2578
  */
2574
2579
  interface StudioFeaturesResult {
2580
+ /** `@lunora/flags` / `ctx.flags` is used, or it is a declared dependency. */
2581
+ flags: boolean;
2575
2582
  /** `@lunora/mail` is imported by a `lunora/` source or a declared dependency. */
2576
2583
  mail: boolean;
2577
2584
  /** `@lunora/payment` is used (import or `ctx.payments`) or a declared dependency. */
@@ -2588,6 +2595,40 @@ interface StudioFeaturesResult {
2588
2595
  workflows: boolean;
2589
2596
  }
2590
2597
  /**
2598
+ * One feature flag evaluated under a supplied targeting context, surfaced by
2599
+ * `__lunora_admin__:listFlags` for the studio's read-only Flags page. The `key`
2600
+ * and `type` are statically discovered by `@lunora/codegen` from the app's
2601
+ * `ctx.flags.&lt;type>("key", …)` reads; `value`/`reason`/`variant`/`errorCode`
2602
+ * come from the live OpenFeature evaluation (the codegen subclass overrides the
2603
+ * base `evaluateFlags` hook). `value` is the resolved flag value as JSON.
2604
+ */
2605
+ interface FlagEvaluation {
2606
+ /** OpenFeature `errorCode` when the evaluation failed (the value falls back to the default). */
2607
+ errorCode?: string;
2608
+ /** The discovered flag key (the first argument of a `ctx.flags.&lt;type>(...)` read). */
2609
+ key: string;
2610
+ /** OpenFeature `reason` for the resolution (`TARGETING_MATCH`, `DEFAULT`, `ERROR`, …). */
2611
+ reason?: string;
2612
+ /** The flag's value type, derived from which `ctx.flags.&lt;type>` method read it. */
2613
+ type: "boolean" | "number" | "object" | "string";
2614
+ /** The resolved value (JSON), or the type default when unconfigured / on error. */
2615
+ value: unknown;
2616
+ /** OpenFeature `variant` identifier when the provider reports one. */
2617
+ variant?: string;
2618
+ }
2619
+ /**
2620
+ * Payload of a `__lunora_admin__:listFlags` call: every statically-discovered
2621
+ * flag evaluated under the supplied targeting context. `configured` is `false`
2622
+ * when the app wires no `@lunora/flags` provider (the base hook), so the studio
2623
+ * can distinguish "no flags configured" from "configured but zero flags read".
2624
+ */
2625
+ interface FlagsResult {
2626
+ /** `true` when an `@lunora/flags` provider is wired (the codegen override ran). */
2627
+ configured: boolean;
2628
+ /** Each discovered flag evaluated under the request's targeting context. */
2629
+ flags: FlagEvaluation[];
2630
+ }
2631
+ /**
2591
2632
  * One declared Cloudflare Workflow, surfaced by `__lunora_admin__:listWorkflows`
2592
2633
  * for the studio's Workflows page. Statically discovered by `@lunora/codegen`
2593
2634
  * from `lunora/workflows.ts` (the codegen subclass overrides the base hook);
@@ -4520,6 +4561,26 @@ declare abstract class ShardDO {
4520
4561
  */
4521
4562
  protected studioFeatures(): StudioFeaturesResult;
4522
4563
  /**
4564
+ * Evaluate every statically-discovered feature flag under `context` for the
4565
+ * studio's read-only Flags page (`__lunora_admin__:listFlags`). The flag keys
4566
+ * + value types are discovered by `@lunora/codegen` from the app's
4567
+ * `ctx.flags.&lt;type>("key", …)` reads and evaluated through the configured
4568
+ * `@lunora/flags` provider — work only the codegen subclass can do, so it
4569
+ * overrides this. The base class wires no provider and reports
4570
+ * `configured: false` with zero flags (an un-generated `ShardDO` has none).
4571
+ */
4572
+ protected evaluateFlags(_context?: Record<string, unknown>): Promise<FlagsResult>;
4573
+ /**
4574
+ * Serve one reserved {@link FLAGS_FUNCTION_PREFIX} live flag read for the
4575
+ * React client's `useFlag`/`useFlags`. `functionPath` carries the flag key +
4576
+ * type and `args` the per-subscriber targeting context; the codegen subclass
4577
+ * overrides this to evaluate the flag through the app's `@lunora/flags`
4578
+ * provider under `identity` and return the resolved value. The base class
4579
+ * wires no provider, so it returns `null` — `resolveReactiveOutcome` reads
4580
+ * `null` as "nothing to deliver" and the subscriber keeps its default.
4581
+ */
4582
+ protected runFlagSubscriptionRead(_functionPath: string, _arguments: Record<string, unknown>, _identity?: SubscriptionIdentity): Promise<unknown>;
4583
+ /**
4523
4584
  * The Cloudflare Queues declared by this app, surfaced via
4524
4585
  * `__lunora_admin__:listQueues` for the studio's Queues page. Queues are NOT
4525
4586
  * Durable Objects and hold no shard state, so this is pure declaration
@@ -5031,6 +5092,16 @@ declare abstract class ShardDO {
5031
5092
  */
5032
5093
  private handleGetWorkflowInstanceStatus;
5033
5094
  /**
5095
+ * Serve `__lunora_admin__:listFlags` — the studio's read-only Flags page.
5096
+ * Evaluates every statically-discovered feature flag under an optional
5097
+ * `args.context` targeting context (the studio's editable context editor)
5098
+ * via the {@link evaluateFlags} hook, which the codegen subclass overrides
5099
+ * with live OpenFeature evaluation. Read-only: a flag lookup mutates no shard
5100
+ * state, so nothing is flushed or audited. Admin-gated by `handleAdminRpc`'s
5101
+ * caller.
5102
+ */
5103
+ private handleListFlags;
5104
+ /**
5034
5105
  * Run `run()` with the per-request identity pinned to (`userId`, `identity`),
5035
5106
  * then restore the prior values in a `finally` (even if `run()` throws), so the
5036
5107
  * forced identity can never leak into a later dispatch on this DO instance. The
@@ -5290,6 +5361,16 @@ declare abstract class ShardDO {
5290
5361
  */
5291
5362
  private executeAdminSubscription;
5292
5363
  /**
5364
+ * Resolve one subscription (seed or refresh) to its {@link SubscriptionOutcome}
5365
+ * by routing the `functionPath` to the right read path — shared by
5366
+ * {@link seedSubscription} and {@link refreshSubscriptions} so both branch
5367
+ * identically:
5368
+ * - `__lunora_admin__:*` → {@link executeAdminSubscription} (raw SQLite read).
5369
+ * - {@link FLAGS_FUNCTION_PREFIX} → {@link runFlagSubscriptionRead} (the codegen subclass evaluates the flag through the configured provider). The value isn't bound to any table, so it is tagged with the {@link ADMIN_WILDCARD} dep — re-evaluated on every write-flush so a live `useFlag` stays current within a session. A `null` read means "nothing to deliver" (no provider, or a flag that resolved to `null`).
5370
+ * - everything else → {@link executeSubscription} (the user query, under the socket's own by-value identity).
5371
+ */
5372
+ private resolveReactiveOutcome;
5373
+ /**
5293
5374
  * Constant-time bearer check against `env.LUNORA_ADMIN_TOKEN`. Returns
5294
5375
  * `false` (closed) when the token is unset so admin introspection is
5295
5376
  * opt-in rather than exposed by default.
@@ -5718,4 +5799,4 @@ interface WhereSqlStrategy {
5718
5799
  * `undefined` when the input imposes no constraint (empty `where`).
5719
5800
  */
5720
5801
  declare const compileWhereSql: (where: WhereInput | undefined, strategy: WhereSqlStrategy) => SQL | undefined;
5721
- 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, 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 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 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 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, ShardDO, type ShardDOOptions, type ShardDOState, type ShardRankPageResult, ShardRegistryDO, type SocketAttachment, type SortDirection, 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, assertValidClientId, backfillAggregateIndexes, backfillRankIndexes, buildFtsMatch, buildSecurityAudit, buildSeekWhere, clearCapturedMail, coerceAggregateNumber, compileWhereSql, containsRelationPredicate, createDependencyTracker, createShardCtxDb, createSystemReader, decodeCursor, depKey, encodeAggregateKey, encodeCursor, encodePartitionKey, ensureAuthMetricsTables, ensureFunctionMetricsTables, ensureMailTable, exportShardRows, exportShardTable, facetColumn, foldAggregateTally, ftsTableName, guardWriter, hasTrigger, importShardRows, isRelationPredicate, listTables, matchesRankStaticWhere, matchesStaticWhere, mergeWhere, normalizeCountArgument, normalizeIdStructurally, normalizeOrderKeys, parseExportShardArgs, parseImportShardArgs, planAggregateLookup, rankTableName, reactiveCacheKey, readAggregateValue, readAuthMetrics, readBookmark, readCapturedMail, readCdcChanges, readFunctionMetricBuckets, readFunctionMetricIndexHits, readFunctionMetrics, readFunctionMetricsTotals, readMigrationStatus, readTablePage, recordAuthEvent, recordCapturedMail, recordFunctionMetric, renderSql, resolveRankPartition, resolveRelationPredicates, resolveWith, runDataMigration, runReadonlySql, runRowValidators, runShardMigrations, runTriggers, scoreDocument, selectExportTables, selectIndexForAggregate, selectIndexForCount, selectIndexForGroupBy, selectMatchingIds, serveRelationFanout, softDeleteScope, sortColumnName, stableStringify, stringifySearchText, subscriptionListDeltas, throwingScheduler, tokenizeSearch, trimCdcChanges, validateImportRow };
5802
+ 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, 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 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 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, ShardDO, type ShardDOOptions, type ShardDOState, type ShardRankPageResult, ShardRegistryDO, type SocketAttachment, type SortDirection, 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, assertValidClientId, backfillAggregateIndexes, backfillRankIndexes, buildFtsMatch, buildSecurityAudit, buildSeekWhere, clearCapturedMail, coerceAggregateNumber, compileWhereSql, containsRelationPredicate, createDependencyTracker, createShardCtxDb, createSystemReader, decodeCursor, depKey, encodeAggregateKey, encodeCursor, encodePartitionKey, ensureAuthMetricsTables, ensureFunctionMetricsTables, ensureMailTable, exportShardRows, exportShardTable, facetColumn, foldAggregateTally, ftsTableName, guardWriter, hasTrigger, importShardRows, isRelationPredicate, listTables, matchesRankStaticWhere, matchesStaticWhere, mergeWhere, normalizeCountArgument, normalizeIdStructurally, normalizeOrderKeys, parseExportShardArgs, parseImportShardArgs, planAggregateLookup, rankTableName, reactiveCacheKey, readAggregateValue, readAuthMetrics, readBookmark, readCapturedMail, readCdcChanges, readFunctionMetricBuckets, readFunctionMetricIndexHits, readFunctionMetrics, readFunctionMetricsTotals, readMigrationStatus, readTablePage, recordAuthEvent, recordCapturedMail, recordFunctionMetric, renderSql, resolveRankPartition, resolveRelationPredicates, resolveWith, runDataMigration, runReadonlySql, runRowValidators, runShardMigrations, runTriggers, scoreDocument, selectExportTables, selectIndexForAggregate, selectIndexForCount, selectIndexForGroupBy, selectMatchingIds, serveRelationFanout, softDeleteScope, sortColumnName, stableStringify, stringifySearchText, subscriptionListDeltas, throwingScheduler, tokenizeSearch, trimCdcChanges, validateImportRow };
package/dist/index.mjs CHANGED
@@ -8,22 +8,22 @@ export { DATA_MIGRATION_STATE_TABLE, readMigrationStatus, runDataMigration } fro
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
10
  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';
11
- export { ADMIN_FUNCTIONS, ADMIN_FUNCTION_PREFIX, RELATION_FUNCTION_PREFIX, facetColumn, listTables, readTablePage, selectMatchingIds } from './packem_shared/ADMIN_FUNCTIONS-CHcC8fKV.mjs';
11
+ export { ADMIN_FUNCTIONS, ADMIN_FUNCTION_PREFIX, FLAGS_FUNCTION_PREFIX, RELATION_FUNCTION_PREFIX, facetColumn, listTables, readTablePage, selectMatchingIds } from './packem_shared/ADMIN_FUNCTIONS-D_UiYJFk.mjs';
12
12
  export { LogBuffer } from './packem_shared/LogBuffer-B_Ezju_N.mjs';
13
13
  export { MAIL_RETENTION, MAIL_TABLE, clearCapturedMail, ensureMailTable, readCapturedMail, recordCapturedMail } from './packem_shared/MAIL_RETENTION-CPpgl-dX.mjs';
14
14
  export { default as NotFoundError } from './packem_shared/NotFoundError-CMuMZt81.mjs';
15
15
  export { armRestore, readBookmark } from './packem_shared/armRestore-BJk53Ro8.mjs';
16
16
  export { applySelect, buildSeekWhere, decodeCursor, encodeCursor, normalizeOrderKeys, softDeleteScope } from './packem_shared/applySelect-BvZdFUBT.mjs';
17
17
  export { R as RANK_TIEBREAK, e as encodePartitionKey, m as matchesRankStaticWhere, r as rankTableName, a as resolveRankPartition, s as sortColumnName } from './packem_shared/rank-CrkEIpF4.mjs';
18
- export { ReactiveCache, reactiveCacheKey, stableStringify } from './packem_shared/ReactiveCache-ByVzgH3d.mjs';
19
- export { serveRelationFanout } from './packem_shared/serveRelationFanout-oxaM6_WL.mjs';
18
+ export { ReactiveCache, reactiveCacheKey } from './packem_shared/ReactiveCache-1hDydFyv.mjs';
19
+ export { serveRelationFanout } from './packem_shared/serveRelationFanout-C6lDaesn.mjs';
20
20
  export { DEFAULT_MAX_RELATION_KEYS, assertFlatPredicate, containsRelationPredicate, isRelationPredicate, resolveRelationPredicates } from './packem_shared/DEFAULT_MAX_RELATION_KEYS-Dou2PWdO.mjs';
21
21
  export { applyOnDelete, resolveWith, runRowValidators } from './packem_shared/applyOnDelete-sA7o1CqD.mjs';
22
22
  export { RLS_UNWRAP_SYMBOL, RlsRequiredError, guardWriter } from './packem_shared/RLS_UNWRAP_SYMBOL-EtGQdC9d.mjs';
23
23
  export { buildFtsMatch, ftsTableName, scoreDocument, stringifySearchText, tokenizeSearch } from './packem_shared/buildFtsMatch-BLEMawrp.mjs';
24
24
  export { M as MIN_ADMIN_TOKEN_LENGTH, a as MIN_AUTH_SECRET_LENGTH, b as buildSecurityAudit } from './packem_shared/security-audit-CucgBice.mjs';
25
25
  export { SESSION_DO_TTL_DEFAULT, SessionDO } from './packem_shared/SESSION_DO_TTL_DEFAULT-ilPZsVwu.mjs';
26
- export { ROOT_DO_SIZE_WARN_BYTES, ROOT_SHARD_NAME, ShardDO } from './packem_shared/ROOT_DO_SIZE_WARN_BYTES-2DxWrdla.mjs';
26
+ export { ROOT_DO_SIZE_WARN_BYTES, ROOT_SHARD_NAME, ShardDO } from './packem_shared/ROOT_DO_SIZE_WARN_BYTES-BCz6GIDw.mjs';
27
27
  export { SHARD_REGISTRY_DO_NAME, ShardRegistryDO } from './packem_shared/SHARD_REGISTRY_DO_NAME-BsAbi5Mn.mjs';
28
28
  export { MAX_SQL_ROWS, assertReadonly, runReadonlySql } from './packem_shared/MAX_SQL_ROWS-dDcFE1YZ.mjs';
29
29
  export { createSystemReader } from './packem_shared/createSystemReader-8CzSZP9V.mjs';
@@ -33,4 +33,5 @@ export { compileWhereSql } from './packem_shared/compileWhereSql-CXrhFA3G.mjs';
33
33
  export { CDC_LOG_TABLE, applyCdcChanges, readCdcChanges, trimCdcChanges } from './packem_shared/CDC_LOG_TABLE-Ctdmxmrv.mjs';
34
34
  export { backfillAggregateIndexes, backfillRankIndexes } from './packem_shared/backfillAggregateIndexes-BbVPvciS.mjs';
35
35
  export { runShardMigrations } from './packem_shared/runShardMigrations-PabobOjF.mjs';
36
+ export { stableStringify } from './packem_shared/stableStringify-CyHKJXre.mjs';
36
37
  export { subscriptionListDeltas } from './packem_shared/subscriptionListDeltas-ce84gpwL.mjs';
@@ -1,5 +1,6 @@
1
1
  const ADMIN_FUNCTION_PREFIX = "__lunora_admin__:";
2
2
  const RELATION_FUNCTION_PREFIX = "__lunora_relation__:";
3
+ const FLAGS_FUNCTION_PREFIX = "__lunora_flags__:";
3
4
  const ADMIN_FUNCTIONS = {
4
5
  applyCdc: "__lunora_admin__:applyCdc",
5
6
  cdcSync: "__lunora_admin__:cdcSync",
@@ -27,6 +28,7 @@ const ADMIN_FUNCTIONS = {
27
28
  // eslint-disable-next-line no-secrets/no-secrets -- reserved admin RPC path constant, not a credential
28
29
  getWorkflowInstanceStatus: "__lunora_admin__:getWorkflowInstanceStatus",
29
30
  importShard: "__lunora_admin__:importShard",
31
+ listFlags: "__lunora_admin__:listFlags",
30
32
  listQueues: "__lunora_admin__:listQueues",
31
33
  listTables: "__lunora_admin__:listTables",
32
34
  listWorkflows: "__lunora_admin__:listWorkflows",
@@ -311,4 +313,4 @@ const summarizeSubscriptions = (attachments) => {
311
313
  return { connections, totalConnections: connections.length, totalSubscriptions };
312
314
  };
313
315
 
314
- export { ADMIN_FUNCTIONS, ADMIN_FUNCTION_PREFIX, MAX_PAGE_SIZE, RELATION_FUNCTION_PREFIX, facetColumn, findStorageReferences, listTables, readTablePage, selectMatchingIds, summarizeSubscriptions };
316
+ export { ADMIN_FUNCTIONS, ADMIN_FUNCTION_PREFIX, FLAGS_FUNCTION_PREFIX, MAX_PAGE_SIZE, RELATION_FUNCTION_PREFIX, facetColumn, findStorageReferences, listTables, readTablePage, selectMatchingIds, summarizeSubscriptions };
@@ -4,11 +4,11 @@ import { recordAuthEvent, readAuthMetrics } from './AUTH_METRICS_BUCKETS_TABLE-C
4
4
  import { DATA_MIGRATION_STATE_TABLE, readMigrationStatus } from './DATA_MIGRATION_STATE_TABLE-PTtTiQ7U.mjs';
5
5
  import { SCAN_DEP, createDependencyTracker, tableFromDepKey } from './SCAN_DEP-DLJF8dsj.mjs';
6
6
  import { readFunctionMetricsTotals, readFunctionMetricIndexHits, recordFunctionMetric, mergeScanAttribution, readFunctionMetrics, readFunctionMetricBuckets } from './FUNCTION_METRICS_BUCKETS_TABLE-UDNVD7FS.mjs';
7
- import { ADMIN_FUNCTION_PREFIX, RELATION_FUNCTION_PREFIX, selectMatchingIds, ADMIN_FUNCTIONS, findStorageReferences, listTables, summarizeSubscriptions, readTablePage, facetColumn, MAX_PAGE_SIZE } from './ADMIN_FUNCTIONS-CHcC8fKV.mjs';
7
+ import { ADMIN_FUNCTION_PREFIX, RELATION_FUNCTION_PREFIX, selectMatchingIds, ADMIN_FUNCTIONS, findStorageReferences, listTables, summarizeSubscriptions, readTablePage, facetColumn, FLAGS_FUNCTION_PREFIX, MAX_PAGE_SIZE } from './ADMIN_FUNCTIONS-D_UiYJFk.mjs';
8
8
  import { LogBuffer } from './LogBuffer-B_Ezju_N.mjs';
9
9
  import { recordCapturedMail, clearCapturedMail, readCapturedMail, MAIL_TABLE } from './MAIL_RETENTION-CPpgl-dX.mjs';
10
10
  import { readBookmark, armRestore } from './armRestore-BJk53Ro8.mjs';
11
- import { ReactiveCache, reactiveCacheKey } from './ReactiveCache-ByVzgH3d.mjs';
11
+ import { ReactiveCache, reactiveCacheKey } from './ReactiveCache-1hDydFyv.mjs';
12
12
  import { redact, standardRules } from '@visulima/redact';
13
13
  import { i as isDevEnvironment, c as buildSettings, b as buildSecurityAudit } from './security-audit-CucgBice.mjs';
14
14
  import { runReadonlySql } from './MAX_SQL_ROWS-dDcFE1YZ.mjs';
@@ -1776,7 +1776,33 @@ class ShardDO {
1776
1776
  */
1777
1777
  // eslint-disable-next-line class-methods-use-this -- base-class override hook: the codegen subclass overrides this with the statically-discovered feature flags
1778
1778
  studioFeatures() {
1779
- return { mail: false, payments: false, queues: false, scheduler: false, storage: false, vectors: false, workflows: false };
1779
+ return { flags: false, mail: false, payments: false, queues: false, scheduler: false, storage: false, vectors: false, workflows: false };
1780
+ }
1781
+ /**
1782
+ * Evaluate every statically-discovered feature flag under `context` for the
1783
+ * studio's read-only Flags page (`__lunora_admin__:listFlags`). The flag keys
1784
+ * + value types are discovered by `@lunora/codegen` from the app's
1785
+ * `ctx.flags.&lt;type>("key", …)` reads and evaluated through the configured
1786
+ * `@lunora/flags` provider — work only the codegen subclass can do, so it
1787
+ * overrides this. The base class wires no provider and reports
1788
+ * `configured: false` with zero flags (an un-generated `ShardDO` has none).
1789
+ */
1790
+ // eslint-disable-next-line class-methods-use-this -- base-class override hook: the codegen subclass overrides this with live OpenFeature evaluation over the discovered flag keys
1791
+ evaluateFlags(_context) {
1792
+ return Promise.resolve({ configured: false, flags: [] });
1793
+ }
1794
+ /**
1795
+ * Serve one reserved {@link FLAGS_FUNCTION_PREFIX} live flag read for the
1796
+ * React client's `useFlag`/`useFlags`. `functionPath` carries the flag key +
1797
+ * type and `args` the per-subscriber targeting context; the codegen subclass
1798
+ * overrides this to evaluate the flag through the app's `@lunora/flags`
1799
+ * provider under `identity` and return the resolved value. The base class
1800
+ * wires no provider, so it returns `null` — `resolveReactiveOutcome` reads
1801
+ * `null` as "nothing to deliver" and the subscriber keeps its default.
1802
+ */
1803
+ // eslint-disable-next-line class-methods-use-this -- base-class override hook: the codegen subclass overrides this to evaluate the flag through the configured provider
1804
+ runFlagSubscriptionRead(_functionPath, _arguments, _identity) {
1805
+ return Promise.resolve(null);
1780
1806
  }
1781
1807
  /**
1782
1808
  * The Cloudflare Queues declared by this app, surfaced via
@@ -2728,6 +2754,9 @@ class ShardDO {
2728
2754
  if (functionPath === ADMIN_FUNCTIONS.getWorkflowInstanceStatus) {
2729
2755
  return this.handleGetWorkflowInstanceStatus(args);
2730
2756
  }
2757
+ if (functionPath === ADMIN_FUNCTIONS.listFlags) {
2758
+ return this.handleListFlags(args);
2759
+ }
2731
2760
  return this.handlePitrAdminOp(functionPath, args);
2732
2761
  }
2733
2762
  /**
@@ -2848,6 +2877,21 @@ class ShardDO {
2848
2877
  return jsonResponse({ result }, 200);
2849
2878
  }
2850
2879
  /* eslint-enable no-secrets/no-secrets */
2880
+ /**
2881
+ * Serve `__lunora_admin__:listFlags` — the studio's read-only Flags page.
2882
+ * Evaluates every statically-discovered feature flag under an optional
2883
+ * `args.context` targeting context (the studio's editable context editor)
2884
+ * via the {@link evaluateFlags} hook, which the codegen subclass overrides
2885
+ * with live OpenFeature evaluation. Read-only: a flag lookup mutates no shard
2886
+ * state, so nothing is flushed or audited. Admin-gated by `handleAdminRpc`'s
2887
+ * caller.
2888
+ */
2889
+ async handleListFlags(args) {
2890
+ const rawContext = args.context;
2891
+ const context = typeof rawContext === "object" && rawContext !== null && !Array.isArray(rawContext) ? rawContext : void 0;
2892
+ const result = await this.evaluateFlags(context);
2893
+ return jsonResponse({ result }, 200);
2894
+ }
2851
2895
  /**
2852
2896
  * Run `run()` with the per-request identity pinned to (`userId`, `identity`),
2853
2897
  * then restore the prior values in a `finally` (even if `run()` throws), so the
@@ -3389,6 +3433,25 @@ class ShardDO {
3389
3433
  const read = this.readAdminOp(functionPath, args);
3390
3434
  return read ? { result: read.result, tables: read.tables } : null;
3391
3435
  }
3436
+ /**
3437
+ * Resolve one subscription (seed or refresh) to its {@link SubscriptionOutcome}
3438
+ * by routing the `functionPath` to the right read path — shared by
3439
+ * {@link seedSubscription} and {@link refreshSubscriptions} so both branch
3440
+ * identically:
3441
+ * - `__lunora_admin__:*` → {@link executeAdminSubscription} (raw SQLite read).
3442
+ * - {@link FLAGS_FUNCTION_PREFIX} → {@link runFlagSubscriptionRead} (the codegen subclass evaluates the flag through the configured provider). The value isn't bound to any table, so it is tagged with the {@link ADMIN_WILDCARD} dep — re-evaluated on every write-flush so a live `useFlag` stays current within a session. A `null` read means "nothing to deliver" (no provider, or a flag that resolved to `null`).
3443
+ * - everything else → {@link executeSubscription} (the user query, under the socket's own by-value identity).
3444
+ */
3445
+ async resolveReactiveOutcome(functionPath, args, isAdmin, identity) {
3446
+ if (isAdmin) {
3447
+ return this.executeAdminSubscription(functionPath, args);
3448
+ }
3449
+ if (functionPath.startsWith(FLAGS_FUNCTION_PREFIX)) {
3450
+ const result = await this.runFlagSubscriptionRead(functionPath, args, identity);
3451
+ return result === null ? null : { result, tables: /* @__PURE__ */ new Set([ADMIN_WILDCARD]) };
3452
+ }
3453
+ return this.executeSubscription(functionPath, args, identity);
3454
+ }
3392
3455
  /**
3393
3456
  * Constant-time bearer check against `env.LUNORA_ADMIN_TOKEN`. Returns
3394
3457
  * `false` (closed) when the token is unset so admin introspection is
@@ -3605,15 +3668,10 @@ class ShardDO {
3605
3668
  continue;
3606
3669
  }
3607
3670
  try {
3608
- const outcome = isAdmin ? this.executeAdminSubscription(functionPath, query.args ?? {}) : (
3609
- // Re-run under the socket's OWN verified identity (stamped on the
3610
- // attachment at upgrade, unforgeable by the client) — passed BY
3611
- // VALUE, so this deferred re-run never reads or mutates the shared
3612
- // per-request identity fields. Without it an `rls()` / `ctx.auth`
3613
- // scoped live query would evaluate anonymous and return zero rows.
3614
- // eslint-disable-next-line no-await-in-loop -- subscriptions on a socket re-run sequentially; each shares the single SQLite handle
3615
- await this.executeSubscription(functionPath, query.args ?? {}, { identity: attachment.identity, userId: attachment.userId })
3616
- );
3671
+ const outcome = await this.resolveReactiveOutcome(functionPath, query.args ?? {}, isAdmin, {
3672
+ identity: attachment.identity,
3673
+ userId: attachment.userId
3674
+ });
3617
3675
  if (!outcome) {
3618
3676
  continue;
3619
3677
  }
@@ -3655,7 +3713,10 @@ class ShardDO {
3655
3713
  async seedSubscription(ws, subId, query, functionPath, isAdmin) {
3656
3714
  const seedArgs = query.args ?? {};
3657
3715
  const attachment = this.readAttachment(ws);
3658
- const outcome = isAdmin ? this.executeAdminSubscription(functionPath, seedArgs) : await this.executeSubscription(functionPath, seedArgs, { identity: attachment.identity, userId: attachment.userId });
3716
+ const outcome = await this.resolveReactiveOutcome(functionPath, seedArgs, isAdmin, {
3717
+ identity: attachment.identity,
3718
+ userId: attachment.userId
3719
+ });
3659
3720
  if (!outcome) {
3660
3721
  return;
3661
3722
  }
@@ -1,11 +1,6 @@
1
+ import { stableStringify } from './stableStringify-CyHKJXre.mjs';
1
2
  import { depKey, SCAN_DEP } from './SCAN_DEP-DLJF8dsj.mjs';
2
3
 
3
- const compareKeys = (a, b) => {
4
- if (a < b) {
5
- return -1;
6
- }
7
- return a > b ? 1 : 0;
8
- };
9
4
  const DEFAULT_MAX_ENTRIES = 1e3;
10
5
  const DEFAULT_MAX_BYTES = 4 * 1024 * 1024;
11
6
  const estimateBytes = (value) => {
@@ -232,28 +227,6 @@ class ReactiveCache {
232
227
  }
233
228
  }
234
229
  }
235
- const stableStringify = (value) => {
236
- if (value === void 0) {
237
- return "null";
238
- }
239
- if (value === null || typeof value !== "object") {
240
- return JSON.stringify(value);
241
- }
242
- if (Array.isArray(value)) {
243
- return `[${value.map((item) => stableStringify(item)).join(",")}]`;
244
- }
245
- const record = value;
246
- const keys = Object.keys(record).toSorted(compareKeys);
247
- const parts = [];
248
- for (const key of keys) {
249
- const raw = record[key];
250
- if (raw === void 0) {
251
- continue;
252
- }
253
- parts.push(`${JSON.stringify(key)}:${stableStringify(raw)}`);
254
- }
255
- return `{${parts.join(",")}}`;
256
- };
257
230
  const reactiveCacheKey = (functionPath, args, identity) => `${identity ?? "\0anon"}\0${functionPath}:${stableStringify(args)}`;
258
231
 
259
232
  export { ReactiveCache, reactiveCacheKey, stableStringify };
@@ -1,4 +1,4 @@
1
- import { RELATION_FUNCTION_PREFIX } from './ADMIN_FUNCTIONS-CHcC8fKV.mjs';
1
+ import { RELATION_FUNCTION_PREFIX } from './ADMIN_FUNCTIONS-D_UiYJFk.mjs';
2
2
 
3
3
  const serveRelationFanout = async (schema, database, functionPath, args) => {
4
4
  const table = typeof args["table"] === "string" ? args["table"] : "";
@@ -0,0 +1,30 @@
1
+ const compareKeys = (a, b) => {
2
+ if (a < b) {
3
+ return -1;
4
+ }
5
+ return a > b ? 1 : 0;
6
+ };
7
+ const stableStringify = (value) => {
8
+ if (value === void 0) {
9
+ return "null";
10
+ }
11
+ if (value === null || typeof value !== "object") {
12
+ return JSON.stringify(value);
13
+ }
14
+ if (Array.isArray(value)) {
15
+ return `[${value.map((item) => stableStringify(item)).join(",")}]`;
16
+ }
17
+ const record = value;
18
+ const keys = Object.keys(record).toSorted(compareKeys);
19
+ const parts = [];
20
+ for (const key of keys) {
21
+ const raw = record[key];
22
+ if (raw === void 0) {
23
+ continue;
24
+ }
25
+ parts.push(`${JSON.stringify(key)}:${stableStringify(raw)}`);
26
+ }
27
+ return `{${parts.join(",")}}`;
28
+ };
29
+
30
+ export { stableStringify };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/do",
3
- "version": "1.0.0-alpha.7",
3
+ "version": "1.0.0-alpha.8",
4
4
  "description": "Lunora Durable Objects: ShardDO (SQLite, OCC, hibernated WebSocket subscriptions) and SessionDO",
5
5
  "keywords": [
6
6
  "cloudflare",