@lunora/runtime 1.0.0-alpha.38 → 1.0.0-alpha.39

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
@@ -1560,6 +1560,20 @@ interface LogSinkContext {
1560
1560
  interface LogEvent {
1561
1561
  /** Raw arguments passed to the `ctx.log.*` call, in order. */
1562
1562
  args: unknown[];
1563
+ /**
1564
+ * OTel `LogRecord.eventName` — set when the line was emitted as a **structured
1565
+ * event** via `ctx.log.event(name, fields)` rather than as a human-readable
1566
+ * log line.
1567
+ *
1568
+ * The distinction is the whole point of the Events API: a log line's payload
1569
+ * is its `message` (prose, for a human, unstable), while an event's payload is
1570
+ * its `fields` (a named schema, for a query, stable). A collector that knows
1571
+ * `eventName` can index and aggregate the latter; without it, "how many
1572
+ * checkouts failed" degrades into a substring search over prose.
1573
+ *
1574
+ * Absent for ordinary `ctx.log.*` calls.
1575
+ */
1576
+ eventName?: string;
1563
1577
  /**
1564
1578
  * Structured fields the caller attached (`ctx.log.info(message, fields)` or a
1565
1579
  * bound `ctx.log.with(fields)` child), already normalized to a fresh bag of
@@ -1817,6 +1831,58 @@ interface MetricEvent {
1817
1831
  */
1818
1832
  value: number;
1819
1833
  }
1834
+ /** A JS attribute value the encoder maps onto an OTLP `AnyValue`. */
1835
+ type OtlpAttributeValue = boolean | number | string;
1836
+ /**
1837
+ * A `Resource.attributes` bag — the process-level identity (`service.name`,
1838
+ * `service.version`, `cloud.region`, …) attached to every exported signal.
1839
+ * Lives here rather than in either exporter because both packages build one and
1840
+ * `wrapResource*` consumes it.
1841
+ */
1842
+ type OtlpResourceAttributes = Record<string, OtlpAttributeValue>;
1843
+ /**
1844
+ * The OTel `SpanKind` union, in the spec's own words rather than its wire
1845
+ * numbers, so a call site reads `{ kind: "client" }` instead of `{ kind: 3 }`.
1846
+ *
1847
+ * Kind is not cosmetic: a service map is built from it. A CLIENT span with no
1848
+ * matching SERVER span on the other side is a dropped hop; PRODUCER/CONSUMER is
1849
+ * what makes a queue render as an async edge rather than a synchronous call.
1850
+ * Getting it wrong is why "everything is INTERNAL" traces produce no topology.
1851
+ */
1852
+ type OtlpSpanKind = "client" | "consumer" | "internal" | "producer" | "server";
1853
+ /**
1854
+ * One timestamped occurrence inside a span — OTel's `Span.events`.
1855
+ *
1856
+ * The right shape for something that has a moment but no duration: a retry, a
1857
+ * cache miss, a validation failure, a thrown exception. Modelling those as
1858
+ * near-zero-width child spans clutters the waterfall, and modelling them as
1859
+ * separate log lines loses the "which span was I in" correlation that makes them
1860
+ * useful in the first place.
1861
+ */
1862
+ interface SpanEventPoint {
1863
+ /** Structured attributes, normalized like a span's own. */
1864
+ attributes?: LogFields;
1865
+ /** Event name, e.g. `"exception"` or `"cache.miss"`. */
1866
+ name: string;
1867
+ /** Wall-clock millis when it happened. */
1868
+ ts: number;
1869
+ }
1870
+ /**
1871
+ * A causal reference to a span in ANOTHER trace — OTel's `Span.links`.
1872
+ *
1873
+ * The standard answer to fan-in: a queue consumer processing a batch of 100
1874
+ * messages links to the 100 producing spans rather than parenting to one of them
1875
+ * (arbitrary) or all of them (impossible). The traces stay separately navigable
1876
+ * and the causal edge survives.
1877
+ */
1878
+ interface SpanLink {
1879
+ /** Attributes describing the relationship, e.g. `{ "link.kind": "enqueued_by" }`. */
1880
+ attributes?: LogFields;
1881
+ /** Linked span id (16-hex). */
1882
+ spanId: string;
1883
+ /** Linked trace id (32-hex). */
1884
+ traceId: string;
1885
+ }
1820
1886
  interface SpanEvent {
1821
1887
  /**
1822
1888
  * Structured attributes the caller attached, already normalized to a fresh
@@ -1826,6 +1892,12 @@ interface SpanEvent {
1826
1892
  attributes?: LogFields;
1827
1893
  /** Wall-clock duration of the span body, in milliseconds. */
1828
1894
  durationMs: number;
1895
+ /**
1896
+ * Timestamped occurrences inside the span (see {@link SpanEventPoint}) —
1897
+ * `ctx.trace`'s `span.addEvent(...)` / `span.recordException(...)`. Absent
1898
+ * when the body recorded none.
1899
+ */
1900
+ events?: SpanEventPoint[];
1829
1901
  /**
1830
1902
  * Populated when the span body threw. `type` is the error's constructor name
1831
1903
  * (or its `LunoraError` code); `message` is the human-readable string and may
@@ -1842,6 +1914,14 @@ interface SpanEvent {
1842
1914
  * reuses its context — the same attribution rule `ctx.log` follows.
1843
1915
  */
1844
1916
  functionPath: string;
1917
+ /**
1918
+ * OTel `SpanKind`. Absent means `"internal"` — the overwhelming majority of
1919
+ * `ctx.trace` spans — so the common case costs no bytes on the wire and every
1920
+ * pre-existing recorded span stays valid.
1921
+ */
1922
+ kind?: OtlpSpanKind;
1923
+ /** Causal references to spans in other traces (see {@link SpanLink}). Absent when none. */
1924
+ links?: SpanLink[];
1845
1925
  /** Caller-supplied span name, e.g. `"stripe.charge"`. */
1846
1926
  name: string;
1847
1927
  /** True when the span body returned without throwing. */
@@ -1963,6 +2043,21 @@ type ObservabilitySinkContext = LogSinkContext;
1963
2043
  * events it cares about; the runtime no-ops the others.
1964
2044
  */
1965
2045
  interface ObservabilitySink {
2046
+ /**
2047
+ * Ship anything the sink is holding, now.
2048
+ *
2049
+ * A batching sink (`otlpSink` by default) buffers events and exports them as
2050
+ * one request instead of one request per event. That is only safe because a
2051
+ * Workers isolate can be frozen the instant a response is returned: the
2052
+ * runtime calls this at every invocation boundary — end of `fetch`, `queue`,
2053
+ * `scheduled`, and each Durable Object dispatch — passing the request's
2054
+ * `waitUntil` so the export outlives the response.
2055
+ *
2056
+ * Optional and idempotent: a non-buffering sink simply omits it, and calling
2057
+ * it with an empty buffer is a no-op. A sink must never throw from here; like
2058
+ * every other hook, a telemetry failure must not surface to the caller.
2059
+ */
2060
+ flush?: (context?: ObservabilitySinkContext) => void;
1966
2061
  /**
1967
2062
  * **Opt-in, EXPERIMENTAL, default `false`.** When `true`, each `ctx.trace`
1968
2063
  * span the Durable Object records is ALSO emitted as a Cloudflare **custom
@@ -1993,6 +2088,23 @@ interface ObservabilitySink {
1993
2088
  * `createShardDO` — the DO reads the flag when building `ctx.trace`.
1994
2089
  */
1995
2090
  fuseCloudflareTraces?: boolean;
2091
+ /**
2092
+ * How much detail automatic `ctx.db` instrumentation produces.
2093
+ *
2094
+ * `"summary"` (**default**) — aggregate counters (`db.calls`, `db.duration_ms`,
2095
+ * per-operation counts) folded onto the dispatch's wide event. No extra spans
2096
+ * and no extra log records, so the cost is flat no matter how many queries a
2097
+ * handler makes.
2098
+ *
2099
+ * `"spans"` — one span per database call: the full waterfall, for when you are
2100
+ * chasing a specific slow query. Capped per dispatch so a query loop cannot
2101
+ * bury the trace; truncation is reported as `db.spans_truncated`.
2102
+ *
2103
+ * `"off"` — no database telemetry.
2104
+ *
2105
+ * Applies only when a sink is configured; with none, `ctx.db` is untouched.
2106
+ */
2107
+ instrumentDatabase?: "off" | "spans" | "summary";
1996
2108
  /** Invoked once per `ctx.log.*` call from a function handler. */
1997
2109
  onLog?: (event: LogEvent, context?: ObservabilitySinkContext) => void;
1998
2110
  /**
@@ -2008,6 +2120,20 @@ interface ObservabilitySink {
2008
2120
  * INTERNAL spans a handler creates beneath it.
2009
2121
  */
2010
2122
  onSpan?: (event: SpanEvent, context?: ObservabilitySinkContext) => void;
2123
+ /**
2124
+ * Whether `ctx.fetch` is instrumented: each outbound call becomes a **CLIENT
2125
+ * span**, and a W3C `traceparent` naming that span is injected so the callee's
2126
+ * spans join this trace instead of starting a disconnected one. Default `true`
2127
+ * whenever a sink is configured.
2128
+ *
2129
+ * Set `false` for the bare platform `fetch` (no span, no header). Pass
2130
+ * `{ propagate }` to keep the spans but control who receives trace context, e.g.
2131
+ * `propagate: (url) => url.host.endsWith(".internal")` to send it to your own
2132
+ * services and not to third parties.
2133
+ */
2134
+ traceFetch?: boolean | {
2135
+ propagate?: ((url: URL) => boolean) | boolean;
2136
+ };
2011
2137
  }
2012
2138
  /**
2013
2139
  * Invoke `sink.onRpc` with the given event, swallowing any error the sink
@@ -3819,15 +3945,6 @@ interface MemoizeIdentityOptions {
3819
3945
  * An anonymous request (no cookie, no bearer) is never cached.
3820
3946
  */
3821
3947
  declare const memoizeIdentity: (resolver: IdentityResolver, options?: MemoizeIdentityOptions) => IdentityResolver;
3822
- /** A JS attribute value the encoder maps onto an OTLP `AnyValue`. */
3823
- type OtlpAttributeValue = boolean | number | string;
3824
- /**
3825
- * A `Resource.attributes` bag — the process-level identity (`service.name`,
3826
- * `service.version`, `cloud.region`, …) attached to every exported signal.
3827
- * Lives here rather than in either exporter because both packages build one and
3828
- * `wrapResource*` consumes it.
3829
- */
3830
- type OtlpResourceAttributes = Record<string, OtlpAttributeValue>;
3831
3948
  /** Shared shape for sinks that can be limited to error events only. */
3832
3949
  interface OnlyErrorsOption {
3833
3950
  /** When true, only events with `ok === false` are forwarded. */
@@ -4026,8 +4143,76 @@ interface PipelineLogSinkOptions {
4026
4143
  * `serializeFields` stores `fields` as a queryable JSON string.
4027
4144
  */
4028
4145
  declare const pipelineLogSink: (options: PipelineLogSinkOptions) => ObservabilitySink;
4146
+ /**
4147
+ * Everything the exporter buffered for one flush window, grouped so a
4148
+ * {@link TailSampler} can judge a trace as a whole.
4149
+ *
4150
+ * This is what makes it *tail* sampling rather than another head decision: by
4151
+ * flush time the trace's spans have all settled, so "keep it if anything in it
4152
+ * was slow or failed" is answerable — which it is not at the moment the first
4153
+ * span starts.
4154
+ */
4155
+ interface TailSamplerInput {
4156
+ /** Log records emitted under this trace. */
4157
+ logs: LogEvent[];
4158
+ /** RPC (SERVER) dispatch events belonging to this trace. */
4159
+ rpc: ObservabilityEvent[];
4160
+ /** `ctx.trace` spans belonging to this trace. */
4161
+ spans: SpanEvent[];
4162
+ /** The trace's id, or `undefined` for events that carried no trace context. */
4163
+ traceId: string | undefined;
4164
+ }
4165
+ /**
4166
+ * Decide whether a whole trace is exported. Return `false` to drop it — spans,
4167
+ * logs, and all.
4168
+ *
4169
+ * Composes with head sampling rather than replacing it: head sampling cheaply
4170
+ * discards most traces before they cost anything, and this makes the final call
4171
+ * on what survived. The canonical policy — "keep errors and slow requests, drop
4172
+ * the rest" — needs both.
4173
+ */
4174
+ type TailSampler = (input: TailSamplerInput) => boolean;
4175
+ /**
4176
+ * Last-chance transforms applied to each event immediately before encoding.
4177
+ *
4178
+ * Return `undefined` from any hook to drop that event entirely. This is the
4179
+ * redaction seam: attributes, log messages, and error strings can all carry user
4180
+ * input, and once a payload leaves for a third-party collector it is out of your
4181
+ * control. Doing it here rather than at each call site means one auditable place
4182
+ * to prove PII cannot escape.
4183
+ *
4184
+ * A hook that THROWS also drops the event. Redaction is a privacy control, so it
4185
+ * fails closed — losing a span beats exporting the thing the hook existed to
4186
+ * remove.
4187
+ */
4188
+ interface OtlpPostProcessor {
4189
+ log?: (event: LogEvent) => LogEvent | undefined;
4190
+ metric?: (event: MetricEvent) => MetricEvent | undefined;
4191
+ rpc?: (event: ObservabilityEvent) => ObservabilityEvent | undefined;
4192
+ span?: (event: SpanEvent) => SpanEvent | undefined;
4193
+ }
4194
+ /** Batching knobs for {@link otlpSink}; pass `batch: false` to export each event immediately. */
4195
+ interface OtlpBatchOptions {
4196
+ /**
4197
+ * Flush this long after the first buffered event, as a backstop for contexts
4198
+ * with no invocation boundary. Default 200ms.
4199
+ */
4200
+ maxDelayMs?: number;
4201
+ /** Flush as soon as this many events are buffered. Default 512. */
4202
+ maxItems?: number;
4203
+ }
4029
4204
  /** Options for {@link otlpSink}. */
4030
4205
  interface OtlpSinkOptions extends OnlyErrorsOption {
4206
+ /**
4207
+ * Buffer events and export them as one request per signal instead of one
4208
+ * request per event (the default). Pass `false` to restore per-event POSTs.
4209
+ *
4210
+ * Batching is on by default because the alternative is a correctness problem,
4211
+ * not just an efficiency one: a Worker is capped at 50 (free) / 1000 (paid)
4212
+ * subrequests per invocation, so a well-instrumented handler exporting one
4213
+ * `fetch` per span can exhaust the budget its own business logic needs.
4214
+ */
4215
+ batch?: OtlpBatchOptions | false;
4031
4216
  /**
4032
4217
  * Value of the `deployment.environment` resource attribute (e.g.
4033
4218
  * `"production"`, `"staging"`, `"development"`).
@@ -4064,6 +4249,12 @@ interface OtlpSinkOptions extends OnlyErrorsOption {
4064
4249
  * default and may be overridden here.
4065
4250
  */
4066
4251
  headers?: Record<string, string>;
4252
+ /**
4253
+ * Redact or drop events just before they are encoded — see
4254
+ * {@link OtlpPostProcessor}. A hook that throws drops the event (fail-closed);
4255
+ * see {@link postProcess}.
4256
+ */
4257
+ postProcessor?: OtlpPostProcessor;
4067
4258
  /**
4068
4259
  * Additional resource attributes to attach to every exported signal. These
4069
4260
  * ride alongside the built-in `service.name` and any convenience fields
@@ -4087,6 +4278,18 @@ interface OtlpSinkOptions extends OnlyErrorsOption {
4087
4278
  * release tag).
4088
4279
  */
4089
4280
  serviceVersion?: string;
4281
+ /**
4282
+ * Decide per trace, at flush time, whether it is exported — see
4283
+ * {@link TailSampler}. Requires batching (the default); ignored when
4284
+ * `batch: false`, because an unbuffered exporter has no trace to judge.
4285
+ *
4286
+ * A sampler that throws **keeps** the trace (fail-open) and the failure is
4287
+ * reported to `console.error`, rate-limited per sink. Treat this hook as a
4288
+ * cost control, not a guarantee: if a bounded export volume is a hard
4289
+ * requirement, enforce it at the collector, which cannot be bypassed by a bug
4290
+ * in this predicate.
4291
+ */
4292
+ tailSampler?: TailSampler;
4090
4293
  /**
4091
4294
  * Convenience bearer token: when set, an `Authorization: Bearer` header
4092
4295
  * carrying it is added to every POST (overriding any authorization in
package/dist/index.d.ts CHANGED
@@ -1560,6 +1560,20 @@ interface LogSinkContext {
1560
1560
  interface LogEvent {
1561
1561
  /** Raw arguments passed to the `ctx.log.*` call, in order. */
1562
1562
  args: unknown[];
1563
+ /**
1564
+ * OTel `LogRecord.eventName` — set when the line was emitted as a **structured
1565
+ * event** via `ctx.log.event(name, fields)` rather than as a human-readable
1566
+ * log line.
1567
+ *
1568
+ * The distinction is the whole point of the Events API: a log line's payload
1569
+ * is its `message` (prose, for a human, unstable), while an event's payload is
1570
+ * its `fields` (a named schema, for a query, stable). A collector that knows
1571
+ * `eventName` can index and aggregate the latter; without it, "how many
1572
+ * checkouts failed" degrades into a substring search over prose.
1573
+ *
1574
+ * Absent for ordinary `ctx.log.*` calls.
1575
+ */
1576
+ eventName?: string;
1563
1577
  /**
1564
1578
  * Structured fields the caller attached (`ctx.log.info(message, fields)` or a
1565
1579
  * bound `ctx.log.with(fields)` child), already normalized to a fresh bag of
@@ -1817,6 +1831,58 @@ interface MetricEvent {
1817
1831
  */
1818
1832
  value: number;
1819
1833
  }
1834
+ /** A JS attribute value the encoder maps onto an OTLP `AnyValue`. */
1835
+ type OtlpAttributeValue = boolean | number | string;
1836
+ /**
1837
+ * A `Resource.attributes` bag — the process-level identity (`service.name`,
1838
+ * `service.version`, `cloud.region`, …) attached to every exported signal.
1839
+ * Lives here rather than in either exporter because both packages build one and
1840
+ * `wrapResource*` consumes it.
1841
+ */
1842
+ type OtlpResourceAttributes = Record<string, OtlpAttributeValue>;
1843
+ /**
1844
+ * The OTel `SpanKind` union, in the spec's own words rather than its wire
1845
+ * numbers, so a call site reads `{ kind: "client" }` instead of `{ kind: 3 }`.
1846
+ *
1847
+ * Kind is not cosmetic: a service map is built from it. A CLIENT span with no
1848
+ * matching SERVER span on the other side is a dropped hop; PRODUCER/CONSUMER is
1849
+ * what makes a queue render as an async edge rather than a synchronous call.
1850
+ * Getting it wrong is why "everything is INTERNAL" traces produce no topology.
1851
+ */
1852
+ type OtlpSpanKind = "client" | "consumer" | "internal" | "producer" | "server";
1853
+ /**
1854
+ * One timestamped occurrence inside a span — OTel's `Span.events`.
1855
+ *
1856
+ * The right shape for something that has a moment but no duration: a retry, a
1857
+ * cache miss, a validation failure, a thrown exception. Modelling those as
1858
+ * near-zero-width child spans clutters the waterfall, and modelling them as
1859
+ * separate log lines loses the "which span was I in" correlation that makes them
1860
+ * useful in the first place.
1861
+ */
1862
+ interface SpanEventPoint {
1863
+ /** Structured attributes, normalized like a span's own. */
1864
+ attributes?: LogFields;
1865
+ /** Event name, e.g. `"exception"` or `"cache.miss"`. */
1866
+ name: string;
1867
+ /** Wall-clock millis when it happened. */
1868
+ ts: number;
1869
+ }
1870
+ /**
1871
+ * A causal reference to a span in ANOTHER trace — OTel's `Span.links`.
1872
+ *
1873
+ * The standard answer to fan-in: a queue consumer processing a batch of 100
1874
+ * messages links to the 100 producing spans rather than parenting to one of them
1875
+ * (arbitrary) or all of them (impossible). The traces stay separately navigable
1876
+ * and the causal edge survives.
1877
+ */
1878
+ interface SpanLink {
1879
+ /** Attributes describing the relationship, e.g. `{ "link.kind": "enqueued_by" }`. */
1880
+ attributes?: LogFields;
1881
+ /** Linked span id (16-hex). */
1882
+ spanId: string;
1883
+ /** Linked trace id (32-hex). */
1884
+ traceId: string;
1885
+ }
1820
1886
  interface SpanEvent {
1821
1887
  /**
1822
1888
  * Structured attributes the caller attached, already normalized to a fresh
@@ -1826,6 +1892,12 @@ interface SpanEvent {
1826
1892
  attributes?: LogFields;
1827
1893
  /** Wall-clock duration of the span body, in milliseconds. */
1828
1894
  durationMs: number;
1895
+ /**
1896
+ * Timestamped occurrences inside the span (see {@link SpanEventPoint}) —
1897
+ * `ctx.trace`'s `span.addEvent(...)` / `span.recordException(...)`. Absent
1898
+ * when the body recorded none.
1899
+ */
1900
+ events?: SpanEventPoint[];
1829
1901
  /**
1830
1902
  * Populated when the span body threw. `type` is the error's constructor name
1831
1903
  * (or its `LunoraError` code); `message` is the human-readable string and may
@@ -1842,6 +1914,14 @@ interface SpanEvent {
1842
1914
  * reuses its context — the same attribution rule `ctx.log` follows.
1843
1915
  */
1844
1916
  functionPath: string;
1917
+ /**
1918
+ * OTel `SpanKind`. Absent means `"internal"` — the overwhelming majority of
1919
+ * `ctx.trace` spans — so the common case costs no bytes on the wire and every
1920
+ * pre-existing recorded span stays valid.
1921
+ */
1922
+ kind?: OtlpSpanKind;
1923
+ /** Causal references to spans in other traces (see {@link SpanLink}). Absent when none. */
1924
+ links?: SpanLink[];
1845
1925
  /** Caller-supplied span name, e.g. `"stripe.charge"`. */
1846
1926
  name: string;
1847
1927
  /** True when the span body returned without throwing. */
@@ -1963,6 +2043,21 @@ type ObservabilitySinkContext = LogSinkContext;
1963
2043
  * events it cares about; the runtime no-ops the others.
1964
2044
  */
1965
2045
  interface ObservabilitySink {
2046
+ /**
2047
+ * Ship anything the sink is holding, now.
2048
+ *
2049
+ * A batching sink (`otlpSink` by default) buffers events and exports them as
2050
+ * one request instead of one request per event. That is only safe because a
2051
+ * Workers isolate can be frozen the instant a response is returned: the
2052
+ * runtime calls this at every invocation boundary — end of `fetch`, `queue`,
2053
+ * `scheduled`, and each Durable Object dispatch — passing the request's
2054
+ * `waitUntil` so the export outlives the response.
2055
+ *
2056
+ * Optional and idempotent: a non-buffering sink simply omits it, and calling
2057
+ * it with an empty buffer is a no-op. A sink must never throw from here; like
2058
+ * every other hook, a telemetry failure must not surface to the caller.
2059
+ */
2060
+ flush?: (context?: ObservabilitySinkContext) => void;
1966
2061
  /**
1967
2062
  * **Opt-in, EXPERIMENTAL, default `false`.** When `true`, each `ctx.trace`
1968
2063
  * span the Durable Object records is ALSO emitted as a Cloudflare **custom
@@ -1993,6 +2088,23 @@ interface ObservabilitySink {
1993
2088
  * `createShardDO` — the DO reads the flag when building `ctx.trace`.
1994
2089
  */
1995
2090
  fuseCloudflareTraces?: boolean;
2091
+ /**
2092
+ * How much detail automatic `ctx.db` instrumentation produces.
2093
+ *
2094
+ * `"summary"` (**default**) — aggregate counters (`db.calls`, `db.duration_ms`,
2095
+ * per-operation counts) folded onto the dispatch's wide event. No extra spans
2096
+ * and no extra log records, so the cost is flat no matter how many queries a
2097
+ * handler makes.
2098
+ *
2099
+ * `"spans"` — one span per database call: the full waterfall, for when you are
2100
+ * chasing a specific slow query. Capped per dispatch so a query loop cannot
2101
+ * bury the trace; truncation is reported as `db.spans_truncated`.
2102
+ *
2103
+ * `"off"` — no database telemetry.
2104
+ *
2105
+ * Applies only when a sink is configured; with none, `ctx.db` is untouched.
2106
+ */
2107
+ instrumentDatabase?: "off" | "spans" | "summary";
1996
2108
  /** Invoked once per `ctx.log.*` call from a function handler. */
1997
2109
  onLog?: (event: LogEvent, context?: ObservabilitySinkContext) => void;
1998
2110
  /**
@@ -2008,6 +2120,20 @@ interface ObservabilitySink {
2008
2120
  * INTERNAL spans a handler creates beneath it.
2009
2121
  */
2010
2122
  onSpan?: (event: SpanEvent, context?: ObservabilitySinkContext) => void;
2123
+ /**
2124
+ * Whether `ctx.fetch` is instrumented: each outbound call becomes a **CLIENT
2125
+ * span**, and a W3C `traceparent` naming that span is injected so the callee's
2126
+ * spans join this trace instead of starting a disconnected one. Default `true`
2127
+ * whenever a sink is configured.
2128
+ *
2129
+ * Set `false` for the bare platform `fetch` (no span, no header). Pass
2130
+ * `{ propagate }` to keep the spans but control who receives trace context, e.g.
2131
+ * `propagate: (url) => url.host.endsWith(".internal")` to send it to your own
2132
+ * services and not to third parties.
2133
+ */
2134
+ traceFetch?: boolean | {
2135
+ propagate?: ((url: URL) => boolean) | boolean;
2136
+ };
2011
2137
  }
2012
2138
  /**
2013
2139
  * Invoke `sink.onRpc` with the given event, swallowing any error the sink
@@ -3819,15 +3945,6 @@ interface MemoizeIdentityOptions {
3819
3945
  * An anonymous request (no cookie, no bearer) is never cached.
3820
3946
  */
3821
3947
  declare const memoizeIdentity: (resolver: IdentityResolver, options?: MemoizeIdentityOptions) => IdentityResolver;
3822
- /** A JS attribute value the encoder maps onto an OTLP `AnyValue`. */
3823
- type OtlpAttributeValue = boolean | number | string;
3824
- /**
3825
- * A `Resource.attributes` bag — the process-level identity (`service.name`,
3826
- * `service.version`, `cloud.region`, …) attached to every exported signal.
3827
- * Lives here rather than in either exporter because both packages build one and
3828
- * `wrapResource*` consumes it.
3829
- */
3830
- type OtlpResourceAttributes = Record<string, OtlpAttributeValue>;
3831
3948
  /** Shared shape for sinks that can be limited to error events only. */
3832
3949
  interface OnlyErrorsOption {
3833
3950
  /** When true, only events with `ok === false` are forwarded. */
@@ -4026,8 +4143,76 @@ interface PipelineLogSinkOptions {
4026
4143
  * `serializeFields` stores `fields` as a queryable JSON string.
4027
4144
  */
4028
4145
  declare const pipelineLogSink: (options: PipelineLogSinkOptions) => ObservabilitySink;
4146
+ /**
4147
+ * Everything the exporter buffered for one flush window, grouped so a
4148
+ * {@link TailSampler} can judge a trace as a whole.
4149
+ *
4150
+ * This is what makes it *tail* sampling rather than another head decision: by
4151
+ * flush time the trace's spans have all settled, so "keep it if anything in it
4152
+ * was slow or failed" is answerable — which it is not at the moment the first
4153
+ * span starts.
4154
+ */
4155
+ interface TailSamplerInput {
4156
+ /** Log records emitted under this trace. */
4157
+ logs: LogEvent[];
4158
+ /** RPC (SERVER) dispatch events belonging to this trace. */
4159
+ rpc: ObservabilityEvent[];
4160
+ /** `ctx.trace` spans belonging to this trace. */
4161
+ spans: SpanEvent[];
4162
+ /** The trace's id, or `undefined` for events that carried no trace context. */
4163
+ traceId: string | undefined;
4164
+ }
4165
+ /**
4166
+ * Decide whether a whole trace is exported. Return `false` to drop it — spans,
4167
+ * logs, and all.
4168
+ *
4169
+ * Composes with head sampling rather than replacing it: head sampling cheaply
4170
+ * discards most traces before they cost anything, and this makes the final call
4171
+ * on what survived. The canonical policy — "keep errors and slow requests, drop
4172
+ * the rest" — needs both.
4173
+ */
4174
+ type TailSampler = (input: TailSamplerInput) => boolean;
4175
+ /**
4176
+ * Last-chance transforms applied to each event immediately before encoding.
4177
+ *
4178
+ * Return `undefined` from any hook to drop that event entirely. This is the
4179
+ * redaction seam: attributes, log messages, and error strings can all carry user
4180
+ * input, and once a payload leaves for a third-party collector it is out of your
4181
+ * control. Doing it here rather than at each call site means one auditable place
4182
+ * to prove PII cannot escape.
4183
+ *
4184
+ * A hook that THROWS also drops the event. Redaction is a privacy control, so it
4185
+ * fails closed — losing a span beats exporting the thing the hook existed to
4186
+ * remove.
4187
+ */
4188
+ interface OtlpPostProcessor {
4189
+ log?: (event: LogEvent) => LogEvent | undefined;
4190
+ metric?: (event: MetricEvent) => MetricEvent | undefined;
4191
+ rpc?: (event: ObservabilityEvent) => ObservabilityEvent | undefined;
4192
+ span?: (event: SpanEvent) => SpanEvent | undefined;
4193
+ }
4194
+ /** Batching knobs for {@link otlpSink}; pass `batch: false` to export each event immediately. */
4195
+ interface OtlpBatchOptions {
4196
+ /**
4197
+ * Flush this long after the first buffered event, as a backstop for contexts
4198
+ * with no invocation boundary. Default 200ms.
4199
+ */
4200
+ maxDelayMs?: number;
4201
+ /** Flush as soon as this many events are buffered. Default 512. */
4202
+ maxItems?: number;
4203
+ }
4029
4204
  /** Options for {@link otlpSink}. */
4030
4205
  interface OtlpSinkOptions extends OnlyErrorsOption {
4206
+ /**
4207
+ * Buffer events and export them as one request per signal instead of one
4208
+ * request per event (the default). Pass `false` to restore per-event POSTs.
4209
+ *
4210
+ * Batching is on by default because the alternative is a correctness problem,
4211
+ * not just an efficiency one: a Worker is capped at 50 (free) / 1000 (paid)
4212
+ * subrequests per invocation, so a well-instrumented handler exporting one
4213
+ * `fetch` per span can exhaust the budget its own business logic needs.
4214
+ */
4215
+ batch?: OtlpBatchOptions | false;
4031
4216
  /**
4032
4217
  * Value of the `deployment.environment` resource attribute (e.g.
4033
4218
  * `"production"`, `"staging"`, `"development"`).
@@ -4064,6 +4249,12 @@ interface OtlpSinkOptions extends OnlyErrorsOption {
4064
4249
  * default and may be overridden here.
4065
4250
  */
4066
4251
  headers?: Record<string, string>;
4252
+ /**
4253
+ * Redact or drop events just before they are encoded — see
4254
+ * {@link OtlpPostProcessor}. A hook that throws drops the event (fail-closed);
4255
+ * see {@link postProcess}.
4256
+ */
4257
+ postProcessor?: OtlpPostProcessor;
4067
4258
  /**
4068
4259
  * Additional resource attributes to attach to every exported signal. These
4069
4260
  * ride alongside the built-in `service.name` and any convenience fields
@@ -4087,6 +4278,18 @@ interface OtlpSinkOptions extends OnlyErrorsOption {
4087
4278
  * release tag).
4088
4279
  */
4089
4280
  serviceVersion?: string;
4281
+ /**
4282
+ * Decide per trace, at flush time, whether it is exported — see
4283
+ * {@link TailSampler}. Requires batching (the default); ignored when
4284
+ * `batch: false`, because an unbuffered exporter has no trace to judge.
4285
+ *
4286
+ * A sampler that throws **keeps** the trace (fail-open) and the failure is
4287
+ * reported to `console.error`, rate-limited per sink. Treat this hook as a
4288
+ * cost control, not a guarantee: if a bounded export volume is a hard
4289
+ * requirement, enforce it at the collector, which cannot be bypassed by a bug
4290
+ * in this predicate.
4291
+ */
4292
+ tailSampler?: TailSampler;
4090
4293
  /**
4091
4294
  * Convenience bearer token: when set, an `Authorization: Bearer` header
4092
4295
  * carrying it is added to every POST (overriding any authorization in
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{toAirbyteMessages as t,toFivetranResponse as i}from"./packem_shared/toAirbyteMessages-DBTuFjb5.mjs";import{composeWorker as n,createLunoraHandler as s,createWorker as p,defineRpcEnvelope as m,resolveLunoraOptions as c,withFrameworkWorker as R}from"./packem_shared/composeWorker-BayjP04B.mjs";import{createCrossShardRelationCapabilities as E}from"./packem_shared/createCrossShardRelationCapabilities-B2EKbSEs.mjs";import{DEFAULT_REGISTRY_CACHE_TTL_MS as x,SHARD_REGISTRY_DO_NAME as d,createDynamicShardRegistry as l}from"./packem_shared/DEFAULT_REGISTRY_CACHE_TTL_MS-BBf3mNrD.mjs";import{LunoraError as L,toErrorResponse as g}from"./packem_shared/LunoraError-C08OP5Uq.mjs";import{createKvCursorStore as y,createMemoryCursorStore as T,defineExportSink as A,r2Sink as k,runExportTap as C,sanitizeChange as O,webhookExportSink as h}from"./packem_shared/createKvCursorStore-C24tEuYk.mjs";import{HEALTH_PATH as H,HEALTH_READY_PATH as I,buildHealthRoutes as b,d1Probe as F,durableObjectProbe as P,presenceProbe as D}from"./packem_shared/HEALTH_PATH-DiZqjEGp.mjs";import{LOG_ARCHIVE_PATH as G,resolveLogArchiveFromEnv as M}from"./packem_shared/LOG_ARCHIVE_PATH-e8U3ftfM.mjs";import{memoizeIdentity as w,memoizeIdentityPerRequest as z}from"./packem_shared/memoizeIdentity-DRYIK1yT.mjs";import{e as W,a as Y}from"./packem_shared/observability-D3GeW_py.mjs";import{analyticsEngineSink as Q,combineSinks as X,consoleSink as j,otlpSink as q,pipelineLogSink as J,sentrySink as B,webhookSink as Z}from"./packem_shared/analyticsEngineSink-pVh4v2aY.mjs";import{D as ee,a as re,c as oe}from"./packem_shared/pipeline-log-reader-tDuvc_Ty.mjs";import{createQueryCoordinator as ie,createStaticShardRegistry as ae,mergeStrategyForAggregate as ne}from"./packem_shared/createQueryCoordinator-DLsrcOkB.mjs";import{applyJurisdiction as pe,resolveShard as me}from"./packem_shared/applyJurisdiction-uRQLx282.mjs";import{argsFromQuery as Re,buildRestRoutes as Se,createRestRateLimit as Ee,readShardKey as fe,restSurfaceFromRegistry as xe}from"./packem_shared/argsFromQuery-0KrWTkNx.mjs";import{decorateResponse as le,enforceOrigin as _e,handleCorsPreflight as Le,resolveSecurity as ge}from"./packem_shared/decorateResponse-C6TZSzID.mjs";import{createShardClient as ye}from"./packem_shared/createShardClient-62qcYKGl.mjs";import{LOG_ARCHIVE_NOT_CONFIGURED as Ae}from"./packem_shared/LOG_ARCHIVE_NOT_CONFIGURED-CDpi4yFD.mjs";import{NOOP_EXECUTION_CONTEXT as Ce}from"./packem_shared/NOOP_EXECUTION_CONTEXT-YmXqH-jH.mjs";import{composeIdentityResolvers as he,routeIdentityResolvers as ve}from"./packem_shared/composeIdentityResolvers-DlBbYmBJ.mjs";const e="0.0.0";export{ee as DEFAULT_LOG_COLUMNS,re as DEFAULT_LOG_LIMIT,x as DEFAULT_REGISTRY_CACHE_TTL_MS,H as HEALTH_PATH,I as HEALTH_READY_PATH,Ae as LOG_ARCHIVE_NOT_CONFIGURED,G as LOG_ARCHIVE_PATH,L as LunoraError,Ce as NOOP_EXECUTION_CONTEXT,d as SHARD_REGISTRY_DO_NAME,e as VERSION,Q as analyticsEngineSink,pe as applyJurisdiction,Re as argsFromQuery,b as buildHealthRoutes,Se as buildRestRoutes,X as combineSinks,he as composeIdentityResolvers,n as composeWorker,j as consoleSink,E as createCrossShardRelationCapabilities,l as createDynamicShardRegistry,y as createKvCursorStore,s as createLunoraHandler,T as createMemoryCursorStore,oe as createPipelineLogReader,ie as createQueryCoordinator,Ee as createRestRateLimit,ye as createShardClient,ae as createStaticShardRegistry,p as createWorker,F as d1Probe,le as decorateResponse,A as defineExportSink,m as defineRpcEnvelope,P as durableObjectProbe,W as emitLogEvent,Y as emitRpcEvent,_e as enforceOrigin,Le as handleCorsPreflight,w as memoizeIdentity,z as memoizeIdentityPerRequest,ne as mergeStrategyForAggregate,q as otlpSink,J as pipelineLogSink,D as presenceProbe,k as r2Sink,fe as readShardKey,M as resolveLogArchiveFromEnv,c as resolveLunoraOptions,ge as resolveSecurity,me as resolveShard,xe as restSurfaceFromRegistry,ve as routeIdentityResolvers,C as runExportTap,O as sanitizeChange,B as sentrySink,t as toAirbyteMessages,g as toErrorResponse,i as toFivetranResponse,h as webhookExportSink,Z as webhookSink,R as withFrameworkWorker};
1
+ import{toAirbyteMessages as t,toFivetranResponse as i}from"./packem_shared/toAirbyteMessages-DBTuFjb5.mjs";import{composeWorker as n,createLunoraHandler as s,createWorker as p,defineRpcEnvelope as m,resolveLunoraOptions as c,withFrameworkWorker as R}from"./packem_shared/composeWorker-D7Zi6kZR.mjs";import{createCrossShardRelationCapabilities as E}from"./packem_shared/createCrossShardRelationCapabilities-B2EKbSEs.mjs";import{DEFAULT_REGISTRY_CACHE_TTL_MS as x,SHARD_REGISTRY_DO_NAME as d,createDynamicShardRegistry as l}from"./packem_shared/DEFAULT_REGISTRY_CACHE_TTL_MS-BBf3mNrD.mjs";import{LunoraError as L,toErrorResponse as g}from"./packem_shared/LunoraError-C08OP5Uq.mjs";import{createKvCursorStore as y,createMemoryCursorStore as T,defineExportSink as A,r2Sink as k,runExportTap as C,sanitizeChange as O,webhookExportSink as h}from"./packem_shared/createKvCursorStore-C24tEuYk.mjs";import{HEALTH_PATH as H,HEALTH_READY_PATH as I,buildHealthRoutes as b,d1Probe as F,durableObjectProbe as P,presenceProbe as D}from"./packem_shared/HEALTH_PATH-DiZqjEGp.mjs";import{LOG_ARCHIVE_PATH as G,resolveLogArchiveFromEnv as M}from"./packem_shared/LOG_ARCHIVE_PATH-e8U3ftfM.mjs";import{memoizeIdentity as w,memoizeIdentityPerRequest as z}from"./packem_shared/memoizeIdentity-DRYIK1yT.mjs";import{e as W,a as Y}from"./packem_shared/observability-B0MYwNDB.mjs";import{analyticsEngineSink as Q,combineSinks as X,consoleSink as j,otlpSink as q,pipelineLogSink as J,sentrySink as B,webhookSink as Z}from"./packem_shared/analyticsEngineSink-DOoyBx4o.mjs";import{D as ee,a as re,c as oe}from"./packem_shared/pipeline-log-reader-tDuvc_Ty.mjs";import{createQueryCoordinator as ie,createStaticShardRegistry as ae,mergeStrategyForAggregate as ne}from"./packem_shared/createQueryCoordinator-DLsrcOkB.mjs";import{applyJurisdiction as pe,resolveShard as me}from"./packem_shared/applyJurisdiction-uRQLx282.mjs";import{argsFromQuery as Re,buildRestRoutes as Se,createRestRateLimit as Ee,readShardKey as fe,restSurfaceFromRegistry as xe}from"./packem_shared/argsFromQuery-0KrWTkNx.mjs";import{decorateResponse as le,enforceOrigin as _e,handleCorsPreflight as Le,resolveSecurity as ge}from"./packem_shared/decorateResponse-C6TZSzID.mjs";import{createShardClient as ye}from"./packem_shared/createShardClient-62qcYKGl.mjs";import{LOG_ARCHIVE_NOT_CONFIGURED as Ae}from"./packem_shared/LOG_ARCHIVE_NOT_CONFIGURED-CDpi4yFD.mjs";import{NOOP_EXECUTION_CONTEXT as Ce}from"./packem_shared/NOOP_EXECUTION_CONTEXT-YmXqH-jH.mjs";import{composeIdentityResolvers as he,routeIdentityResolvers as ve}from"./packem_shared/composeIdentityResolvers-DlBbYmBJ.mjs";const e="0.0.0";export{ee as DEFAULT_LOG_COLUMNS,re as DEFAULT_LOG_LIMIT,x as DEFAULT_REGISTRY_CACHE_TTL_MS,H as HEALTH_PATH,I as HEALTH_READY_PATH,Ae as LOG_ARCHIVE_NOT_CONFIGURED,G as LOG_ARCHIVE_PATH,L as LunoraError,Ce as NOOP_EXECUTION_CONTEXT,d as SHARD_REGISTRY_DO_NAME,e as VERSION,Q as analyticsEngineSink,pe as applyJurisdiction,Re as argsFromQuery,b as buildHealthRoutes,Se as buildRestRoutes,X as combineSinks,he as composeIdentityResolvers,n as composeWorker,j as consoleSink,E as createCrossShardRelationCapabilities,l as createDynamicShardRegistry,y as createKvCursorStore,s as createLunoraHandler,T as createMemoryCursorStore,oe as createPipelineLogReader,ie as createQueryCoordinator,Ee as createRestRateLimit,ye as createShardClient,ae as createStaticShardRegistry,p as createWorker,F as d1Probe,le as decorateResponse,A as defineExportSink,m as defineRpcEnvelope,P as durableObjectProbe,W as emitLogEvent,Y as emitRpcEvent,_e as enforceOrigin,Le as handleCorsPreflight,w as memoizeIdentity,z as memoizeIdentityPerRequest,ne as mergeStrategyForAggregate,q as otlpSink,J as pipelineLogSink,D as presenceProbe,k as r2Sink,fe as readShardKey,M as resolveLogArchiveFromEnv,c as resolveLunoraOptions,ge as resolveSecurity,me as resolveShard,xe as restSurfaceFromRegistry,ve as routeIdentityResolvers,C as runExportTap,O as sanitizeChange,B as sentrySink,t as toAirbyteMessages,g as toErrorResponse,i as toFivetranResponse,h as webhookExportSink,Z as webhookSink,R as withFrameworkWorker};
@@ -0,0 +1 @@
1
+ import{w as J,f as k,V as F,O as z,c as d,b as Z,a as C,y as K,L as A,S as B,R as ee}from"./otlp-resource-cAjGEywx.mjs";const ne=e=>{if(typeof e=="string")return e;try{return JSON.stringify(e)??String(e)}catch{return String(e)}},R=e=>typeof e=="boolean"||typeof e=="number"||typeof e=="string"?e:ne(e),te=e=>{const r=e.maxItems??512,n=e.maxDelayMs??200;let t=[],o,i,p;const f=()=>{o!==void 0&&(clearTimeout(o),o=void 0)},h=async()=>{f();const c=t;t=[];const u=p;i=void 0,p=void 0;try{c.length>0&&await e.export(c)}catch{}finally{u?.()}},m=c=>{i===void 0&&(i=new Promise(u=>{p=u}),o=setTimeout(()=>{h()},n)),c?.(i)};return{add:(c,u)=>{for(t.push(c);t.length>r;)t.shift();m(u),t.length>=r&&h()},flush:async c=>{if(t.length===0){f();return}const u=h();return c?.(u),u},get size(){return t.length}}},q=(e,r)=>{const n=[d("lunora.function_path",e.functionPath),d("lunora.ok",e.ok)];e.method!==void 0&&n.push(d("http.request.method",e.method)),e.path!==void 0&&n.push(d("url.path",e.path)),n.push(d("http.route",e.functionPath)),e.scheme!==void 0&&n.push(d("url.scheme",e.scheme)),e.host!==void 0&&n.push(d("server.address",e.host)),e.port!==void 0&&n.push(d("server.port",e.port)),e.userAgent!==void 0&&n.push(d("user_agent.original",e.userAgent)),e.shardKey!==void 0&&n.push(d("lunora.shard_key",e.shardKey)),n.push(d("http.response.status_code",e.error?.status??200)),e.error&&n.push(d("error.type",e.error.code),d("lunora.error_status",e.error.status)),e.fanOut&&n.push(d("lunora.fanout.table",e.fanOut.table),d("lunora.fanout.shards",e.fanOut.shards),d("lunora.fanout.failed",e.fanOut.failed));const t={attributes:n,endTimeUnixNano:k(r),kind:J.server,name:e.functionPath,...e.parentSpanId===void 0?{}:{parentSpanId:e.parentSpanId},spanId:e.spanId??z(8),startTimeUnixNano:k(r-e.durationMs),status:e.ok?{code:1}:{code:2,message:e.error?.message??""},traceId:e.traceId??z(16)};return e.traceFlags!==void 0&&(t.flags=e.traceFlags),e.error&&(t.events=[{attributes:[d("exception.type",e.error.code),d("exception.message",e.error.message)],name:"exception",timeUnixNano:k(r)}]),t},L=(e,r)=>{const n=new Map([["lunora.function_path",d("lunora.function_path",e.functionPath)]]);e.shardKey!==void 0&&n.set("lunora.shard_key",d("lunora.shard_key",e.shardKey)),e.userId!==void 0&&n.set("lunora.user_id",d("lunora.user_id",e.userId)),e.errorType!==void 0&&n.set("error.type",d("error.type",e.errorType));for(const[t,o]of Object.entries(r??{}))n.set(t,d(t,R(o)));return[...n.values()]},W=e=>{const r={attributes:L({errorType:e.error?.type,functionPath:e.functionPath,shardKey:e.shardKey,userId:e.userId},e.attributes),endTimeUnixNano:k(e.startTs+e.durationMs),kind:J[e.kind??"internal"],name:e.name,parentSpanId:e.parentSpanId,spanId:e.spanId,startTimeUnixNano:k(e.startTs),status:e.ok?{code:1}:{code:2,message:e.error?.message??""},traceId:e.traceId};return e.events!==void 0&&e.events.length>0&&(r.events=e.events.map(n=>({attributes:F(Object.fromEntries(Object.entries(n.attributes??{}).map(([t,o])=>[t,R(o)]))),name:n.name,timeUnixNano:k(n.ts)}))),e.links!==void 0&&e.links.length>0&&(r.links=e.links.map(n=>({attributes:F(Object.fromEntries(Object.entries(n.attributes??{}).map(([t,o])=>[t,R(o)]))),spanId:n.spanId,traceId:n.traceId}))),r},G=e=>{const r=k(e.ts),n=L({functionPath:e.functionPath,shardKey:e.shardKey},e.attributes),t={asDouble:e.value,attributes:n,timeUnixNano:r};return e.kind==="gauge"?{gauge:{dataPoints:[t]},name:e.name}:e.kind==="histogram"?{histogram:{aggregationTemporality:1,dataPoints:[{attributes:n,bucketCounts:["1"],count:"1",explicitBounds:[],max:e.value,min:e.value,sum:e.value,timeUnixNano:r}]},name:e.name}:{name:e.name,sum:{aggregationTemporality:1,dataPoints:[t],isMonotonic:!0}}},H=e=>{const r={attributes:L({functionPath:e.functionPath,shardKey:e.shardKey,userId:e.userId},e.fields),body:{stringValue:e.message},severityNumber:Z[e.level],severityText:e.level.toUpperCase(),timeUnixNano:k(e.ts)};return e.traceId!==void 0&&(r.traceId=e.traceId),e.spanId!==void 0&&(r.spanId=e.spanId),e.eventName!==void 0&&(r.eventName=e.eventName,r.attributes.push(d("event.name",e.eventName))),r},re=1024,oe=async e=>{const r=new Blob([e]).stream().pipeThrough(new CompressionStream("gzip"));return new Response(r).arrayBuffer()},U=async(e,r,n,t)=>{try{const o=JSON.stringify(r),i=(o.length<re?fetch(e,{body:o,headers:n,method:"POST"}):oe(o).then(p=>fetch(e,{body:p,headers:{...n,"content-encoding":"gzip"},method:"POST"}))).then(()=>{},()=>{});t?.(i),await i}catch{}},N=(e,r,n,t)=>{U(e,r,n,t?.waitUntil).catch(()=>{})},P=(e,r)=>r===!0&&e.ok,se=e=>e.kind==="metric"?void 0:e.event.traceId,ae=e=>{const r=new Map,n=[];for(const t of e){const o=se(t);if(o===void 0){n.push(t);continue}const i=r.get(o);i===void 0?r.set(o,[t]):i.push(t)}return{byTrace:r,untraced:n}},V=5,ie=(e,r,n)=>{if(r===void 0)return e;const{byTrace:t,untraced:o}=ae(e),i=[...o];let p=0,f;for(const[h,m]of t){let c;try{c=r({logs:m.filter(u=>u.kind==="log").map(u=>u.event),rpc:m.filter(u=>u.kind==="rpc").map(u=>u.event),spans:m.filter(u=>u.kind==="span").map(u=>u.event),traceId:h})}catch(u){p+=1,p===1&&(f=u),c=!0}c&&i.push(...m)}return p>0&&n(f,p),i},y=(e,r)=>{if(r===void 0)return e;try{return r(e)}catch{return}},ce=(e,r)=>{if(e.kind==="rpc"){const t=y(e.event,r?.rpc);return t===void 0?void 0:{bucket:"spans",encoded:q(t,e.endMs)}}if(e.kind==="span"){const t=y(e.event,r?.span);return t===void 0?void 0:{bucket:"spans",encoded:W(t)}}if(e.kind==="log"){const t=y(e.event,r?.log);return t===void 0?void 0:{bucket:"logs",encoded:H(t)}}const n=y(e.event,r?.metric);return n===void 0?void 0:{bucket:"metrics",encoded:G(n)}},de=(e={})=>{const{onlyErrors:r}=e;return{onLog:n=>{n.level==="error"||n.level==="fatal"?console.error("[lunora:log]",n.functionPath,n.message):console.log("[lunora:log]",n.functionPath,n.message)},onMetric:n=>{console.log("[lunora:metric]",`${n.name}=${String(n.value)}`,n.kind,n.functionPath)},onRpc:n=>{P(n,r)||(n.ok?console.log("[lunora:rpc]",n):console.error("[lunora:rpc]",n))},onSpan:n=>{const t=n.ok?"ok":`error ${n.error?.type??""}`.trim();console.log("[lunora:span]",n.name,`${String(n.durationMs)}ms`,t,n.functionPath)}}},le=e=>{const{headers:r,onlyErrors:n,transform:t,transformLog:o,url:i}=e,p=C({"content-type":"application/json"},r),f=(h,m)=>{try{const c=fetch(i,{body:JSON.stringify(h),headers:p,method:"POST"}).catch(()=>{});m?.waitUntil&&m.waitUntil(c)}catch{}};return{onLog:(h,m)=>{let c=h;if(o)try{c=o(h)}catch{return}c!=null&&f(c,m)},onRpc:(h,m)=>{if(!P(h,n))try{let c=h;if(t)try{c=t(h)}catch{return}if(c==null)return;f(c,m)}catch{}}}},pe=e=>{const{capture:r,captureLog:n}=e,t=e.onlyErrors??!0;return{onLog:n?o=>{try{n(o)}catch{}}:void 0,onRpc:o=>{if(!P(o,t))try{r(o)}catch{}}}},he=e=>{const{dataset:r,onlyErrors:n}=e;return{onRpc:t=>{if(!P(t,n))try{r.writeDataPoint({blobs:[t.functionPath,t.ok?"ok":"error",t.shardKey??"",t.error?.code??"",t.fanOut?.table??""],doubles:[t.durationMs,t.ok?0:1,t.fanOut?.shards??0,t.fanOut?.failed??0],indexes:[t.functionPath]})}catch{}}}},me=e=>{const{pipeline:r,serializeFields:n}=e;return{onLog:(t,o)=>{try{const i={functionPath:t.functionPath,level:t.level,message:t.message,ts:t.ts};t.fields&&(i.fields=n===!0?JSON.stringify(t.fields):t.fields),t.shardKey!==void 0&&(i.shardKey=t.shardKey),t.userId!==void 0&&(i.userId=t.userId),t.traceId!==void 0&&(i.traceId=t.traceId),t.spanId!==void 0&&(i.spanId=t.spanId);const p=r.send([i]).catch(()=>{});o?.waitUntil&&o.waitUntil(p)}catch{}}}},fe=e=>{const{batch:r,deploymentEnvironment:n,detectResources:t,endpoint:o,headers:i,onlyErrors:p,postProcessor:f,resourceAttributes:h,serviceNamespace:m,serviceVersion:c,tailSampler:u,token:Q}=e,b=e.serviceName??"lunora",_={...c===void 0?{}:{"service.version":c},...m===void 0?{}:{"service.namespace":m},...n===void 0?{}:{"deployment.environment":n},...h},E=new WeakMap,g=a=>{if(t!==!0||a?.resourceAttributes===void 0)return _;const s=E.get(a);if(s!==void 0)return s;const l=ee(a.resourceAttributes(),_);return E.set(a,l),l};let w=o;for(;w.endsWith("/");)w=w.slice(0,-1);const $=`${w}/v1/traces`,j=`${w}/v1/logs`,D=`${w}/v1/metrics`,I=C({"content-type":"application/json"},i,Q);let M=0;const X=(a,s)=>{if(M>=V)return;M+=1;const l=M===V?" Further tailSampler failures from this sink are silenced until the isolate restarts.":"";console.error(`[lunora:otlp] tailSampler threw for ${String(s)} trace(s) in this flush window; keeping them (fail-open), so the sampling policy did NOT apply.${l}`,a)},Y=async a=>{const s=ie(a,u,X),l=new Map;for(const S of s){const v=ce(S,f);if(v===void 0)continue;let T=l.get(S.resource);T===void 0&&(T={logs:[],metrics:[],spans:[]},l.set(S.resource,T)),T[v.bucket].push(v.encoded)}const O=[];for(const[S,v]of l)v.spans.length>0&&O.push(U($,K(v.spans,"@lunora/runtime",b,S),I)),v.logs.length>0&&O.push(U(j,B(v.logs,"@lunora/runtime",b,S),I)),v.metrics.length>0&&O.push(U(D,A(v.metrics,"@lunora/runtime",b,S),I));await Promise.all(O)};if(r===!1)return{onLog:(a,s)=>{const l=y(a,f?.log);l!==void 0&&N(j,B(H(l),"@lunora/runtime",b,g(s)),I,s)},onMetric:(a,s)=>{const l=y(a,f?.metric);l!==void 0&&N(D,A(G(l),"@lunora/runtime",b,g(s)),I,s)},onRpc:(a,s)=>{if(P(a,p))return;const l=y(a,f?.rpc);l!==void 0&&N($,K(q(l,Date.now()),"@lunora/runtime",b,g(s)),I,s)},onSpan:(a,s)=>{const l=y(a,f?.span);l!==void 0&&N($,K(W(l),"@lunora/runtime",b,g(s)),I,s)}};const x=te({export:Y,...r?.maxDelayMs===void 0?{}:{maxDelayMs:r.maxDelayMs},...r?.maxItems===void 0?{}:{maxItems:r.maxItems}});return{flush:a=>{x.flush(a?.waitUntil).catch(()=>{})},onLog:(a,s)=>{x.add({event:a,kind:"log",resource:g(s)},s?.waitUntil)},onMetric:(a,s)=>{x.add({event:a,kind:"metric",resource:g(s)},s?.waitUntil)},onRpc:(a,s)=>{P(a,p)||x.add({endMs:Date.now(),event:a,kind:"rpc",resource:g(s)},s?.waitUntil)},onSpan:(a,s)=>{x.add({event:a,kind:"span",resource:g(s)},s?.waitUntil)}}},ve=(...e)=>{const r=(n,t)=>{for(const o of e){const i=o[n];if(i)try{i.apply(o,t)}catch{}}};return{flush:n=>{r("flush",[n])},onLog:(n,t)=>{r("onLog",[n,t])},onMetric:(n,t)=>{r("onMetric",[n,t])},onRpc:(n,t)=>{r("onRpc",[n,t])},onSpan:(n,t)=>{r("onSpan",[n,t])}}};export{he as analyticsEngineSink,ve as combineSinks,de as consoleSink,fe as otlpSink,me as pipelineLogSink,pe as sentrySink,le as webhookSink};
@@ -0,0 +1,6 @@
1
+ import{isLunoraError as Zt,toErrorBody as er}from"@lunora/errors";import{NOOP_EXECUTION_CONTEXT as tr}from"./NOOP_EXECUTION_CONTEXT-YmXqH-jH.mjs";import{O as Re,m as rr,A as nr,R as or,d as ar,i as sr,s as ir}from"./otlp-resource-cAjGEywx.mjs";import{LunoraError as a,toErrorResponse as ze}from"./LunoraError-C08OP5Uq.mjs";import{GET_AUTH_AUDIT_LOG_OP as dr,buildGetAuthAuditLog as ur}from"./GET_AUTH_AUDIT_LOG_OP-DmxHQbZT.mjs";import{runExportTap as cr}from"./createKvCursorStore-C24tEuYk.mjs";import{d as we}from"./method-guard-BbuR0VfS.mjs";import{buildHealthRoutes as lr,durableObjectProbe as hr,d1Probe as pr,presenceProbe as Pe}from"./HEALTH_PATH-DiZqjEGp.mjs";import{wrapResolverWithContract as fr}from"./composeIdentityResolvers-DlBbYmBJ.mjs";import{composeIdentityResolvers as fa,routeIdentityResolvers as wa}from"./composeIdentityResolvers-DlBbYmBJ.mjs";import{buildLogArchiveAdminRoutes as wr}from"./LOG_ARCHIVE_PATH-e8U3ftfM.mjs";import{o as mr,f as We,a as de}from"./observability-B0MYwNDB.mjs";import{resolveShard as Se,applyJurisdiction as He}from"./applyJurisdiction-uRQLx282.mjs";import{buildRestRoutes as yr}from"./argsFromQuery-0KrWTkNx.mjs";import{resolveSecurity as Je,handleCorsPreflight as gr,enforceOrigin as br,decorateResponse as Ne,enforceWebSocketOrigin as Ve}from"./decorateResponse-C6TZSzID.mjs";const pt=(e,t)=>{if(e.size<t)return;const r=e.keys().next().value;r!==void 0&&e.delete(r)},Or="::relay::",Er=(e,t)=>`${e}${Or}${String(t)}`,Ce=new TextEncoder,Tr=e=>{const t=String.fromCodePoint(...e);return btoa(t).replaceAll("+","-").replaceAll("/","_").replaceAll("=","")},_r=e=>{const t=e.replaceAll("-","+").replaceAll("_","/")+"===".slice((e.length+3)%4),r=atob(t),n=new Uint8Array(r.length);for(let s=0;s<r.length;s+=1)n[s]=r.codePointAt(s)??0;return n},Rr=64,Ue=new Map,ft=async e=>{const t=Ue.get(e);if(t)return t;pt(Ue,Rr);const r=crypto.subtle.importKey("raw",Ce.encode(e),{hash:"SHA-256",name:"HMAC"},!1,["sign","verify"]);return Ue.set(e,r),r},Sr=async(e,t)=>{const r=await ft(e),n=await crypto.subtle.sign("HMAC",r,Ce.encode(t));return Tr(new Uint8Array(n))},Ar=async(e,t,r)=>{const n=await ft(e);return crypto.subtle.verify("HMAC",n,r,Ce.encode(t))},wt="v1",Dr=6e4,vr=async(e,t={})=>{const r=(t.now??Date.now())+(t.ttlMs??Dr),n=`${wt}.${String(r)}`,s=await Sr(e,n);return{expiresAtMs:r,token:`${n}.${s}`}},kr=async(e,t,r=Date.now())=>{if(e.length===0||t.length===0)return!1;const n=t.split(".");if(n.length!==3)return!1;const[s,i,c]=n;if(s!==wt||c.length===0)return!1;const l=Number(i);if(!Number.isFinite(l)||l<=r)return!1;let y;try{y=_r(c)}catch{return!1}return Ar(e,`${s}.${i}`,y)},v="/_lunora/admin/auth",Ir={INVITER_REQUIRED:400,ORG_SLUG_INVALID:400,ORG_SLUG_TAKEN:409,PASSWORD_TOO_LONG:400,PASSWORD_TOO_SHORT:400,USER_ALREADY_EXISTS:409,USER_NOT_FOUND:404},I=(e,t)=>{const r=e[t];if(typeof r!="string"||r==="")throw new a(`\`${t}\` is required`,{code:"BAD_REQUEST",status:400});return r},le=(e,t)=>{const r=e(t);if(r===void 0)throw new a(`\`${t}\` query parameter is required`,{code:"BAD_REQUEST",status:400});return r},qe=e=>{if(typeof e=="string"||Array.isArray(e)&&e.every(t=>typeof t=="string"))return e},X=(e,t)=>typeof e[t]=="string"?e[t]:void 0,Ye=(e,t)=>{const r=e[t];return typeof r=="object"&&r!==null&&!Array.isArray(r)?r:void 0},Xe=e=>{const t=e.permission;if(typeof t!="object"||t===null||Array.isArray(t))throw new a("`permission` object is required",{code:"BAD_REQUEST",status:400});const r={};for(const[n,s]of Object.entries(t))Array.isArray(s)&&s.every(i=>typeof i=="string")&&(r[n]=s);return r},Pr={[`${v}/capabilities`]:{build:()=>({}),http:"GET",method:"capabilities"},[`${v}/users`]:{build:({paging:e,query:t})=>{const r=t("sortDirection");return{...e,filterField:t("filterField"),filterValue:t("filterValue"),search:t("search"),searchField:t("searchField"),sortBy:t("sortBy"),sortDirection:r==="asc"||r==="desc"?r:void 0}},http:"GET",method:"listUsers"},[`${v}/sessions`]:{build:({paging:e,query:t})=>({...e,userId:t("userId")}),http:"GET",method:"listSessions"},[`${v}/accounts`]:{build:({query:e})=>({userId:le(e,"userId")}),http:"GET",method:"listAccounts"},[`${v}/passkeys`]:{build:({query:e})=>({userId:le(e,"userId")}),http:"GET",method:"listPasskeys"},[`${v}/organizations`]:{build:({paging:e})=>({...e}),http:"GET",method:"listOrganizations"},[`${v}/organizations/members`]:{build:({paging:e,query:t})=>({...e,organizationId:le(t,"organizationId")}),http:"GET",method:"listMembers"},[`${v}/organizations/invitations`]:{build:({paging:e,query:t})=>({...e,organizationId:le(t,"organizationId")}),http:"GET",method:"listInvitations"},[`${v}/config`]:{build:()=>({}),http:"GET",method:"config"},[`${v}/organizations/teams`]:{build:({paging:e,query:t})=>({...e,organizationId:le(t,"organizationId")}),http:"GET",method:"listTeams"},[`${v}/organizations/teams/members`]:{build:({paging:e,query:t})=>({...e,teamId:le(t,"teamId")}),http:"GET",method:"listTeamMembers"},[`${v}/organizations/roles`]:{build:({paging:e,query:t})=>({...e,organizationId:le(t,"organizationId")}),http:"GET",method:"listOrgRoles"},[`${v}/users/create`]:{build:({body:e})=>({data:typeof e.data=="object"&&e.data!==null&&!Array.isArray(e.data)?e.data:void 0,email:I(e,"email"),name:I(e,"name"),password:X(e,"password"),role:qe(e.role)}),http:"POST",method:"createUser"},[`${v}/users/update`]:{build:({body:e})=>{const{data:t}=e;if(typeof t!="object"||t===null||Array.isArray(t))throw new a("`data` object is required",{code:"BAD_REQUEST",status:400});return{data:t,userId:I(e,"userId")}},http:"POST",method:"updateUser"},[`${v}/users/role`]:{build:({body:e})=>{const t=qe(e.role);if(t===void 0||typeof t=="string"&&t.trim()==="")throw new a("`role` is required",{code:"BAD_REQUEST",status:400});return{role:t,userId:I(e,"userId")}},http:"POST",method:"setRole"},[`${v}/users/ban`]:{build:({body:e})=>({expiresInSeconds:typeof e.expiresInSeconds=="number"?e.expiresInSeconds:void 0,reason:X(e,"reason"),userId:I(e,"userId")}),http:"POST",method:"banUser"},[`${v}/users/unban`]:{build:({body:e})=>({userId:I(e,"userId")}),http:"POST",method:"unbanUser"},[`${v}/users/password`]:{build:({body:e})=>({newPassword:I(e,"newPassword"),userId:I(e,"userId")}),http:"POST",method:"setUserPassword",returns:"void"},[`${v}/users/remove`]:{build:({body:e})=>({userId:I(e,"userId")}),http:"POST",method:"removeUser",returns:"void"},[`${v}/users/impersonate`]:{build:({body:e})=>({userId:I(e,"userId")}),http:"POST",method:"impersonateUser"},[`${v}/sessions/revoke`]:{build:({body:e})=>({sessionId:I(e,"sessionId")}),http:"POST",method:"revokeUserSession",returns:"void"},[`${v}/sessions/revoke-all`]:{build:({body:e})=>({userId:I(e,"userId")}),http:"POST",method:"revokeUserSessions",returns:"void"},[`${v}/accounts/unlink`]:{build:({body:e})=>({accountId:I(e,"accountId"),userId:I(e,"userId")}),http:"POST",method:"unlinkAccount",returns:"void"},[`${v}/two-factor/disable`]:{build:({body:e})=>({userId:I(e,"userId")}),http:"POST",method:"disableTwoFactor",returns:"void"},[`${v}/passkeys/delete`]:{build:({body:e})=>({passkeyId:I(e,"passkeyId")}),http:"POST",method:"deletePasskey",returns:"void"},[`${v}/organizations/members/remove`]:{build:({body:e})=>({memberId:I(e,"memberId")}),http:"POST",method:"removeMember",returns:"void"},[`${v}/organizations/invitations/cancel`]:{build:({body:e})=>({invitationId:I(e,"invitationId")}),http:"POST",method:"cancelInvitation",returns:"void"},[`${v}/organizations/create`]:{build:({body:e})=>({logo:X(e,"logo"),metadata:Ye(e,"metadata"),name:I(e,"name"),ownerId:X(e,"ownerId"),slug:X(e,"slug")}),http:"POST",method:"createOrganization"},[`${v}/organizations/update`]:{build:({body:e})=>({logo:X(e,"logo"),metadata:Ye(e,"metadata"),name:X(e,"name"),organizationId:I(e,"organizationId"),slug:X(e,"slug")}),http:"POST",method:"updateOrganization"},[`${v}/organizations/remove`]:{build:({body:e})=>({organizationId:I(e,"organizationId")}),http:"POST",method:"deleteOrganization",returns:"void"},[`${v}/organizations/members/add`]:{build:({body:e})=>({organizationId:I(e,"organizationId"),role:X(e,"role"),userId:I(e,"userId")}),http:"POST",method:"addMember"},[`${v}/organizations/members/invite`]:{build:({body:e})=>({email:I(e,"email"),inviterId:X(e,"inviterId"),organizationId:I(e,"organizationId"),role:X(e,"role")}),http:"POST",method:"inviteMember"},[`${v}/organizations/members/role`]:{build:({body:e})=>{const t=qe(e.role);if(t===void 0||typeof t=="string"&&t.trim()==="")throw new a("`role` is required",{code:"BAD_REQUEST",status:400});return{memberId:I(e,"memberId"),role:t}},http:"POST",method:"updateMemberRole"},[`${v}/organizations/teams/create`]:{build:({body:e})=>({name:I(e,"name"),organizationId:I(e,"organizationId")}),http:"POST",method:"createTeam"},[`${v}/organizations/teams/update`]:{build:({body:e})=>({name:I(e,"name"),teamId:I(e,"teamId")}),http:"POST",method:"updateTeam"},[`${v}/organizations/teams/remove`]:{build:({body:e})=>({teamId:I(e,"teamId")}),http:"POST",method:"removeTeam",returns:"void"},[`${v}/organizations/teams/members/add`]:{build:({body:e})=>({teamId:I(e,"teamId"),userId:I(e,"userId")}),http:"POST",method:"addTeamMember"},[`${v}/organizations/teams/members/remove`]:{build:({body:e})=>({teamMemberId:I(e,"teamMemberId")}),http:"POST",method:"removeTeamMember",returns:"void"},[`${v}/organizations/roles/create`]:{build:({body:e})=>({organizationId:I(e,"organizationId"),permission:Xe(e),role:I(e,"role")}),http:"POST",method:"createOrgRole"},[`${v}/organizations/roles/update`]:{build:({body:e})=>({permission:Xe(e),roleId:I(e,"roleId")}),http:"POST",method:"updateOrgRole"},[`${v}/organizations/roles/remove`]:{build:({body:e})=>({roleId:I(e,"roleId")}),http:"POST",method:"deleteOrgRole",returns:"void"}},Nr=e=>{const t=async s=>{try{return await s()}catch(i){if(i instanceof a)throw i;const c=i,l=typeof c.code=="string"?c.code:"AUTH_ADMIN_ERROR";throw console.error("[lunora] auth admin operation failed:",i),new a("auth admin operation failed",{code:l,status:Ir[l]??500})}},r=async(s,i)=>{if(e.assertAdmin(s),s.method!==i.http)throw new a(`Auth admin endpoint requires ${i.http}`,{code:"METHOD_NOT_ALLOWED",status:405});const c=e.getAuthAdmin();if(c===void 0)throw new a("auth endpoints require an `authAdmin` on the worker",{code:"AUTH_NOT_CONFIGURED",status:400});const l=c[i.method];if(l===void 0)throw new a(`auth admin does not support \`${i.method}\``,{code:"AUTH_OP_NOT_SUPPORTED",status:400});const y=new URL(s.url),O={body:i.http==="POST"?await e.readJsonBody(s):{},paging:e.parsePaging(s),query:g=>e.queryParameter(y,g)},D=i.build(O),m=await t(()=>l(D));return Response.json(i.returns==="void"?{ok:!0}:m,{headers:{"content-type":"application/json"},status:200})},n={};for(const[s,i]of Object.entries(Pr))n[s]=c=>r(c,i);return n},Ze=500,Ur=(e,t,r)=>{if(typeof e!="object"||e===null||Array.isArray(e))throw new a("each batch call must be an object",{code:"BAD_REQUEST",status:400});const n=e;if(typeof n.functionPath!="string")throw new a("each batch call needs a string `functionPath`",{code:"BAD_REQUEST",status:400});if(n.functionPath.startsWith("__lunora_relation__:")||n.functionPath.startsWith("__lunora_admin__"))throw new a("reserved function path cannot be batched",{code:"FORBIDDEN",status:403});if(n.args!==void 0&&(typeof n.args!="object"||n.args===null||Array.isArray(n.args)))throw new a("each batch call `args` must be an object",{code:"BAD_REQUEST",status:400});return{entry:{args:n.args===void 0?{}:n.args,clientId:typeof n.clientId=="string"?n.clientId:void 0,clientSeq:typeof n.clientSeq=="number"?n.clientSeq:void 0,functionPath:n.functionPath,id:typeof n.id=="number"?n.id:t,mutationId:typeof n.mutationId=="string"?n.mutationId:void 0},shardKey:typeof n.shardKey=="string"?n.shardKey:r}},qr=(e,t)=>{if(e.length>Ze)throw new a(`RPC batch exceeds the ${String(Ze)}-call limit`,{code:"BAD_REQUEST",status:400});const r=new Map;for(const[n,s]of e.entries()){const{entry:i,shardKey:c}=Ur(s,n,t),l=r.get(c)??[];l.push(i),r.set(c,l)}return r},ge=1048576,ae=async(e,t=ge)=>{if(!e.body)return"";const r=e.body.getReader(),n=new TextDecoder;let s=0,i="";for(;;){const{done:c,value:l}=await r.read();if(c)break;if(l){if(s+=l.byteLength,s>t)throw await r.cancel().catch(()=>{}),new a("Body too large",{code:"PAYLOAD_TOO_LARGE",status:413});i+=n.decode(l,{stream:!0})}}return i+=n.decode(),i},$r=async(e,t=ge)=>{if(!e.body)return new ArrayBuffer(0);const r=e.body.getReader(),n=[];let s=0;for(;;){const{done:l,value:y}=await r.read();if(l)break;if(y){if(s+=y.byteLength,s>t)throw await r.cancel().catch(()=>{}),new a("Body too large",{code:"PAYLOAD_TOO_LARGE",status:413});n.push(y)}}const i=new Uint8Array(s);let c=0;for(const l of n)i.set(l,c),c+=l.byteLength;return i.buffer},Z=async(e,t=ge)=>{try{const r=await ae(e,t);return r===""?{}:JSON.parse(r)}catch(r){throw r instanceof a?r:new a("Request body must be valid JSON",{code:"BAD_REQUEST",status:400})}},Lr=new TextEncoder,Br=e=>{const t=JSON.stringify(e),r=Lr.encode(t);let n="";for(const s of r)n+=String.fromCodePoint(s);return btoa(n).replaceAll("+","-").replaceAll("/","_").replaceAll("=","")},xr=e=>{const t={g:0,s:{},v:1};if(typeof e!="string"||e.length===0)return t;try{const r=atob(e.replaceAll("-","+").replaceAll("_","/")),n=new Uint8Array(r.length);for(let l=0;l<r.length;l+=1)n[l]=r.codePointAt(l)??0;const s=JSON.parse(new TextDecoder().decode(n)),i=s.s&&typeof s.s=="object"?s.s:{},c={};for(const[l,y]of Object.entries(i))typeof y=="number"&&Number.isFinite(y)&&(c[l]=y);return{g:typeof s.g=="number"&&Number.isFinite(s.g)?s.g:0,s:c,v:1}}catch{return t}},Cr=e=>{const t=typeof e.table=="string"?e.table:"",r=typeof e.op=="string"?e.op:"",n=r==="delete"||r==="insert"||r==="update"?r:"upsert",s=typeof e.id=="string"?e.id:void 0;return{doc:(e.doc&&typeof e.doc=="object"?e.doc:void 0)??(s===void 0?{}:{_id:s}),op:n,table:t}},et=(e,t,r)=>{for(const n of t)e.push(Cr(n));return r!==void 0&&t.length>=r},jr="/_lunora/admin/export",Gr="/_lunora/admin/import",Kr="/_lunora/admin/sync",Mr="/_lunora/admin/connector/sync",Qr="/_lunora/admin/apply",Fr="/_lunora/admin/export-tap/run",zr=new TextEncoder,Wr=async e=>{let t;try{const s=await ae(e);t=s===""?{}:JSON.parse(s)}catch(s){throw s instanceof a?s:new a("Export body must be valid JSON",{code:"BAD_REQUEST",status:400})}const r=t??{};if(r.tables===void 0)return{tables:void 0};if(!Array.isArray(r.tables))throw new a("Export `tables` must be a string array",{code:"BAD_REQUEST",status:400});const n=[];for(const s of r.tables){if(typeof s!="string"||s.length===0)throw new a("Export `tables` entries must be non-empty strings",{code:"BAD_REQUEST",status:400});n.push(s)}return{tables:n}},Hr=e=>{const{applyGlobals:t,exportCursorStore:r,exportSinks:n,knownTables:s,queryCoordinator:i,requireAdminOption:c,resolveForwardContext:l,shardDO:y,streamExportRows:O,streamingImport:D,syncGlobals:m}=e,g=async(T,q)=>{const B=we(T,["POST"]);if(B)return B;const K=c(T,i,{code:"BAD_REQUEST",message:"Export endpoint requires a `queryCoordinator` on the worker"}),N=await Wr(T),{headers:M}=await l(T,q),Q=new ReadableStream({async pull(Y){const x=G=>{Y.enqueue(zr.encode(`${JSON.stringify(G)}
2
+ `))};try{await O(K,M,N.tables,x),Y.close()}catch(G){Y.error(G)}}});return new Response(Q,{headers:{"content-type":"application/x-ndjson"},status:200})},p=async(T,q)=>{const B=we(T,["POST"]);if(B)return B;const K=c(T,i,{code:"BAD_REQUEST",message:"Sync endpoint requires a `queryCoordinator` on the worker"}),N=await Z(T),M=typeof N.cursors=="object"&&N.cursors!==null?N.cursors:{},Q=typeof N.limit=="number"?N.limit:void 0,Y=typeof N.globalCursor=="number"?N.globalCursor:0,x=Array.isArray(N.tables)?N.tables.filter(ne=>typeof ne=="string"):void 0,{headers:G}=await l(T,q),J=x??s(),re=await K.orchestrateCdcSync(y,{cursors:M,headers:G,limit:Q,tables:J}),se=m?await m({limit:Q,sinceSeq:Y}):void 0;return Response.json({global:se,shards:re.shards},{status:200})},w=async(T,q)=>{const B=we(T,["POST"]);if(B)return B;const K=c(T,i,{code:"BAD_REQUEST",message:"Connector sync endpoint requires a `queryCoordinator` on the worker"}),N=await Z(T),M=xr(N.cursor),Q=typeof N.limit=="number"&&N.limit>0?N.limit:void 0,Y=Array.isArray(N.tables)?N.tables.filter(ee=>typeof ee=="string"):void 0,{headers:x}=await l(T,q),G=Y??s(),J=await K.orchestrateCdcSync(y,{cursors:M.s,headers:x,limit:Q,tables:G}),re=[],se={...M.s};let ne=!1;for(const ee of J.shards)ne=et(re,ee.changes??[],Q)||ne,se[ee.shardKey]=ee.cursor;let he=M.g;if(m){const ee=await m({limit:Q,sinceSeq:M.g});ne=et(re,ee.changes,Q)||ne,he=ee.cursor}const me=Br({g:he,s:se,v:1}),be={changes:re,hasMore:ne,nextCursor:me};return Response.json(be,{status:200})},_=async(T,q)=>{const B=we(T,["POST"]);if(B)return B;const K=c(T,i,{code:"BAD_REQUEST",message:"Apply endpoint requires a `queryCoordinator` on the worker"}),N=await Z(T),M=(Array.isArray(N.batches)?N.batches:[]).map(J=>J).filter(J=>J!==null&&typeof J=="object"&&typeof J.shardKey=="string"&&Array.isArray(J.changes)),Q=Array.isArray(N.globalChanges)?N.globalChanges:[],{headers:Y}=await l(T,q),x=await K.orchestrateApplyCdc(y,{batches:M,headers:Y}),G=Q.length>0&&t?await t({changes:Q}):0;return Response.json({applied:x.applied+G,failed:x.failed,ok:x.ok},{status:200})},R=async(T,q)=>{const B=we(T,["POST"]);if(B)return B;c(T,i,{code:"BAD_REQUEST",message:"Import endpoint requires a `queryCoordinator` on the worker"});const{headers:K}=await l(T,q),N=await D(T,K);return Response.json(N,{headers:{"content-type":"application/json"},status:200})},P=async(T,q)=>{const B=we(T,["POST"]);if(B)return B;const K=c(T,i,{code:"BAD_REQUEST",message:"Export-tap endpoint requires a `queryCoordinator` on the worker"});if(n===void 0||Object.keys(n).length===0||r===void 0)throw new a("Export-tap endpoint requires `exportSinks` + `exportCursorStore` on the worker",{code:"EXPORT_TAP_NOT_CONFIGURED",status:400});const N=await Z(T),M=typeof N.sink=="string"?N.sink:void 0,Q=typeof N.limit=="number"&&N.limit>0?N.limit:void 0,Y=Array.isArray(N.tables)?N.tables.filter(se=>typeof se=="string"):void 0;if(M===void 0)throw new a("Export-tap `sink` must name a configured sink",{code:"BAD_REQUEST",status:400});const x=n[M];if(x===void 0)throw new a(`Export-tap sink "${M}" is not configured`,{code:"NOT_FOUND",status:404});const{headers:G}=await l(T,q),J=Y??s(),re=await cr({coordinator:K,cursorStore:r,headers:G,limit:Q,shardDO:y,sink:x,tables:J});return Response.json(re,{headers:{"content-type":"application/json"},status:200})};return{[Qr]:_,[Mr]:w,[jr]:g,[Fr]:P,[Gr]:R,[Kr]:p}},mt=e=>[],Jr=(e,t)=>{const r=[],n=[];if(t&&t.length>0)for(const s of t)e.resolveTableSharding?.(s)?.mode.kind==="global"?n.push(s):r.push(s);return{globalTables:n,shardLocalTables:r}},Vr=async(e,t,r,n,s,i,c)=>{if(n!==void 0&&s.length===0)return;const l=n===void 0?[]:s,y=n===void 0?mt():[],O=l.length>0?l:y,D=await t.orchestrateExport(c,{args:{tables:l},headers:r,tables:O});for(const m of D.shards)if(!m.error)for(const g of m.rows??[])i(g)},tt=async(e,t,r,n,s,i)=>{const{globalTables:c,shardLocalTables:l}=Jr(e,n);await Vr(e,t,r,n,l,s,i);const y=e.exportGlobals;if((n===void 0||c.length>0)&&y){const O=n===void 0?[]:c;for await(const D of y({tables:O}))s(D)}},Yr=(e,t)=>{let r;try{r=JSON.parse(e)}catch{return{error:{code:"BAD_ROW",line:t,message:"line is not valid JSON",table:""},ok:!1}}if(!r||typeof r!="object"||Array.isArray(r))return{error:{code:"BAD_ROW",line:t,message:"row must be a JSON object",table:""},ok:!1};const n=r;return typeof n.table!="string"||n.table.length===0?{error:{code:"BAD_ROW",line:t,message:"row is missing `table`",table:""},ok:!1}:!n.doc||typeof n.doc!="object"||Array.isArray(n.doc)?{error:{code:"BAD_ROW",line:t,message:"row is missing or malformed `doc`",table:n.table},ok:!1}:{doc:n.doc,ok:!0,table:n.table}},Xr=(e,t,r,n,s)=>{if(r?.mode.kind==="shardBy"&&typeof r.mode.field=="string"){const i=e[r.mode.field];return i==null?{error:{code:"BAD_ROW",line:s,message:`row missing shard field "${r.mode.field}" for table "${t}"`,table:t},ok:!1}:{ok:!0,shardKey:typeof i=="string"?i:JSON.stringify(i)}}return{ok:!0,shardKey:n}},Zr=async(e,t,r)=>{if(!e.body)throw new a("Import endpoint requires a request body",{code:"BAD_REQUEST",status:400});const n=[],s=[],i=new Map;let c=0;const l=e.body.getReader(),y=new TextDecoder;let O="",D=0;const m=g=>{c+=1;const p=g.trim();if(p.length===0)return;const w=Yr(p,c);if(!w.ok){n.push(w.error);return}const{doc:_,table:R}=w,P=t.resolveTableSharding?.(R);if(P?.mode.kind==="global"){s.push({doc:_,line:c,table:R});return}const T=Xr(_,R,P,r,c);if(!T.ok){n.push(T.error);return}const q=i.get(T.shardKey);q?q.rows.push({doc:_,table:R}):i.set(T.shardKey,{rows:[{doc:_,table:R}],shardKey:T.shardKey,startLine:c})};for(;;){const{done:g,value:p}=await l.read();if(g)break;if(p&&(D+=p.byteLength,D>ge))throw await l.cancel().catch(()=>{}),new a("Body too large",{code:"PAYLOAD_TOO_LARGE",status:413});O+=y.decode(p,{stream:!0});let w=O.indexOf(`
3
+ `);for(;w!==-1;){const _=O.slice(0,w);O=O.slice(w+1),m(_),w=O.indexOf(`
4
+ `)}}return O.length>0&&m(O),{errors:n,globalRows:s,perShard:i}},rt=(e,t)=>{for(const[r,n]of Object.entries(t.inserted))e.inserted[r]=(e.inserted[r]??0)+n;for(const r of t.errors)e.errors.push({...r});e.conflicts+=t.conflicts},en=async(e,t,r,n)=>{const s=t.defaultShardKey??"__root__",{errors:i,globalRows:c,perShard:l}=await Zr(e,t,s),y={conflicts:0,errors:i,inserted:{}};if(l.size>0){const O=t.queryCoordinator;if(!O)throw new a("Import endpoint requires a `queryCoordinator` on the worker",{code:"BAD_REQUEST",status:400});const D=await O.orchestrateImport(n,{batches:[...l.values()],headers:r});rt(y,D)}if(c.length>0)if(t.importGlobals){const O=c[0]?.line??1,D=await t.importGlobals({rows:c,startLine:O});rt(y,D)}else for(const O of c)y.errors.push({code:"GLOBAL_NOT_CONFIGURED",line:O.line,message:`row targets global table "${O.table}" but no \`importGlobals\` is configured`,table:O.table});return{conflicts:y.conflicts,errors:y.errors,inserted:y.inserted}},$e=e=>typeof e=="object"&&e!==null?e:{},Le=e=>typeof e.kind=="string"?e.kind:"unknown",tn=(e,t)=>{let r=$e(t),n=!1;Le(r)==="optional"&&(n=!0,r=$e(r._meta?.inner));const s=Le(r),i=r._meta??{},c={kind:s,name:e,optional:n};if(s==="id"&&typeof i.tableName=="string"&&(c.table=i.tableName),s==="array"){const l=Le($e(i.inner));l!=="unknown"&&(c.element=l)}return c},rn=e=>typeof e!="object"||e===null?[]:Object.entries(e).map(([t,r])=>tn(t,r)).toSorted((t,r)=>t.name.localeCompare(r.name)),nn="/_lunora/admin/functions",on="/_lunora/admin/cron-jobs",an="/_lunora/admin/openapi",sn="/_lunora/admin/openrpc",dn="/_lunora/admin/global/tables",un="/_lunora/admin/global/table",cn="/_lunora/admin/global/facet",nt=e=>{if(e===void 0||e==="")return;let t;try{t=JSON.parse(e)}catch{return}if(!Array.isArray(t))return;const r=t.flatMap(n=>{if(typeof n!="object"||n===null||typeof n.column!="string")return[];const{column:s,value:i}=n;return[{column:s,value:i}]});return r.length===0?void 0:r},ln=Object.freeze({info:{description:'No OpenAPI spec is configured on this worker. Run `lunora codegen`, then wire the generated module to `createWorker`: `import { openApiSpec } from "./lunora/_generated/openapi"`.',title:"Lunora API",version:"0.0.0"},openapi:"3.1.0",paths:{}}),hn=Object.freeze({info:{description:'No OpenRPC spec is configured on this worker. Run `lunora codegen --api-spec openrpc` (or `both`), then wire the generated module to `createWorker`: `import { openRpcSpec } from "./lunora/_generated/openrpc"`.',title:"Lunora RPC",version:"0.0.0"},methods:[],openrpc:"1.3.2"}),pn=e=>{const{assertAdmin:t,options:r,parsePaging:n,queryParameter:s,requireAdminOption:i}=e,c=p=>{if(p.method!=="GET")throw new a("Functions endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});const w=i(p,r.functions,{code:"FUNCTIONS_NOT_CONFIGURED",message:"functions endpoint requires a `functions` registry on the worker"}),_=Object.entries(w).flatMap(([R,P])=>P.visibility==="internal"||P.kind==="stream"?[]:[{args:rn(P.args),kind:P.kind,path:R}]).toSorted((R,P)=>R.path.localeCompare(P.path));return Response.json({functions:_},{headers:{"content-type":"application/json"},status:200})},l=p=>{if(p.method!=="GET")throw new a("Cron-jobs endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});const w=i(p,r.cronJobs,{code:"CRON_JOBS_NOT_CONFIGURED",message:"cron-jobs endpoint requires a `cronJobs` map on the worker"}),_=Object.entries(w).flatMap(([R,P])=>P.map(T=>({args:T.args,cron:R,functionPath:T.functionPath,name:T.name,shardKey:T.shardKey,workflow:T.workflow}))).toSorted((R,P)=>R.name.localeCompare(P.name));return Response.json({jobs:_},{headers:{"content-type":"application/json"},status:200})},y=p=>{if(p.method!=="GET")throw new a("OpenAPI endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});return t(p),Response.json(r.openApiSpec??ln,{headers:{"content-type":"application/json"},status:200})},O=p=>{if(p.method!=="GET")throw new a("OpenRPC endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});return t(p),Response.json(r.openRpcSpec??hn,{headers:{"content-type":"application/json"},status:200})},D=async p=>{if(p.method!=="GET")throw new a("Global-tables endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});const w=i(p,r.globalIntrospector,{code:"GLOBALS_NOT_CONFIGURED",message:"global endpoints require a `globalIntrospector` on the worker"});return Response.json(await w.listTables(),{headers:{"content-type":"application/json"},status:200})},m=async p=>{if(p.method!=="GET")throw new a("Global-table endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});const w=i(p,r.globalIntrospector,{code:"GLOBALS_NOT_CONFIGURED",message:"global endpoints require a `globalIntrospector` on the worker"}),_=new URL(p.url),R=s(_,"table");if(R===void 0)throw new a("Global-table endpoint requires a `table` query param",{code:"BAD_REQUEST",status:400});const P=await w.readTablePage({...n(p),filters:nt(s(_,"filters")),table:R});return Response.json(P,{headers:{"content-type":"application/json"},status:200})},g=async p=>{if(p.method!=="GET")throw new a("Global-facet endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});const w=i(p,r.globalIntrospector,{code:"GLOBALS_NOT_CONFIGURED",message:"global endpoints require a `globalIntrospector` on the worker"}),_=new URL(p.url),R=s(_,"table"),P=s(_,"column");if(R===void 0||P===void 0)throw new a("Global-facet endpoint requires `table` and `column` query params",{code:"BAD_REQUEST",status:400});const T=s(_,"limit"),q=T===void 0?void 0:Number(T),B=await w.facetColumn({column:P,filters:nt(s(_,"filters")),limit:q!==void 0&&Number.isFinite(q)?q:void 0,table:R});return Response.json(B,{headers:{"content-type":"application/json"},status:200})};return{[on]:l,[nn]:c,[cn]:g,[un]:m,[dn]:D,[an]:y,[sn]:O}},fn="/_lunora/admin/kv/namespaces",wn="/_lunora/admin/kv/keys",yt="/_lunora/admin/kv/value",gt=32*1048576,ot=60,mn=e=>{const{readJsonBody:t,requireAdminOption:r}=e,n=m=>r(m,e.kvIntrospector,{code:"KV_NOT_CONFIGURED",message:"KV endpoints require a `kvIntrospector` on the worker"}),s=m=>Response.json(m,{headers:{"content-type":"application/json"},status:200}),i=(m,g)=>{const p=new URL(m.url),w=p.searchParams.get("namespace")??"",_=p.searchParams.get("key")??"";if(w==="")throw new a(`KV-value ${g} request requires a \`namespace\` query parameter`,{code:"BAD_REQUEST",status:400});if(_==="")throw new a(`KV-value ${g} request requires a \`key\` query parameter`,{code:"BAD_REQUEST",status:400});return{key:_,namespace:w}},c=async(m,g)=>{if(!(await m.listNamespaces()).some(p=>p.binding===g))throw new a(`Unknown KV namespace binding \`${g}\``,{code:"NOT_FOUND",status:404})},l=async m=>{if(m.method!=="GET")throw new a("KV-namespaces endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});return s({namespaces:await n(m).listNamespaces()})},y=async m=>{if(m.method!=="GET")throw new a("KV-keys endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});const g=n(m),p=new URL(m.url),w=p.searchParams.get("namespace")??"";if(w==="")throw new a("KV-keys request requires a `namespace` query parameter",{code:"BAD_REQUEST",status:400});const _=p.searchParams.get("prefix")??void 0,R=p.searchParams.get("cursor")??void 0,P=p.searchParams.get("limit"),T=P===null?void 0:Number.parseInt(P,10);if(T!==void 0&&(!Number.isInteger(T)||T<1))throw new a("KV-keys `limit` must be a positive integer",{code:"BAD_REQUEST",status:400});const q=T===void 0?void 0:Math.min(T,1e3);return await c(g,w),s(await g.listKeys({cursor:R,limit:q,namespace:w,prefix:_}))},O={DELETE:async m=>{const g=n(m),p=i(m,"DELETE");return await c(g,p.namespace),await g.deleteKey(p),s({deleted:!0})},GET:async m=>{const g=n(m),p=i(m,"GET");return await c(g,p.namespace),s(await g.getValue(p))},PUT:async m=>{const g=n(m),p=await t(m,gt);if(typeof p.namespace!="string"||p.namespace==="")throw new a("KV-value PUT request requires a `namespace` string",{code:"BAD_REQUEST",status:400});if(typeof p.key!="string"||p.key==="")throw new a("KV-value PUT request requires a `key` string",{code:"BAD_REQUEST",status:400});if(typeof p.value!="string")throw new a("KV-value PUT request requires a `value` string",{code:"BAD_REQUEST",status:400});if(p.expirationTtl!==void 0&&(typeof p.expirationTtl!="number"||!Number.isInteger(p.expirationTtl)||p.expirationTtl<ot))throw new a("KV-value PUT `expirationTtl` must be an integer ≥ 60",{code:"BAD_REQUEST",status:400});const w=Math.floor(Date.now()/1e3)+ot;if(p.expiration!==void 0&&(typeof p.expiration!="number"||!Number.isInteger(p.expiration)||p.expiration<w))throw new a("KV-value PUT `expiration` must be a Unix-seconds timestamp at least 60 seconds in the future",{code:"BAD_REQUEST",status:400});return await c(g,p.namespace),await g.putValue({expiration:p.expiration,expirationTtl:p.expirationTtl,key:p.key,metadata:p.metadata,namespace:p.namespace,value:p.value}),s({ok:!0})}},D=m=>{const g=O[m.method];if(!g)throw new a("KV-value endpoint requires GET, PUT, or DELETE",{code:"METHOD_NOT_ALLOWED",status:405});return g(m)};return{[fn]:l,[wn]:y,[yt]:D}},yn="/_lunora/migrate",gn="/_lunora/admin/pitr",bn="/_lunora/admin/rank",On="/_lunora/admin/rankpage",En="/_lunora/admin/shard-traffic",Tn=new Set(["__lunora_admin__:migrationStatus","__lunora_admin__:runMigration"]),_n=new Set(["__lunora_admin__:getPitrBookmark","__lunora_admin__:pitrRestore"]),Rn=async e=>{let t;try{const n=await ae(e);t=n===""?{}:JSON.parse(n)}catch(n){throw n instanceof a?n:new a("Migration body must be valid JSON",{code:"BAD_REQUEST",status:400})}const r=t??{};if(typeof r.table!="string"||r.table.length===0)throw new a("Migration request is missing `table`",{code:"BAD_REQUEST",status:400});if(typeof r.functionPath!="string"||!Tn.has(r.functionPath))throw new a("Migration request `functionPath` must be a migration admin op",{code:"BAD_REQUEST",status:400});return{args:r.args??{},functionPath:r.functionPath,table:r.table}},Sn=async e=>{let t;try{const n=await ae(e);t=n===""?{}:JSON.parse(n)}catch(n){throw n instanceof a?n:new a("Rank body must be valid JSON",{code:"BAD_REQUEST",status:400})}const r=t??{};if(typeof r.table!="string"||r.table.length===0)throw new a("Rank request is missing `table`",{code:"BAD_REQUEST",status:400});if(typeof r.index!="string"||r.index.length===0)throw new a("Rank request is missing `index`",{code:"BAD_REQUEST",status:400});if(typeof r.partitionKey!="string")throw new a("Rank request `partitionKey` must be a string",{code:"BAD_REQUEST",status:400});if(typeof r.rowId!="string"||r.rowId.length===0)throw new a("Rank request is missing `rowId`",{code:"BAD_REQUEST",status:400});if(!Array.isArray(r.sortValues))throw new a("Rank request `sortValues` must be an array",{code:"BAD_REQUEST",status:400});return{index:r.index,partitionKey:r.partitionKey,rowId:r.rowId,sortValues:r.sortValues,table:r.table}},An=e=>{if(e!==void 0){if(!Array.isArray(e)||e.some(t=>t!=="asc"&&t!=="desc"))throw new a('Rank page request `directions` must be an array of "asc"|"desc"',{code:"BAD_REQUEST",status:400});return e}},Dn=e=>{if(typeof e.table!="string"||e.table.length===0)throw new a("Rank page request is missing `table`",{code:"BAD_REQUEST",status:400});if(typeof e.index!="string"||e.index.length===0)throw new a("Rank page request is missing `index`",{code:"BAD_REQUEST",status:400});if(e.partitionKey!==void 0&&typeof e.partitionKey!="string")throw new a("Rank page request `partitionKey` must be a string",{code:"BAD_REQUEST",status:400});if(e.take!==void 0&&(typeof e.take!="number"||!Number.isFinite(e.take)))throw new a("Rank page request `take` must be a number",{code:"BAD_REQUEST",status:400});if(e.cursor!==void 0&&e.cursor!==null&&typeof e.cursor!="string")throw new a("Rank page request `cursor` must be a string or null",{code:"BAD_REQUEST",status:400})},vn=async e=>{let t;try{const s=await ae(e);t=s===""?{}:JSON.parse(s)}catch(s){throw s instanceof a?s:new a("Rank page body must be valid JSON",{code:"BAD_REQUEST",status:400})}const r=t??{};Dn(r);const n=An(r.directions);return{cursor:typeof r.cursor=="string"?r.cursor:null,directions:n,index:r.index,partitionKey:typeof r.partitionKey=="string"?r.partitionKey:void 0,table:r.table,take:typeof r.take=="number"?r.take:void 0}},kn=async e=>{let t;try{const n=await ae(e);t=n===""?{}:JSON.parse(n)}catch(n){throw n instanceof a?n:new a("Shard-traffic body must be valid JSON",{code:"BAD_REQUEST",status:400})}const r=t??{};if(typeof r.table!="string"||r.table.length===0)throw new a("Shard-traffic request is missing `table`",{code:"BAD_REQUEST",status:400});return{table:r.table}},In=async e=>{const t=await Z(e);if(typeof t.functionPath!="string"||!_n.has(t.functionPath))throw new a("PITR request `functionPath` must be a PITR admin op",{code:"BAD_REQUEST",status:400});if(t.shardKey!==void 0&&typeof t.shardKey!="string")throw new a("PITR `shardKey` must be a string",{code:"BAD_REQUEST",status:400});return{args:t.args??{},functionPath:t.functionPath,shardKey:t.shardKey}},Pn=e=>{const{defaultShard:t,forwardToShard:r,isAdmin:n,queryCoordinator:s,resolveForwardContext:i,shardDO:c}=e,l=async(g,p)=>{if(g.method!=="POST")throw new a("Migration endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});if(!n(g))throw new a("Admin auth required",{code:"FORBIDDEN",status:403});if(!s)throw new a("Migration endpoint requires a `queryCoordinator` on the worker",{code:"BAD_REQUEST",status:400});const w=await Rn(g),{headers:_}=await i(g,p),R=await s.orchestrateMigration(c,{args:w.args,functionPath:w.functionPath,headers:_,table:w.table});return Response.json(R,{headers:{"content-type":"application/json"},status:200})},y=async(g,p)=>{if(g.method!=="POST")throw new a("Rank endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});if(!n(g))throw new a("Admin auth required",{code:"FORBIDDEN",status:403});if(!s)throw new a("Rank endpoint requires a `queryCoordinator` on the worker",{code:"BAD_REQUEST",status:400});const w=await Sn(g),{headers:_}=await i(g,p),R=await s.orchestrateRank(c,{headers:_,index:w.index,partitionKey:w.partitionKey,rowId:w.rowId,sortValues:w.sortValues,table:w.table});return Response.json(R,{headers:{"content-type":"application/json"},status:200})},O=async(g,p)=>{if(g.method!=="POST")throw new a("Rank page endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});if(!n(g))throw new a("Admin auth required",{code:"FORBIDDEN",status:403});if(!s)throw new a("Rank page endpoint requires a `queryCoordinator` on the worker",{code:"BAD_REQUEST",status:400});const w=await vn(g),{headers:_}=await i(g,p),R=await s.orchestrateRankPage(c,{...w,headers:_});return Response.json(R,{headers:{"content-type":"application/json"},status:200})},D=async(g,p)=>{if(g.method!=="POST")throw new a("Shard-traffic endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});if(!n(g))throw new a("Admin auth required",{code:"FORBIDDEN",status:403});if(!s)throw new a("Shard-traffic endpoint requires a `queryCoordinator` on the worker",{code:"BAD_REQUEST",status:400});const w=await kn(g),{headers:_}=await i(g,p),R=await s.orchestrateShardTraffic(c,{headers:_,table:w.table});return Response.json(R,{headers:{"content-type":"application/json"},status:200})},m=async(g,p)=>{if(g.method!=="POST")throw new a("PITR endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});if(!n(g))throw new a("admin PITR endpoint requires a valid admin bearer",{code:"ADMIN_FORBIDDEN",status:403});const w=await In(g),{headers:_}=await i(g,p),R=new Request("https://shard.internal/rpc",{body:JSON.stringify({args:w.args,functionPath:w.functionPath}),headers:_,method:"POST"});return r(c,w.shardKey??t,R)};return{[yn]:l,[gn]:m,[bn]:y,[On]:O,[En]:D}},Nn=1,Un=0,qn=32,$n=512,Ln=/^[a-z][\d_a-z*/-]{0,255}(?:@[a-z][\d_a-z*/-]{0,13})?=[\u0020-\u002B\u002D-\u003C\u003E-\u007E]{1,256}$/,Bn=e=>{if(e==null)return;const t=e.trim();if(t.length===0||t.length>$n)return;const r=t.split(",");if(!(r.length>qn)){for(const n of r)if(!Ln.test(n.trim()))return;return t}},xn=e=>{const t=nr(e.headers.get("traceparent"));if(t===void 0)return;const r=Bn(e.headers.get("tracestate"));return{parentSpanId:t.parentSpanId,sampled:t.sampled,traceId:t.traceId,...r===void 0?{}:{traceState:r}}},Cn=(e,t={})=>{const r=xn(e),n=t.trustInbound===!0?r:void 0,s=Re(8),i=n?.traceId??Re(16),c=mr(t.sampling,n===void 0?s:i),l=c.isTraced&&(n===void 0||n.sampled);return{decision:c,ignoredUpstream:r!==void 0&&n===void 0,trace:{sampled:l,spanId:s,traceFlags:l?Nn:Un,traceId:i,...n?.parentSpanId===void 0?{}:{parentSpanId:n.parentSpanId},...n?.traceState===void 0?{}:{traceState:n.traceState}}}},jn=(e,t)=>{t.traceparent=rr(e.traceId,e.spanId,e.sampled),e.traceState!==void 0&&(t.tracestate=e.traceState)},Gn=(e,t)=>{let r;return()=>{if(r===void 0){const n=ir(e),s=t===void 0?void 0:t.cf;r=or(sr(n),ar(n,s))}return r}},Kn="/_lunora/admin/scheduled",Mn="/_lunora/admin/scheduled/status",Qn="/_lunora/admin/scheduled/ws",Fn="/_lunora/admin/scheduled/cancel",zn="/_lunora/admin/scheduled/dead",Wn="/_lunora/admin/scheduled/dead/retry",Hn="/_lunora/admin/scheduled/dead/cancel",Jn=e=>{const{checkWsAdmin:t,requireSchedulerNamespace:r,resolveSchedulerStub:n,schedulerInstanceName:s}=e,i=async m=>{if(m.method!=="GET")throw new a("Scheduled-list endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});return n(m).fetch(new Request("https://scheduler.internal/list",{method:"GET"}))},c=async m=>{if(m.method!=="GET")throw new a("Scheduler-status endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});return n(m).fetch(new Request("https://scheduler.internal/status",{method:"GET"}))},l=async m=>{if(m.headers.get("Upgrade")!=="websocket")throw new a("WebSocket upgrade header missing",{code:"BAD_REQUEST",status:426});if(!await t(m))throw new a("admin authorization required",{code:"ADMIN_FORBIDDEN",status:403});const g=r();return Se(g,s).fetch(new Request("https://scheduler.internal/ws",{headers:{Upgrade:"websocket"}}))},y=async m=>{if(m.method!=="POST")throw new a("Scheduled-cancel endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});const g=n(m),p=await m.json().catch(()=>{});if(typeof p?.id!="string"||p.id==="")throw new a("Scheduled-cancel requires a string `id`",{code:"BAD_REQUEST",status:400});return g.fetch(new Request("https://scheduler.internal/cancel",{body:JSON.stringify({id:p.id}),headers:{"content-type":"application/json"},method:"POST"}))},O=async m=>{if(m.method!=="GET")throw new a("Scheduled dead-letter endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});return n(m).fetch(new Request("https://scheduler.internal/dead",{method:"GET"}))},D=m=>async g=>{if(g.method!=="POST")throw new a("Scheduled dead-letter action requires POST",{code:"METHOD_NOT_ALLOWED",status:405});const p=n(g),w=await g.json().catch(()=>{});if(typeof w?.id!="string"||w.id==="")throw new a("Scheduled dead-letter action requires a string `id`",{code:"BAD_REQUEST",status:400});return p.fetch(new Request(`https://scheduler.internal${m}`,{body:JSON.stringify({id:w.id}),headers:{"content-type":"application/json"},method:"POST"}))};return{[Fn]:y,[Hn]:D("/dead/cancel"),[zn]:O,[Wn]:D("/dead/retry"),[Kn]:i,[Mn]:c,[Qn]:l}},Vn="/_lunora/admin/storage",Yn="/_lunora/admin/storage/url",Xn="/_lunora/admin/storage/buckets",Zn=10080*60,eo=e=>{const{assertAdmin:t,parsePaging:r,queryParameter:n,readBodyBytes:s,requireAdminOption:i,storage:c}=e,l=w=>{const _=n(w,"key");if(_===void 0)throw new a("Storage endpoint requires a `key` query parameter",{code:"BAD_REQUEST",status:400});return _},y=async w=>{const _=i(w,c.storageList,{code:"STORAGE_NOT_CONFIGURED",message:"storage endpoint requires a `storageList` function on the worker"}),R=new URL(w.url),P=await _(n(R,"prefix"),{bucket:n(R,"bucket"),cursor:n(R,"cursor"),...r(w)});return Response.json(P,{headers:{"content-type":"application/json"},status:200})},O=w=>{if(w.method!=="GET")throw new a("Storage-buckets endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});return t(w),Response.json({buckets:c.storageBuckets??[]},{headers:{"content-type":"application/json"},status:200})},D=async w=>{const _=i(w,c.storageDelete,{code:"STORAGE_DELETE_NOT_CONFIGURED",message:"storage delete requires a `storageDelete` function on the worker"}),R=new URL(w.url),P=l(R);return await _(P,{bucket:n(R,"bucket")}),Response.json({deleted:!0,key:P},{headers:{"content-type":"application/json"},status:200})},m=async w=>{const _=i(w,c.storageUpload,{code:"STORAGE_UPLOAD_NOT_CONFIGURED",message:"storage upload requires a `storageUpload` function on the worker"}),R=new URL(w.url),P=l(R),T=await s(w),q=w.headers.get("content-type"),B=q===null||q===""?void 0:q,K=await _(P,T,{bucket:n(R,"bucket"),contentType:B});return Response.json(K,{headers:{"content-type":"application/json"},status:200})},g=async w=>{switch(w.method){case"DELETE":return D(w);case"GET":return y(w);case"POST":case"PUT":return m(w);default:throw new a("Storage endpoint requires GET, PUT, POST, or DELETE",{code:"METHOD_NOT_ALLOWED",status:405})}},p=async w=>{if(w.method!=="GET")throw new a("Storage URL endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});const _=i(w,c.storageSignedUrl,{code:"STORAGE_URL_NOT_CONFIGURED",message:"storage URL endpoint requires a `storageSignedUrl` function on the worker"}),R=new URL(w.url),P=l(R),T=Number(n(R,"expiresIn")??""),q=Number.isFinite(T)&&T>0?Math.min(T,Zn):void 0,B=await _(P,{bucket:n(R,"bucket"),expiresInSeconds:q});return Response.json({key:P,url:B},{headers:{"content-type":"application/json"},status:200})};return{[Xn]:O,[Vn]:g,[Yn]:p}},to=(e,...t)=>{let r=e.cf;for(const n of t){if(typeof r!="object"||r===null)return;r=r[n]}return typeof r=="string"?r:void 0},ro={mtls:e=>to(e,"tlsClientAuth","certVerified")==="SUCCESS"},no=e=>e===void 0||e===!1?()=>!1:e===!0?()=>!0:typeof e=="function"?e:Object.entries(ro).find(([t])=>t===e)?.[1]??(()=>!1),oo=e=>{if(e!==void 0)return()=>{};let t=!1;return()=>{t||(t=!0,console.warn('[lunora] Ignored an inbound `traceparent`, so this request starts a new trace instead of joining the caller\'s. That is the safe default: the header is caller-supplied, and trusting it lets any client choose which trace its spans and logs join. If this worker sits behind a gateway, service mesh, or Cloudflare Access that sets `traceparent` itself, set `trustInboundTraceContext: true` on createWorker() (or `"mtls"` to trust only edge-verified client certificates). Set it to `false` to keep this behaviour and silence this message.'))}},ao="/_lunora/admin/vector/indexes",so="/_lunora/admin/vector/query",io=e=>{const{readJsonBody:t,requireAdminOption:r}=e,n=async i=>{if(i.method!=="GET")throw new a("Vector-indexes endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});const c=r(i,e.vectorIntrospector,{code:"VECTORS_NOT_CONFIGURED",message:"vector endpoints require a `vectorIntrospector` on the worker"});return Response.json({indexes:await c.listIndexes()},{headers:{"content-type":"application/json"},status:200})},s=async i=>{if(i.method!=="POST")throw new a("Vector-query endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});const c=r(i,e.vectorIntrospector,{code:"VECTORS_NOT_CONFIGURED",message:"vector endpoints require a `vectorIntrospector` on the worker"});if(c.queryIndex===void 0)throw new a("vector index querying is not enabled on this worker",{code:"VECTOR_QUERY_UNSUPPORTED",status:400});const l=await t(i);if(typeof l.name!="string"||l.name==="")throw new a("Vector-query request requires a `name` string",{code:"BAD_REQUEST",status:400});if(typeof l.text!="string"||l.text==="")throw new a("Vector-query request requires a `text` string",{code:"BAD_REQUEST",status:400});if(l.topK!==void 0&&(typeof l.topK!="number"||!Number.isInteger(l.topK)||l.topK<1))throw new a("Vector-query `topK` must be a positive integer",{code:"BAD_REQUEST",status:400});const y=await c.queryIndex({name:l.name,text:l.text,topK:l.topK});return Response.json(y,{headers:{"content-type":"application/json"},status:200})};return{[ao]:n,[so]:s}},uo="/_lunora/admin/workflows/instances",co="/_lunora/admin/workflows/instance",lo="/_lunora/admin/workflows/status",ho={complete:!0,errored:!0,paused:!0,queued:!0,running:!0,terminated:!0,unknown:!0,waiting:!0,waitingForPause:!0},po=e=>e!==null&&Object.hasOwn(ho,e)?e:void 0,at=(e,t)=>{const r=e.searchParams.get(t);if(r===null)return;const n=Number(r);return Number.isInteger(n)&&n>0?n:void 0},Be=(e,t)=>{const r=e.searchParams.get(t);if(r===null||r==="")throw new a(`Workflows admin endpoint requires a \`${t}\` query parameter`,{code:"BAD_REQUEST",status:400});return r},st=()=>{throw new a("Workflow inspection is unconfigured. Set CLOUDFLARE_ACCOUNT_ID + CLOUDFLARE_API_TOKEN in your .dev.vars to enable it.",{code:"WORKFLOWS_NOT_CONFIGURED",status:501})},fo=e=>{const{assertAdmin:t,resolveWorkflowsClient:r}=e,n=async(c,l,y)=>{if(c.method!=="GET")throw new a("Workflows instances endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});t(c);const O=r(l);if(!O)return Response.json({configured:!1,instances:[],page:1,perPage:0,totalCount:0});const D=Be(y,"name"),m=po(y.searchParams.get("status"));return Response.json(await O.listInstances({page:at(y,"page"),perPage:at(y,"perPage"),status:m,workflowName:D}))},s=async(c,l,y)=>{if(c.method!=="GET")throw new a("Workflows instance endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});t(c);const O=r(l);return O?Response.json(await O.getInstance({instanceId:Be(y,"id"),workflowName:Be(y,"name")})):st()},i=async(c,l)=>{if(c.method!=="POST")throw new a("Workflows status endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});t(c);const y=r(l);if(!y)return st();const O=await c.json().catch(()=>{});if(typeof O?.name!="string"||O.name===""||typeof O.id!="string"||O.id==="")throw new a("Workflows status action requires string `name` and `id`",{code:"BAD_REQUEST",status:400});const{action:D}=O;if(D!=="pause"&&D!=="resume"&&D!=="terminate")throw new a("Workflows status action must be one of: pause, resume, terminate",{code:"BAD_REQUEST",status:400});return Response.json(await y.setInstanceStatus({action:D,instanceId:O.id,workflowName:O.name}))};return{[co]:s,[uo]:n,[lo]:i}},wo=new TextEncoder,it="/_lunora/rpc",mo="/_lunora/rpc-batch",yo="/_lunora/ws",Ee=(e,t,r)=>({resourceAttributes:Gn(e,t),...r===void 0?{}:{waitUntil:r}}),dt=e=>({spanId:e.spanId,traceFlags:e.traceFlags,traceId:e.traceId,...e.parentSpanId===void 0?{}:{parentSpanId:e.parentSpanId}}),xe=e=>{const{method:t}=e,r=e.headers.get("user-agent")??void 0;let n;try{n=new URL(e.url)}catch{return{method:t,userAgent:r}}const s=n.port===""?void 0:Number(n.port);return{host:n.hostname,method:t,path:n.pathname,port:Number.isNaN(s)?void 0:s,scheme:n.protocol.replace(":",""),userAgent:r}},ut="/_lunora/voice/",go="/_lunora/scheduler/dispatch",bo="/_lunora/admin/cron-jobs/run",Oo="/_lunora/admin/ws-token",Eo="/_lunora/admin/",To="/_lunora/migrate",_o="/_lunora/status",Ro=e=>e.startsWith(Eo)||e===To,So=new Set(["1","enabled","on","true","yes"]),Ao=e=>{const t=e.headers.get("x-lunora-userid"),r=e.headers.get("x-lunora-identity");if(!(t===null&&r===null))return{...r===null?{}:{identity:r},...t===null?{}:{userId:t}}},Do="/api/auth",vo="__lunora_admin__:recordAuthEvent",ko="__lunora_admin__:listPushSubscriptions",Io=["/sign-in","/sign-up","/callback"],Po=(e,t)=>{const r=t.endsWith("/")?t.slice(0,-1):t;if(!e.startsWith(`${r}/`))return!1;const n=e.slice(r.length);return Io.some(s=>n===s||n.startsWith(`${s}/`))},Te=(e,t,r,n)=>{const s=Zt(r),i=s?r.code:"INTERNAL_SERVER_ERROR",c=s?r.status:500,l=r instanceof Error?r.message:String(r);return{durationMs:t,error:{code:i,message:l,status:c},functionPath:e,ok:!1,...n.fanOut?{fanOut:{failed:0,shards:0,table:n.fanOut.table}}:{},...n.shardKey?{shardKey:n.shardKey}:{}}},No=e=>{const{exp:t,expiresAtMs:r}=e;if(typeof r=="number"&&Number.isFinite(r))return r;if(typeof t=="number"&&Number.isFinite(t))return t*1e3},ct=e=>e.waitUntil?{waitUntil:t=>{e.waitUntil?.(t)}}:void 0,Uo=e=>{const t=e?.queue;return typeof t=="string"&&t.length>0?t:"unknown"},ue=async(e,t,r)=>{const n={"content-type":"application/json"},s=e.headers.get("authorization"),i=e.headers.get("cookie"),c=e.headers.get("x-d1-bookmark"),l=e.headers.get("x-lunora-mutation-id"),y=e.headers.get("x-lunora-client-id"),O=e.headers.get("x-lunora-client-seq");s&&(n.authorization=s),i&&(n.cookie=i),c&&(n["x-d1-bookmark"]=c),l&&(n["x-lunora-mutation-id"]=l),y&&(n["x-lunora-client-id"]=y),O&&(n["x-lunora-client-seq"]=O);const D=e.headers.get("cf-connecting-ip");if(D&&(n["x-lunora-client-ip"]=D),!r)return{claims:null,headers:n,identity:null,userId:null};const m=await r(e,t);if(!m||typeof m.userId!="string"||m.userId.length===0)return{claims:null,headers:n,identity:null,userId:null};n["x-lunora-userid"]=m.userId;const g=No(m);g!==void 0&&(n["x-lunora-identity-exp"]=String(g));const{userId:p,...w}=m,_=Object.keys(w).length>0?w:null;return _&&(n["x-lunora-identity"]=JSON.stringify(_)),{claims:_,headers:n,identity:m,userId:p}},qo=new Set(["concat","first","groupBy","max","min","rank","sum","topK"]),$o=e=>{if(e===void 0)return;if(!e||typeof e!="object")throw new a("RPC `fanOut` must be an object",{code:"BAD_REQUEST",status:400});const t=e;if(typeof t.table!="string"||t.table.length===0)throw new a("RPC `fanOut.table` must be a non-empty string",{code:"BAD_REQUEST",status:400});if(!t.merge||typeof t.merge!="object")throw new a("RPC `fanOut.merge` must be an object",{code:"BAD_REQUEST",status:400});const r=t.merge;if(typeof r.kind!="string"||!qo.has(r.kind))throw new a("RPC `fanOut.merge.kind` is not a recognized merge strategy",{code:"BAD_REQUEST",status:400});if(r.kind==="topK"){if(typeof r.k!="number"||!Number.isInteger(r.k)||r.k<0)throw new a("RPC `fanOut.merge.k` must be a non-negative integer",{code:"BAD_REQUEST",status:400});if(typeof r.by!="string"||r.by.length===0)throw new a("RPC `fanOut.merge.by` must be a non-empty string",{code:"BAD_REQUEST",status:400})}return t},Lo=(e,t)=>{e?.LUNORA_DEBUG_RPC&&console.warn(`[lunora:rpc] ${t.fanOut?"fan-out":`shard=${t.shardKey??"(root)"}`} ${t.functionPath}`)},lt=(e,t)=>{const r=t.functions?.[e.functionPath]?.x402;if(r){if(e.fanOut)throw new a("a paid (`.x402`) function cannot be fanned out",{code:"BAD_REQUEST",status:400});if(!t.x402Charge)throw new a(`function "${e.functionPath}" is marked paid (.x402) but no x402Charge gate is configured on the worker`,{code:"MISCONFIGURED",status:500});return r}},Bo=async e=>{const t=await ae(e);let r;try{r=JSON.parse(t)}catch{throw new a("RPC body must be valid JSON",{code:"BAD_REQUEST",status:400})}if(!r||typeof r!="object"||typeof r.functionPath!="string")throw new a("RPC envelope is missing `functionPath`",{code:"BAD_REQUEST",status:400});const n=r;if(n.args!==void 0&&(typeof n.args!="object"||n.args===null||Array.isArray(n.args)))throw new a("RPC `args` must be an object",{code:"BAD_REQUEST",status:400});if(n.shardKey!==void 0&&typeof n.shardKey!="string")throw new a("RPC `shardKey` must be a string",{code:"BAD_REQUEST",status:400});const s=r,i=$o(s.fanOut),c=s.args??{};if(i&&s.functionPath.startsWith("__lunora_relation__:")){const l=c.table;if(typeof l=="string"&&l!==i.table)throw new a("RPC `args.table` must match the authorized `fanOut.table` for a relation fan-out",{code:"BAD_REQUEST",status:400});c.table=i.table}return{args:c,fanOut:i,functionPath:s.functionPath,shardKey:s.shardKey}},oe=async(e,t,r)=>Se(e,t).fetch(r),_e=new Map,xo=5e3,Co=4096,jo=async(e,t)=>{const r=Date.now(),n=_e.get(t);if(n!==void 0&&n.expiresMs>r)return n.relayCount;n!==void 0&&_e.delete(t);let s=0;try{const i=await Se(e,t).fetch(new Request("https://shard.internal/_lunora/route"));if(i.ok){const c=(await i.json()).relayCount;typeof c=="number"&&c>0&&(s=Math.floor(c))}}catch{s=0}return pt(_e,Co),_e.set(t,{expiresMs:r+xo,relayCount:s}),s},Go=(e,t)=>{if(!(e===null||typeof e!="object")){for(const[r,n]of Object.entries(e))if(n===t)return r}},je=(e,t)=>{const r=Math.max(e.length,t.length);let n=e.length^t.length;for(let s=0;s<r;s+=1){const i=s<e.length?e.codePointAt(s)??0:0,c=s<t.length?t.codePointAt(s)??0:0;n|=i^c}return n===0},Ko=async(e,t,r)=>{if(e.length===0||r.length===0)return!1;const n=new TextEncoder,s=await crypto.subtle.importKey("raw",n.encode(e),{hash:"SHA-256",name:"HMAC"},!1,["sign"]),i=await crypto.subtle.sign("HMAC",s,n.encode(t)),c=new Uint8Array(i);let l="";for(const O of c)l+=String.fromCodePoint(O);const y=btoa(l).replaceAll("+","-").replaceAll("/","_").replaceAll("=","");return je(y,r)},ht=(e,t)=>{if(!t||t.length===0)return!1;const r=e.headers.get("authorization");if(!r)return!1;const[n,...s]=r.split(" ");return n?.toLowerCase()!=="bearer"?!1:je(t,s.join(" ").trim())},Mo=async(e,t,r)=>{if(!t||t.length===0)return!1;const n=new URL(e.url).searchParams.get("token");return n===null?!1:await kr(t,n)?!0:r?!1:je(t,n)},Qo=(e,t)=>{if(t===null||typeof t!="object"&&typeof t!="function")return;const r=t;if(typeof r.prepare=="function"&&typeof r.batch=="function"&&typeof r.dump=="function")return pr(`d1:${e}`,t);if(typeof r.list=="function"&&typeof r.head=="function"&&typeof r.createMultipartUpload=="function")return Pe(`r2:${e}`,!0);if(typeof r.send=="function"&&typeof r.sendBatch=="function"&&typeof r.get!="function")return Pe(`queue:${e}`,!0);if(typeof r.connectionString=="string")return Pe(`hyperdrive:${e}`,!0)},bt=e=>{const t=no(e.trustInboundTraceContext),r=oo(e.trustInboundTraceContext),n=e.defaultShardKey??"__root__",s=fr(e.resolveIdentity,e.identity),i=He(e.shardDO,e.jurisdiction),c=e.schedulerDO===void 0?void 0:He(e.schedulerDO,e.jurisdiction);let l;const y=()=>e.adminToken??l;let O;const D=()=>e.requireEphemeralWsToken??O??!1,m=o=>{const d=o??{};if(O===void 0&&e.requireEphemeralWsToken===void 0){const u=d.LUNORA_REQUIRE_EPHEMERAL_WS_TOKEN;typeof u=="string"&&u.length>0&&(O=So.has(u.trim().toLowerCase()))}if(l!==void 0||e.adminToken!==void 0)return;const h=d.LUNORA_ADMIN_TOKEN;typeof h=="string"&&h.length>0&&(l=h)},g=new WeakSet,p=o=>ht(o,y())||g.has(o),w=async(o,d)=>{const h=await ue(o,d,e.resolveIdentity);if(g.has(o)&&h.headers.authorization===void 0){const u=y();u!==void 0&&(h.headers.authorization=`Bearer ${u}`)}return h};let _=!1;const R=o=>{if(!e.allowUnauthenticatedShardAccess){const d=o==="fan-out"?"authorizeFanOut":"authorizeShard";throw new a(`${o} access is default-denied: configure \`${d}\` on the worker, or set \`allowUnauthenticatedShardAccess: true\` to explicitly allow unauthenticated ${o} access (relying solely on per-row RLS).`,{code:o==="fan-out"?"FORBIDDEN_FANOUT":"FORBIDDEN_SHARD",status:403})}_||(_=!0,console.warn([`[lunora] SECURITY: serving ${o} access with \`allowUnauthenticatedShardAccess: true\` and no \`authorizeShard\`/\`authorizeFanOut\` — `,"any caller (including unauthenticated ones) can target any shard / fan out across the table. ","This is safe only if every table is protected by per-row RLS. Configure `authorizeShard`/`authorizeFanOut` to gate it."].join("")))},P=Pn({defaultShard:n,forwardToShard:oe,isAdmin:p,queryCoordinator:e.queryCoordinator,resolveForwardContext:w,shardDO:i}),T=async(o,d,h,u,f)=>{if(e.authorizeShard&&!await e.authorizeShard(null,h))throw new a("Forbidden shard",{code:"FORBIDDEN_SHARD",status:403});const b={"content-type":"application/json","x-lunora-system":"1"};f?.userId!==void 0&&f.userId.length>0&&(b["x-lunora-userid"]=f.userId),f?.identity!==void 0&&f.identity.length>0&&(b["x-lunora-identity"]=f.identity),u!==void 0&&u.length>0&&(b["x-lunora-mutation-id"]=u);const S=new Request("https://shard.internal/rpc",{body:JSON.stringify({args:d,functionPath:o}),headers:b,method:"POST"});return oe(i,h,S)},q=async(o,d,h,u)=>{const f=h?.[o];if(!f||typeof f.create!="function")throw new a(`${u} targets workflow binding "${o}", which is not bound on env`,{code:"CRON_JOB_FAILED",status:500});await f.create({params:d})},B=async(o,d,h)=>q(o,d.args??{},h,`cron job "${d.name}"`),K=async(o,d)=>{if(o.workflow){await B(o.workflow,o,d);return}if(o.functionPath===void 0)throw new a(`cron job "${o.name}" has neither a function target nor a workflow target`,{code:"CRON_JOB_FAILED",status:500});const h=await T(o.functionPath,o.args??{},o.shardKey??n);if(!h.ok)throw new a(`cron job "${o.name}" (${o.functionPath}) failed with shard status ${String(h.status)}`,{code:"CRON_JOB_FAILED",status:500})},N=async(o,d,h,u)=>{const f=e.cronJobs?.[o];if(f)for(const b of f)try{await K(b,d)}catch(S){h.push(u(S))}},M=async(o,d)=>{if(!p(o))throw new a("admin endpoint requires a valid admin bearer",{code:"ADMIN_FORBIDDEN",status:403});if(o.method!=="POST")throw new a("cron-jobs run endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});if(!e.cronJobs)throw new a("cron-jobs run endpoint requires a `cronJobs` map on the worker",{code:"CRON_JOBS_NOT_CONFIGURED",status:400});const h=await Z(o),u=typeof h.name=="string"?h.name:"";if(u==="")throw new a("cron-jobs run endpoint requires a job `name`",{code:"BAD_REQUEST",status:400});const f=Object.values(e.cronJobs).flat().find(b=>b.name===u);if(!f)throw new a(`no cron job named "${u}" is registered`,{code:"CRON_JOB_NOT_FOUND",status:404});return await K(f,d),Response.json({name:u,ran:!0},{status:200})},Q=async o=>{const d=typeof o.pool=="string"&&o.pool.length>0?o.pool:void 0;if(!d||!c||typeof o.id!="string")return;const h=typeof o.instanceName=="string"&&o.instanceName.length>0?o.instanceName:"default";try{await c.get(c.idFromName(h)).fetch(new Request("https://scheduler.internal/complete",{body:JSON.stringify({id:o.id,pool:d}),headers:{"content-type":"application/json"},method:"POST"}))}catch{}},Y=async(o,d)=>{if(o.method!=="POST")throw new a("Scheduler dispatch endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});const h=await ae(o),u=d??{},f=typeof u.LUNORA_SCHEDULER_SECRET=="string"?u.LUNORA_SCHEDULER_SECRET:void 0,b=e.adminToken??(typeof u.LUNORA_ADMIN_TOKEN=="string"?u.LUNORA_ADMIN_TOKEN:void 0),S=o.headers.get("x-lunora-scheduler-signature");let E=!1;if(S&&f?E=await Ko(f,h,S):b&&(E=ht(o,b)),!E)throw new a("Scheduler dispatch requires a valid signature or admin bearer",{code:"FORBIDDEN",status:403});let A;try{A=JSON.parse(h)}catch{throw new a("Scheduler dispatch body must be valid JSON",{code:"BAD_REQUEST",status:400})}const k=A??{},U=k.args??{};if(typeof k.workflow=="string"&&k.workflow.length>0)return await q(k.workflow,U,d,"scheduled workflow"),Response.json({ok:!0},{status:200});if(typeof k.functionPath!="string"||k.functionPath.length===0)throw new a("Scheduler dispatch is missing `functionPath`",{code:"BAD_REQUEST",status:400});const L=typeof k.shardKey=="string"&&k.shardKey.length>0?k.shardKey:n,$=typeof k.id=="string"&&k.id.length>0?k.id:void 0,C=Ao(o),W=await T(k.functionPath,U,L,$,C);return await Q(k),W},x=o=>{if(!p(o))throw new a("admin endpoint requires a valid admin bearer",{code:"ADMIN_FORBIDDEN",status:403})},G=(o,d,h)=>{if(x(o),d===void 0)throw new a(h.message,{code:h.code,status:400});return d},J=ur({assertAdmin:x,getReader:()=>e.authAuditReader}),re=async(o,d)=>{x(o);const h=e.notifySubscriptionStore;if(h===void 0)return Response.json({subscriptions:[]},{headers:{"content-type":"application/json"},status:200});const u=d?.kind,f=d?.userId,b=typeof u=="string"&&u!==""?u:void 0,S=typeof f=="string"&&f!==""?f:void 0,E=(await h.list()).filter(A=>(b===void 0||A.kind===b)&&(S===void 0||A.userId===S)).map(({keys:A,token:k,...U})=>U);return Response.json({subscriptions:E},{headers:{"content-type":"application/json"},status:200})},se=async(o,d)=>{if(!d.fanOut){if(d.functionPath===dr)return J(o,d.args??{});if(d.functionPath===ko)return re(o,d.args)}},ne=Hr({applyGlobals:e.applyGlobals,exportCursorStore:e.exportCursorStore,exportSinks:e.exportSinks,knownTables:()=>mt(),queryCoordinator:e.queryCoordinator,requireAdminOption:G,resolveForwardContext:w,shardDO:i,streamExportRows:(o,d,h,u)=>tt(e,o,d,h,u,i),streamingImport:(o,d)=>en(o,e,d,i),syncGlobals:e.syncGlobals}),he=(o,d)=>{const h=o.searchParams.get(d);return h===null||h===""?void 0:h},me=o=>{const d=new URL(o.url),h=d.searchParams.get("limit"),u=d.searchParams.get("offset"),f=h===null?void 0:Number.parseInt(h,10),b=u===null?void 0:Number.parseInt(u,10);return{limit:f!==void 0&&Number.isFinite(f)&&f>=0?f:void 0,offset:b!==void 0&&Number.isFinite(b)&&b>=0?b:void 0}},be=()=>{if(c===void 0)throw new a("scheduled endpoints require a `schedulerDO` namespace on the worker",{code:"SCHEDULER_NOT_CONFIGURED",status:400});return c},ee=Jn({checkWsAdmin:async o=>p(o)||Mo(o,y(),D()),requireSchedulerNamespace:be,resolveSchedulerStub:o=>(x(o),Se(be(),e.schedulerInstanceName??"default")),schedulerInstanceName:e.schedulerInstanceName??"default"}),Ot=fo({assertAdmin:x,resolveWorkflowsClient:e.workflowsClient??(()=>{})}),Et=eo({assertAdmin:x,parsePaging:me,queryParameter:he,readBodyBytes:$r,requireAdminOption:G,storage:{storageBuckets:e.storageBuckets,storageDelete:e.storageDelete,storageList:e.storageList,storageSignedUrl:e.storageSignedUrl,storageUpload:e.storageUpload}}),Tt=io({readJsonBody:Z,requireAdminOption:G,vectorIntrospector:e.vectorIntrospector}),_t=mn({kvIntrospector:e.kvIntrospector,readJsonBody:Z,requireAdminOption:G}),Rt=wr({logArchive:e.logArchive,readJsonBody:Z,requireAdminOption:G}),St=pn({assertAdmin:x,options:{cronJobs:e.cronJobs,functions:e.functions,globalIntrospector:e.globalIntrospector,openApiSpec:e.openApiSpec,openRpcSpec:e.openRpcSpec},parsePaging:me,queryParameter:he,requireAdminOption:G}),At=o=>{const d=[],h=i??o?.SHARD;if(h!==void 0&&d.push(hr("durable-object",h,n)),e.health?.disableBindingProbes!==!0)for(const[u,f]of Object.entries(o??{})){const b=Qo(u,f);b!==void 0&&d.push(b)}for(const u of e.health?.probes??[])d.push(u);return d},Dt=lr({appName:e.health?.appName,appVersion:e.health?.appVersion,auth:e.health?.auth??"public",isAdmin:p,resolveProbes:At}),vt=async(o,d,h)=>{const{claims:u,headers:f,userId:b}=await ue(o,d,s),S=async(E,A={})=>{const k=E.__lunoraRef;if(typeof k!="string")throw new a("ctx.run*: expected a function reference from the generated `api`",{code:"BAD_REQUEST",status:400});const U=new Request("https://shard.internal/rpc",{body:JSON.stringify({args:A,functionPath:k}),headers:f,method:"POST"}),L=await oe(i,n,U),$=await L.json();if($.error)throw new a($.error.message??"shard RPC failed",{code:$.error.code??"INTERNAL",status:L.status});return $.result};return{auth:{getIdentity:()=>Promise.resolve(u),userId:b},cache:h.cache,fetch:globalThis.fetch.bind(globalThis),runAction:S,runMutation:S,runQuery:S}},kt=async(o,d,h)=>{if(!e.httpRouter)return;const u=await vt(o,d,h);try{return await e.httpRouter.fetch(o,{...d,__lunoraCtx:u},h)}catch(f){return console.error("[lunora] httpRouter (SSR) handler threw:",f),new Response("Internal Server Error",{status:500})}},It=async(o,d,h)=>{if(o.headers.get("Upgrade")!=="websocket")throw new a("WebSocket upgrade header missing",{code:"BAD_REQUEST",status:426});const u=Ve(o,ie);if(u)return u;const f=h.searchParams.get("shard")??n,{headers:b,identity:S}=await ue(o,d,s);if(e.authorizeShard){if(!await e.authorizeShard(S,f))throw new a("Forbidden shard",{code:"FORBIDDEN_SHARD",status:403})}else f!==n&&R("shard");const E=new Headers(o.headers),A=[...E.keys()];for(const C of A)C.startsWith("x-lunora-")&&E.delete(C);const k=b["x-lunora-userid"],U=b["x-lunora-identity"],L=b["x-lunora-identity-exp"];k!==void 0&&E.set("x-lunora-userid",k),U!==void 0&&E.set("x-lunora-identity",U),L!==void 0&&E.set("x-lunora-identity-exp",L);const $=Go(d,e.shardDO);if($!==void 0){E.set("x-lunora-shard-binding",$);const C=await jo(i,f);if(C>0){const W=Er(f,Math.floor(Math.random()*C));return oe(i,W,new Request(o,{headers:E}))}}return oe(i,f,new Request(o,{headers:E}))},Pt=async(o,d,h)=>{const{voiceAgents:u}=e;if(u===void 0)return new Response("Not found",{status:404});if(o.headers.get("Upgrade")!=="websocket")return new Response("Expected a WebSocket upgrade",{headers:{allow:"GET"},status:426});const f=Ve(o,ie);if(f)return f;let b;try{b=decodeURIComponent(h.pathname.slice(ut.length))}catch{return new Response("Unknown voice agent",{status:404})}const S=Object.hasOwn(u,b)?u[b]:void 0;if(S===void 0)return new Response("Unknown voice agent",{status:404});const E=h.searchParams.get("threadKey");if(E===null||E.length===0)return new Response("Missing threadKey",{status:400});const{headers:A,identity:k}=await ue(o,d,s);if(e.authorizeShard){if(!await e.authorizeShard(k,E))return new Response("Forbidden",{status:403})}else R("shard");const U=new Headers(o.headers);U.delete("x-lunora-userid"),U.delete("x-lunora-identity"),U.delete("x-lunora-identity-exp");const L=A["x-lunora-userid"],$=A["x-lunora-identity"],C=A["x-lunora-identity-exp"];return L!==void 0&&U.set("x-lunora-userid",L),$!==void 0&&U.set("x-lunora-identity",$),C!==void 0&&U.set("x-lunora-identity-exp",C),oe(S,E,new Request(o,{headers:U}))},Nt=async(o,d,h)=>{if(e.authorizeFanOut){if(!await e.authorizeFanOut(h,o.table,d))throw new a("Forbidden fan-out",{code:"FORBIDDEN_FANOUT",status:403});return}if(d.startsWith("__lunora_relation__:"))throw new a("reverse cross-backend relation reads (`__lunora_relation__:*`) require `authorizeFanOut` to be configured on the worker",{code:"FORBIDDEN_FANOUT",status:403});if(e.authorizeShard)throw new a("Fan-out requires `authorizeFanOut` to be configured on the worker when `authorizeShard` is set",{code:"FORBIDDEN_FANOUT",status:403});R("fan-out")},Oe=async(o,d)=>{if(!(!o.fanOut&&o.functionPath.startsWith("__lunora_admin__:"))){if(o.fanOut){await Nt(o.fanOut,o.functionPath,d);return}if(e.authorizeShard){const h=o.shardKey??n;if(!await e.authorizeShard(d,h))throw new a("Forbidden shard",{code:"FORBIDDEN_SHARD",status:403})}else o.shardKey!==void 0&&o.shardKey!==n&&R("shard")}},Ae=async(o,d,h,u,f,b)=>{const S=Date.now(),{observability:E,sampling:A}=e,k=xe(o),{decision:U,ignoredUpstream:L,trace:$}=Cn(o,{...A===void 0?{}:{sampling:A},trustInbound:t(o)});L&&r();const C={...f,"x-lunora-sample-errors":U.keepErrors?"1":"0"};jn($,C);const W=new Request("https://shard.internal/rpc",{body:JSON.stringify({args:h,functionPath:d}),headers:C,method:"POST"});try{const j=await oe(i,u,W);return de(E,{...k,...dt($),durationMs:Date.now()-S,functionPath:d,ok:j.ok,shardKey:u,...j.ok?{}:{error:{code:"SHARD_ERROR",message:`shard returned ${String(j.status)}`,status:j.status}}},b,A),j}catch(j){throw de(E,{...k,...dt($),...Te(d,Date.now()-S,j,{shardKey:u})},b,A),j}},Ut=o=>{if(o.fanOut&&o.shardKey)throw new a("RPC envelope cannot set both `shardKey` and `fanOut`",{code:"BAD_REQUEST",status:400});if(!o.fanOut&&o.functionPath.startsWith("__lunora_relation__:"))throw new a("`__lunora_relation__:*` is a fan-out-only reserved RPC and cannot be dispatched to a single shard",{code:"FORBIDDEN",status:403});if(o.fanOut&&!e.queryCoordinator)throw new a("RPC envelope set `fanOut` but no `queryCoordinator` is configured on the worker",{code:"BAD_REQUEST",status:400})},qt=async(o,d,h)=>{if(o.method!=="POST")throw new a("RPC endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});const u=await Bo(o);Lo(d,u),Ut(u);const f=await se(o,u);if(f!==void 0)return f;const{headers:b,identity:S}=await ue(o,d,s);await Oe(u,S);const E=lt(u,e);{const A=Date.now(),{observability:k}=e,U=xe(o),L=Ee(d,o,h&&(W=>h.waitUntil?.(W)));if(u.fanOut){const W=e.queryCoordinator;if(!W)throw new a("RPC envelope set `fanOut` but no `queryCoordinator` is configured on the worker",{code:"BAD_REQUEST",status:400});try{const j=await W.fanOut(i,{args:u.args??{},fanOut:u.fanOut,functionPath:u.functionPath,headers:b});return de(k,{durationMs:Date.now()-A,fanOut:{failed:j.failed,shards:j.ok+j.failed,table:u.fanOut.table},functionPath:u.functionPath,...U,ok:!0},L),Response.json(j,{headers:{"content-type":"application/json"},status:200})}catch(j){throw de(k,{...Te(u.functionPath,Date.now()-A,j,{fanOut:{table:u.fanOut.table}}),...U},L),j}}const $=u.shardKey??n,C=()=>Ae(o,u.functionPath,u.args??{},$,b,L);return E&&e.x402Charge?e.x402Charge(o,{functionPath:u.functionPath,price:E.price},C):C()}},$t=async(o,d,h)=>{if(o.method!=="POST")throw new a("RPC batch endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});const u=await ae(o);let f;try{f=JSON.parse(u)}catch{throw new a("RPC batch body must be valid JSON",{code:"BAD_REQUEST",status:400})}if(typeof f!="object"||f===null||Array.isArray(f))throw new a("RPC batch body must be an object",{code:"BAD_REQUEST",status:400});const{calls:b}=f;if(!Array.isArray(b))throw new a("RPC batch `calls` must be an array",{code:"BAD_REQUEST",status:400});const{headers:S,identity:E}=await ue(o,d,s),A=qr(b,n);for(const F of A.values())for(const z of F)if(e.functions?.[z.functionPath]?.x402)throw new a(`paid (\`.x402\`) function "${z.functionPath}" cannot be called in a batch; dispatch it individually over ${it}`,{code:"BAD_REQUEST",status:400});await Promise.all([...A.entries()].flatMap(([F,z])=>z.map(te=>Oe({functionPath:te.functionPath,shardKey:F},E))));const{observability:k}=e,U=Ee(d,o,h&&(F=>h.waitUntil?.(F))),L=xe(o),$=[],C=[],W=(F,z,te,ce)=>({body:{error:{code:te,message:ce}},id:F.id,status:z}),j=(F,z,te,ce,pe)=>{for(const H of F)de(k,pe(H),U),$.push(W(H,z,te,ce))},Jt=(F,z,te,ce,pe)=>{for(const H of F){const fe=ce.get(H.id)??pe,ye=fe<400;de(k,{durationMs:te,functionPath:H.functionPath,...L,ok:ye,shardKey:z,...ye?{}:{error:{code:"SHARD_ERROR",message:`batched call returned ${String(fe)}`,status:fe}}},U)}};await Promise.all([...A.entries()].map(async([F,z])=>{const te=new Headers(S);te.set("content-type","application/json");const ce=new Request("https://shard.internal/rpc-batch",{body:JSON.stringify({calls:z}),headers:te,method:"POST"}),pe=Date.now();let H;try{H=await oe(i,F,ce)}catch(V){const Ie=Date.now()-pe,{body:Fe}=er(V,{fallbackCode:"SHARD_UNAVAILABLE",redactedMessage:"shard unavailable"});j(z,502,Fe.code,Fe.message,Xt=>({...Te(Xt.functionPath,Ie,V,{shardKey:F}),...L}));return}const fe=Date.now()-pe,ye=H.headers.get("x-d1-bookmark");ye&&C.push(ye);let ve;try{ve=await H.json()}catch{const V=`shard batch returned a non-JSON response (${String(H.status)})`;j(z,H.status,"SHARD_ERROR",V,Ie=>({durationMs:fe,error:{code:"SHARD_ERROR",message:V,status:H.status},functionPath:Ie.functionPath,...L,ok:!1,shardKey:F}));return}const ke=Array.isArray(ve.results)?ve.results:[],Vt=new Map(ke.map(V=>[V.id,V.status??H.status])),Yt=new Set(ke.map(V=>V.id));Jt(z,F,fe,Vt,H.status),$.push(...ke);for(const V of z)Yt.has(V.id)||$.push(W(V,H.status,"SHARD_ERROR",`shard batch omitted result for call ${String(V.id)}`))}));const Me={"content-type":"application/json"},[Qe]=C;return C.length===1&&Qe!==void 0&&(Me["x-d1-bookmark"]=Qe),Response.json({results:$},{headers:Me,status:200})},Lt=async(o,d,h,u={},f={})=>{try{const b=h.__lunoraRef;if(typeof b!="string")throw new a("serverQuery: expected a function reference from the generated `api`",{code:"BAD_REQUEST",status:400});const{headers:S,identity:E}=await ue(o,d,s);await Oe({functionPath:b,shardKey:f.shardKey},E);const A=f.shardKey??n,k=Ee(d,o,f.waitUntil);return await Ae(o,b,u,A,S,k)}catch(b){return ze(b)}},Bt=1e3,xt=async(o,d)=>{const h=e.backupRetain;if(h===void 0||h<=0)return;const u=[];let f;for(let S=0;S<Bt;S+=1){const E=await o.list({cursor:f,prefix:d});for(const A of E.objects)A.key.endsWith(".manifest.json")&&u.push(A.key);if(!E.truncated||E.cursor===void 0)break;f=E.cursor}const b=u.toSorted((S,E)=>E.localeCompare(S)).slice(h);await Promise.all(b.flatMap(S=>{const E=S.slice(0,-14);return[o.delete(S),o.delete(E)]}))},Ct=async o=>{const d=e.backupStore,h=e.queryCoordinator;if(!d)throw new a("scheduled backup requires a `backupStore` on the worker",{code:"BACKUP_NOT_CONFIGURED",status:500});if(!h)throw new a("scheduled backup requires a `queryCoordinator` on the worker",{code:"BACKUP_NOT_CONFIGURED",status:500});const u=y();if(!u||u.length===0)throw new a("scheduled backup requires an `adminToken` (or `env.LUNORA_ADMIN_TOKEN`) to authenticate the per-shard export gate",{code:"BACKUP_NOT_CONFIGURED",status:500});const f={authorization:`Bearer ${u}`,"content-type":"application/json"},b=e.backupTables;let S=0,E=0;const A=[];await tt(e,h,f,b,W=>{const j=`${JSON.stringify(W)}
5
+ `;S+=1,E+=wo.encode(j).byteLength,A.push(j)},i);const k=e.backupPrefix??"backups/",U=new Date(o.scheduledTime).toISOString(),L=`${k}lunora-backup-${U.replaceAll(/[.:]/gu,"-")}.ndjson`,$=`${L}.manifest.json`;await d.put(L,new Blob(A,{type:"application/x-ndjson"}),{httpMetadata:{contentType:"application/x-ndjson"}});const C={bytes:E,createdAt:U,cron:o.cron,file:L,id:U,rows:S,scheduledTime:o.scheduledTime,...b?{tables:b.join(",")}:{}};await d.put($,`${JSON.stringify(C,void 0,2)}
6
+ `,{httpMetadata:{contentType:"application/json"}}),await xt(d,k)},Ge=async(o,d,h)=>{const{observability:u}=e,f=Date.now(),b=Re(16),S=Re(8),E=ct(d);try{const A=await h();return de(u,{durationMs:Date.now()-f,functionPath:o,ok:!0,spanId:S,traceId:b},E),A}catch(A){throw de(u,{...Te(o,Date.now()-f,A,{}),spanId:S,traceId:b},E),A}finally{We(u,E)}},jt=async(o,d,h)=>{m(d);const u=[],f=E=>E instanceof Error?E:new Error(String(E)),b=e.crons?.[o.cron];if(b)try{await b(o,d,h)}catch(E){u.push(f(E))}if(await N(o.cron,d,u,f),e.backupStore&&e.backupCron!==void 0&&e.backupCron===o.cron)try{await Ct(o)}catch(E){u.push(f(E))}const[S]=u;if(u.length===1&&S)throw S;if(u.length>1)throw new AggregateError(u,`scheduled("${o.cron}") had ${String(u.length)} failure(s)`)},Gt=async(o,d)=>{try{const h=o??{},u=e.adminToken??(typeof h.LUNORA_ADMIN_TOKEN=="string"?h.LUNORA_ADMIN_TOKEN:void 0);if(!u||u.length===0)return;const f=new Request("https://shard.internal/rpc",{body:JSON.stringify({args:{outcome:d},functionPath:vo}),headers:{authorization:`Bearer ${u}`,"content-type":"application/json"},method:"POST"});await oe(i,n,f)}catch{}},Kt=async(o,d,h,u)=>{if(!e.authHandler)return;const f=await e.authHandler(o);if(!f)return;const b=e.authBasePath??Do;return Po(h.pathname,b)&&u.waitUntil?.(Gt(d,f.status>=400?"fail":"ok")),f},Mt=async({args:o,env:d,functionPath:h,request:u,shardKey:f,waitUntil:b})=>{const S={functionPath:h,...f===void 0?{}:{shardKey:f}},{headers:E,identity:A}=await ue(u,d,s);await Oe(S,A);const k=f??n,U=Ee(d,u,b),L=()=>Ae(u,h,o,k,E,U),$=lt(S,e);return $&&e.x402Charge?e.x402Charge(u,{functionPath:h,price:$.price},L):L()},Qt=yr({functions:e.functions??{},invoke:Mt,readJsonBody:Z,...e.restRateLimit?{rateLimit:e.restRateLimit}:{}}),De=e.routes!==void 0&&Object.keys(e.routes).length>0?e.routes:void 0,Ft={[_o]:o=>o.method!=="GET"&&o.method!=="HEAD"?new Response(void 0,{headers:{allow:"GET, HEAD"},status:405}):Response.json({ok:!0},{headers:{"cache-control":"no-store"}}),[yo]:(o,d,h)=>It(o,d,h),[it]:(o,d,h,u)=>qt(o,d,u),[mo]:(o,d,h,u)=>$t(o,d,u),[go]:(o,d)=>Y(o,d),[bo]:(o,d)=>M(o,d),[Oo]:async o=>{if(o.method!=="POST")throw new a("ws-token endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});x(o);const d=y();if(d===void 0)throw new a("ws-token minting requires a configured admin token",{code:"ADMIN_TOKEN_NOT_CONFIGURED",status:400});const h=await vr(d);return Response.json(h,{headers:{"cache-control":"no-store"}})},...P,...ne,...ee,...Ot,...Et,...Tt,..._t,...Rt,...St,...Dt,...Qt,...Nr({assertAdmin:x,getAuthAdmin:()=>e.authAdmin,parsePaging:me,queryParameter:he,readJsonBody:Z})};let ie=Je(e.security),Ke=!1;const zt=o=>{Ke||(Ke=!0,ie=Je(e.security,o??{}))},Wt=async(o,d)=>{if(!(e.adminGate===void 0||!Ro(d)))try{await e.adminGate(o)&&g.add(o)}catch{}},Ht=async(o,d,h)=>{const u=new URL(o.url);if(o.method==="POST"||o.method==="PUT"){const E=Number(o.headers.get("content-length")??""),A=u.pathname===yt?gt:ge;if(Number.isFinite(E)&&E>A)throw new a("Body too large",{code:"PAYLOAD_TOO_LARGE",status:413})}const f=await Kt(o,d,u,h);if(f)return f;if(De){const E=`${o.method} ${u.pathname}`,A=De[E]??De[u.pathname];if(A)return A(o,d,h)}const b=Ft[u.pathname];return b?(await Wt(o,u.pathname),b(o,d,u,h)):e.voiceAgents!==void 0&&u.pathname.startsWith(ut)?Pt(o,d,u):await kt(o,d,h)||new Response("Not found",{status:404})};return{async fetch(o,d,h){e.passThroughOnException&&h.passThroughOnException?.(),zt(d),m(d);const u=gr(o,ie);if(u)return u;const f=br(o,ie);if(f)return Ne(f,o,ie);try{const b=await Ht(o,d,h);return Ne(b,o,ie)}catch(b){return Ne(ze(b),o,ie)}finally{We(e.observability,ct(h))}},async queue(o,d,h){await Ge(`queue:${Uo(o)}`,h,async()=>{await e.queue?.(o,d,h)})},async scheduled(o,d,h){await Ge(`cron:${o.cron}`,h,async()=>{await jt(o,d,h)})},serverQuery:Lt}},Fo=e=>bt(e),zo=e=>typeof e=="function"?{fetch:e}:e,Wo=e=>!!(e.crons??e.cronJobs??e.backupCron),ua=(e,t)=>{const r=zo(e),n=typeof e=="object"&&typeof e.scheduled=="function"?e.scheduled:void 0,s=c=>{const l=Fo({...c,httpRouter:r});return n!==void 0&&!Wo(c)?{...l,scheduled:async(y,O,D)=>{await n(y,O,D)}}:l};if(typeof t!="function")return s(t);const i=t;return{fetch:(c,l,y)=>s(i(l)).fetch(c,l,y),queue:(c,l,y)=>s(i(l)).queue?.(c,l,y)??Promise.resolve(),scheduled:(c,l,y)=>s(i(l)).scheduled(c,l,y),serverQuery:(c,l,y,O,D)=>s(i(l)).serverQuery(c,l,y,O,D)}},Ho=(e,t)=>{if(typeof e=="function")return e(t);const r=e.shardDO??t?.SHARD;if(!r)throw new a("@lunora/runtime: no shard Durable Object namespace found. Bind `SHARD` in wrangler.jsonc, or pass `createLunoraHandler({ shardDO: env.MY_SHARD })`.");return{...e,shardDO:r}},ca=(e={})=>(t,r,n)=>bt(Ho(e,r)).fetch(t,r,n??tr),la=e=>e;export{dr as GET_AUTH_AUDIT_LOG_OP,tr as NOOP_EXECUTION_CONTEXT,fa as composeIdentityResolvers,Fo as composeWorker,ca as createLunoraHandler,bt as createWorker,la as defineRpcEnvelope,jo as probeRelayCount,Ho as resolveLunoraOptions,wa as routeIdentityResolvers,ua as withFrameworkWorker};
@@ -0,0 +1 @@
1
+ import{e as a,a as s,f}from"./observability-B0MYwNDB.mjs";export{a as emitLogEvent,s as emitRpcEvent,f as flushSink};
@@ -0,0 +1 @@
1
+ const t=r=>{const e=Number.parseInt(r.slice(0,8),16);return Number.isFinite(e)?e/4294967296:0},o=(r,e=1)=>e>=1?!0:e<=0?!1:t(r)<e,c=(r,e)=>({isTraced:o(e,r?.headRate??1),keepErrors:r?.alwaysSampleErrors??!0}),i=(r,e)=>r.isTraced||r.keepErrors&&e,n=(r,e,s,a)=>{if(r?.onRpc&&!(a!==void 0&&e.traceId!==void 0&&!i(c(a,e.traceId),!e.ok)))try{r.onRpc(e,s)}catch{}},f=(r,e,s)=>{if(r?.onLog)try{r.onLog(e,s)}catch{}},p=(r,e)=>{if(r?.flush)try{r.flush(e)}catch{}};export{n as a,f as e,p as f,c as o};
@@ -0,0 +1 @@
1
+ const v={debug:5,error:17,fatal:21,info:9,log:9,trace:1,warn:13},O=e=>`${String(Math.round(e))}000000`,b=e=>{const t=new Uint8Array(e);crypto.getRandomValues(t);let r="";for(const o of t)r+=o.toString(16).padStart(2,"0");return r},a=/^[0-9a-f]+$/,m=(e,t,r=!0)=>`00-${e}-${t}-${r?"01":"00"}`,E=e=>{if(e==null)return;const t=e.trim().toLowerCase().split("-"),[r,o,n,s]=t;if(!(t.length<4||r===void 0||r.length!==2||!a.test(r)||r==="ff"||r==="00"&&t.length!==4||o===void 0||n===void 0||s===void 0||s.length!==2||!a.test(s)||o.length!==32||n.length!==16||!a.test(o)||!a.test(n)||o==="00000000000000000000000000000000"||n==="0000000000000000"))return{parentSpanId:n,sampled:(Number.parseInt(s,16)&1)===1,traceId:o}},p=(e,t)=>typeof t=="boolean"?{key:e,value:{boolValue:t}}:typeof t=="number"?Number.isFinite(t)?Number.isSafeInteger(t)?{key:e,value:{intValue:String(t)}}:{key:e,value:{doubleValue:t}}:{key:e,value:{stringValue:String(t)}}:{key:e,value:{stringValue:t}},y=e=>e===void 0?[]:Object.entries(e).map(([t,r])=>p(t,r)),S=(e,t,r)=>{const o={},n=new Map,s=(i,c)=>{const d=i.toLowerCase(),f=n.get(d);f===void 0?(n.set(d,i),o[i]=c):o[f]=c};for(const[i,c]of Object.entries(e))s(i,c);for(const[i,c]of Object.entries(t??{}))s(i,c);return r!==void 0&&r.length>0&&s("authorization",`Bearer ${r}`),o},u=e=>Array.isArray(e)?e:[e],C={client:3,consumer:5,internal:1,producer:4,server:2},l=(e,t)=>{const r={"service.name":e};for(const[o,n]of Object.entries(t??{}))r[o]=n;return Object.entries(r).map(([o,n])=>p(o,n))},N=(e,t,r,o)=>({resourceSpans:[{resource:{attributes:l(r,o)},scopeSpans:[{scope:{name:t},spans:u(e)}]}]}),I=(e,t,r,o)=>({resourceLogs:[{resource:{attributes:l(r,o)},scopeLogs:[{logRecords:u(e),scope:{name:t}}]}]}),V=(e,t,r,o)=>({resourceMetrics:[{resource:{attributes:l(r,o)},scopeMetrics:[{metrics:u(e),scope:{name:t}}]}]}),_=e=>t=>{const r=e?.[t];return typeof r=="string"&&r.length>0?r:void 0},g=(e,t)=>{if(typeof e!="object"||e===null)return;const r=e[t];return typeof r=="string"&&r.length>0?r:void 0},A=e=>{const t={},r=e("SERVICE_VERSION")??e("CF_VERSION_METADATA")??e("VERCEL_GIT_COMMIT_SHA")??e("GITHUB_SHA")??e("COMMIT_SHA");r!==void 0&&(t["service.version"]=r);const o=e("DEPLOYMENT_ENVIRONMENT")??e("ENVIRONMENT")??e("NODE_ENV");return o!==void 0&&(t["deployment.environment"]=o),t},L=(e,t)=>{if(!(t!==void 0||e("CLOUDFLARE")!==void 0||e("CF_ACCOUNT_ID")!==void 0))return{};const r={"cloud.provider":"cloudflare"},o=g(t,"colo")??e("CF_COLO")??e("CLOUDFLARE_COLO");return o!==void 0&&(r["cloud.region"]=o),r},M=(...e)=>{const t={};for(const r of e)if(r!==void 0)for(const[o,n]of Object.entries(r))t[o]=n;return t};export{E as A,V as L,b as O,M as R,I as S,y as V,S as a,v as b,p as c,L as d,O as f,A as i,m,_ as s,C as w,N as y};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/runtime",
3
- "version": "1.0.0-alpha.38",
3
+ "version": "1.0.0-alpha.39",
4
4
  "description": "Lunora Worker runtime: the RPC router, shard resolver, and query coordinator",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -1 +0,0 @@
1
- import{a as w,f as T,b as h,c as s,L as I,w as $,e as L,V as N,R}from"./otlp-resource-Ck1njnSc.mjs";const M=e=>{if(typeof e=="string")return e;try{return JSON.stringify(e)??String(e)}catch{return String(e)}},_=e=>typeof e=="boolean"||typeof e=="number"||typeof e=="string"?e:M(e),E=(e,a,t,n)=>{const o=[s("lunora.function_path",e.functionPath),s("lunora.ok",e.ok)];e.method!==void 0&&o.push(s("http.request.method",e.method)),e.path!==void 0&&o.push(s("url.path",e.path)),o.push(s("http.route",e.functionPath)),e.scheme!==void 0&&o.push(s("url.scheme",e.scheme)),e.host!==void 0&&o.push(s("server.address",e.host)),e.port!==void 0&&o.push(s("server.port",e.port)),e.userAgent!==void 0&&o.push(s("user_agent.original",e.userAgent)),e.shardKey!==void 0&&o.push(s("lunora.shard_key",e.shardKey)),o.push(s("http.response.status_code",e.error?.status??200)),e.error&&o.push(s("error.type",e.error.code),s("lunora.error_status",e.error.status)),e.fanOut&&o.push(s("lunora.fanout.table",e.fanOut.table),s("lunora.fanout.shards",e.fanOut.shards),s("lunora.fanout.failed",e.fanOut.failed));const r={attributes:o,endTimeUnixNano:h(t),kind:2,name:e.functionPath,spanId:e.spanId??T(8),startTimeUnixNano:h(t-e.durationMs),status:e.ok?{code:1}:{code:2,message:e.error?.message??""},traceId:e.traceId??T(16)};return e.parentSpanId!==void 0&&(r.parentSpanId=e.parentSpanId),e.traceFlags!==void 0&&(r.flags=e.traceFlags),e.error&&(r.events=[{attributes:[s("exception.type",e.error.code),s("exception.message",e.error.message)],name:"exception",timeUnixNano:h(t)}]),w(r,"@lunora/runtime",a,n)},k=(e,a)=>{const t=new Map([["lunora.function_path",s("lunora.function_path",e.functionPath)]]);e.shardKey!==void 0&&t.set("lunora.shard_key",s("lunora.shard_key",e.shardKey)),e.userId!==void 0&&t.set("lunora.user_id",s("lunora.user_id",e.userId)),e.errorType!==void 0&&t.set("error.type",s("error.type",e.errorType));for(const[n,o]of Object.entries(a??{}))t.set(n,s(n,_(o)));return[...t.values()]},A=(e,a,t)=>{const n={attributes:k({errorType:e.error?.type,functionPath:e.functionPath,shardKey:e.shardKey,userId:e.userId},e.attributes),endTimeUnixNano:h(e.startTs+e.durationMs),kind:1,name:e.name,parentSpanId:e.parentSpanId,spanId:e.spanId,startTimeUnixNano:h(e.startTs),status:e.ok?{code:1}:{code:2,message:e.error?.message??""},traceId:e.traceId};return w(n,"@lunora/runtime",a,t)},F=(e,a,t)=>{const n=h(e.ts),o=k({functionPath:e.functionPath,shardKey:e.shardKey},e.attributes),r={asDouble:e.value,attributes:o,timeUnixNano:n};return e.kind==="gauge"?I({gauge:{dataPoints:[r]},name:e.name},"@lunora/runtime",a,t):e.kind==="histogram"?I({histogram:{aggregationTemporality:1,dataPoints:[{attributes:o,bucketCounts:["1"],count:"1",explicitBounds:[],max:e.value,min:e.value,sum:e.value,timeUnixNano:n}]},name:e.name},"@lunora/runtime",a,t):I({name:e.name,sum:{aggregationTemporality:1,dataPoints:[r],isMonotonic:!0}},"@lunora/runtime",a,t)},V=(e,a,t)=>{const n={attributes:k({functionPath:e.functionPath,shardKey:e.shardKey,userId:e.userId},e.fields),body:{stringValue:e.message},severityNumber:L[e.level],severityText:e.level.toUpperCase(),timeUnixNano:h(e.ts)};return e.traceId!==void 0&&(n.traceId=e.traceId),e.spanId!==void 0&&(n.spanId=e.spanId),$(n,"@lunora/runtime",a,t)},J=1024,j=async e=>{const a=new Blob([e]).stream().pipeThrough(new CompressionStream("gzip"));return new Response(a).arrayBuffer()},b=(e,a,t,n)=>{try{const o=JSON.stringify(a),r=(o.length<J?fetch(e,{body:o,headers:t,method:"POST"}):j(o).then(l=>fetch(e,{body:l,headers:{...t,"content-encoding":"gzip"},method:"POST"}))).catch(()=>{});n?.waitUntil&&n.waitUntil(r)}catch{}},y=(e,a)=>a===!0&&e.ok,B=(e={})=>{const{onlyErrors:a}=e;return{onLog:t=>{t.level==="error"||t.level==="fatal"?console.error("[lunora:log]",t.functionPath,t.message):console.log("[lunora:log]",t.functionPath,t.message)},onMetric:t=>{console.log("[lunora:metric]",`${t.name}=${String(t.value)}`,t.kind,t.functionPath)},onRpc:t=>{y(t,a)||(t.ok?console.log("[lunora:rpc]",t):console.error("[lunora:rpc]",t))},onSpan:t=>{const n=t.ok?"ok":`error ${t.error?.type??""}`.trim();console.log("[lunora:span]",t.name,`${String(t.durationMs)}ms`,n,t.functionPath)}}},C=e=>{const{headers:a,onlyErrors:t,transform:n,transformLog:o,url:r}=e,l=N({"content-type":"application/json"},a),m=(d,p)=>{try{const i=fetch(r,{body:JSON.stringify(d),headers:l,method:"POST"}).catch(()=>{});p?.waitUntil&&p.waitUntil(i)}catch{}};return{onLog:(d,p)=>{let i=d;if(o)try{i=o(d)}catch{return}i!=null&&m(i,p)},onRpc:(d,p)=>{if(!y(d,t))try{let i=d;if(n)try{i=n(d)}catch{return}if(i==null)return;m(i,p)}catch{}}}},D=e=>{const{capture:a,captureLog:t}=e,n=e.onlyErrors??!0;return{onLog:t?o=>{try{t(o)}catch{}}:void 0,onRpc:o=>{if(!y(o,n))try{a(o)}catch{}}}},W=e=>{const{dataset:a,onlyErrors:t}=e;return{onRpc:n=>{if(!y(n,t))try{a.writeDataPoint({blobs:[n.functionPath,n.ok?"ok":"error",n.shardKey??"",n.error?.code??"",n.fanOut?.table??""],doubles:[n.durationMs,n.ok?0:1,n.fanOut?.shards??0,n.fanOut?.failed??0],indexes:[n.functionPath]})}catch{}}}},q=e=>{const{pipeline:a,serializeFields:t}=e;return{onLog:(n,o)=>{try{const r={functionPath:n.functionPath,level:n.level,message:n.message,ts:n.ts};n.fields&&(r.fields=t===!0?JSON.stringify(n.fields):n.fields),n.shardKey!==void 0&&(r.shardKey=n.shardKey),n.userId!==void 0&&(r.userId=n.userId),n.traceId!==void 0&&(r.traceId=n.traceId),n.spanId!==void 0&&(r.spanId=n.spanId);const l=a.send([r]).catch(()=>{});o?.waitUntil&&o.waitUntil(l)}catch{}}}},G=e=>{const{deploymentEnvironment:a,detectResources:t,endpoint:n,headers:o,onlyErrors:r,resourceAttributes:l,serviceNamespace:m,serviceVersion:d,token:p}=e,i=e.serviceName??"lunora",S={...d===void 0?{}:{"service.version":d},...m===void 0?{}:{"service.namespace":m},...a===void 0?{}:{"deployment.environment":a},...l},P=new WeakMap,g=c=>{if(t!==!0||c?.resourceAttributes===void 0)return S;const u=P.get(c);if(u!==void 0)return u;const x=R(c.resourceAttributes(),S);return P.set(c,x),x};let f=n;for(;f.endsWith("/");)f=f.slice(0,-1);const O=`${f}/v1/traces`,U=`${f}/v1/logs`,K=`${f}/v1/metrics`,v=N({"content-type":"application/json"},o,p);return{onLog:(c,u)=>{b(U,V(c,i,g(u)),v,u)},onMetric:(c,u)=>{b(K,F(c,i,g(u)),v,u)},onRpc:(c,u)=>{y(c,r)||b(O,E(c,i,Date.now(),g(u)),v,u)},onSpan:(c,u)=>{b(O,A(c,i,g(u)),v,u)}}},H=(...e)=>{const a=(t,n,o)=>{for(const r of e){const l=r[t];if(l)try{l.call(r,n,o)}catch{}}};return{onLog:(t,n)=>{a("onLog",t,n)},onMetric:(t,n)=>{a("onMetric",t,n)},onRpc:(t,n)=>{a("onRpc",t,n)},onSpan:(t,n)=>{a("onSpan",t,n)}}};export{W as analyticsEngineSink,H as combineSinks,B as consoleSink,G as otlpSink,q as pipelineLogSink,D as sentrySink,C as webhookSink};
@@ -1,6 +0,0 @@
1
- import{isLunoraError as Vt,toErrorBody as Yt}from"@lunora/errors";import{NOOP_EXECUTION_CONTEXT as Xt}from"./NOOP_EXECUTION_CONTEXT-YmXqH-jH.mjs";import{LunoraError as a,toErrorResponse as Qe}from"./LunoraError-C08OP5Uq.mjs";import{GET_AUTH_AUDIT_LOG_OP as Zt,buildGetAuthAuditLog as er}from"./GET_AUTH_AUDIT_LOG_OP-DmxHQbZT.mjs";import{runExportTap as tr}from"./createKvCursorStore-C24tEuYk.mjs";import{d as fe}from"./method-guard-BbuR0VfS.mjs";import{buildHealthRoutes as rr,durableObjectProbe as nr,d1Probe as or,presenceProbe as ke}from"./HEALTH_PATH-DiZqjEGp.mjs";import{wrapResolverWithContract as ar}from"./composeIdentityResolvers-DlBbYmBJ.mjs";import{composeIdentityResolvers as ca,routeIdentityResolvers as la}from"./composeIdentityResolvers-DlBbYmBJ.mjs";import{buildLogArchiveAdminRoutes as sr}from"./LOG_ARCHIVE_PATH-e8U3ftfM.mjs";import{o as ir,a as me}from"./observability-D3GeW_py.mjs";import{f as Fe,O as dr,m as ur,R as cr,d as lr,i as hr,s as pr}from"./otlp-resource-Ck1njnSc.mjs";import{resolveShard as _e,applyJurisdiction as ze}from"./applyJurisdiction-uRQLx282.mjs";import{buildRestRoutes as fr}from"./argsFromQuery-0KrWTkNx.mjs";import{resolveSecurity as We,handleCorsPreflight as mr,enforceOrigin as wr,decorateResponse as Ie,enforceWebSocketOrigin as He}from"./decorateResponse-C6TZSzID.mjs";const ct=(e,r)=>{if(e.size<r)return;const t=e.keys().next().value;t!==void 0&&e.delete(t)},yr="::relay::",gr=(e,r)=>`${e}${yr}${String(r)}`,xe=new TextEncoder,br=e=>{const r=String.fromCodePoint(...e);return btoa(r).replaceAll("+","-").replaceAll("/","_").replaceAll("=","")},Or=e=>{const r=e.replaceAll("-","+").replaceAll("_","/")+"===".slice((e.length+3)%4),t=atob(r),n=new Uint8Array(t.length);for(let s=0;s<t.length;s+=1)n[s]=t.codePointAt(s)??0;return n},Er=64,Pe=new Map,lt=async e=>{const r=Pe.get(e);if(r)return r;ct(Pe,Er);const t=crypto.subtle.importKey("raw",xe.encode(e),{hash:"SHA-256",name:"HMAC"},!1,["sign","verify"]);return Pe.set(e,t),t},Tr=async(e,r)=>{const t=await lt(e),n=await crypto.subtle.sign("HMAC",t,xe.encode(r));return br(new Uint8Array(n))},_r=async(e,r,t)=>{const n=await lt(e);return crypto.subtle.verify("HMAC",n,t,xe.encode(r))},ht="v1",Rr=6e4,Sr=async(e,r={})=>{const t=(r.now??Date.now())+(r.ttlMs??Rr),n=`${ht}.${String(t)}`,s=await Tr(e,n);return{expiresAtMs:t,token:`${n}.${s}`}},Ar=async(e,r,t=Date.now())=>{if(e.length===0||r.length===0)return!1;const n=r.split(".");if(n.length!==3)return!1;const[s,i,u]=n;if(s!==ht||u.length===0)return!1;const l=Number(i);if(!Number.isFinite(l)||l<=t)return!1;let y;try{y=Or(u)}catch{return!1}return _r(e,`${s}.${i}`,y)},v="/_lunora/admin/auth",Dr={INVITER_REQUIRED:400,ORG_SLUG_INVALID:400,ORG_SLUG_TAKEN:409,PASSWORD_TOO_LONG:400,PASSWORD_TOO_SHORT:400,USER_ALREADY_EXISTS:409,USER_NOT_FOUND:404},I=(e,r)=>{const t=e[r];if(typeof t!="string"||t==="")throw new a(`\`${r}\` is required`,{code:"BAD_REQUEST",status:400});return t},ce=(e,r)=>{const t=e(r);if(t===void 0)throw new a(`\`${r}\` query parameter is required`,{code:"BAD_REQUEST",status:400});return t},Ne=e=>{if(typeof e=="string"||Array.isArray(e)&&e.every(r=>typeof r=="string"))return e},X=(e,r)=>typeof e[r]=="string"?e[r]:void 0,Je=(e,r)=>{const t=e[r];return typeof t=="object"&&t!==null&&!Array.isArray(t)?t:void 0},Ve=e=>{const r=e.permission;if(typeof r!="object"||r===null||Array.isArray(r))throw new a("`permission` object is required",{code:"BAD_REQUEST",status:400});const t={};for(const[n,s]of Object.entries(r))Array.isArray(s)&&s.every(i=>typeof i=="string")&&(t[n]=s);return t},vr={[`${v}/capabilities`]:{build:()=>({}),http:"GET",method:"capabilities"},[`${v}/users`]:{build:({paging:e,query:r})=>{const t=r("sortDirection");return{...e,filterField:r("filterField"),filterValue:r("filterValue"),search:r("search"),searchField:r("searchField"),sortBy:r("sortBy"),sortDirection:t==="asc"||t==="desc"?t:void 0}},http:"GET",method:"listUsers"},[`${v}/sessions`]:{build:({paging:e,query:r})=>({...e,userId:r("userId")}),http:"GET",method:"listSessions"},[`${v}/accounts`]:{build:({query:e})=>({userId:ce(e,"userId")}),http:"GET",method:"listAccounts"},[`${v}/passkeys`]:{build:({query:e})=>({userId:ce(e,"userId")}),http:"GET",method:"listPasskeys"},[`${v}/organizations`]:{build:({paging:e})=>({...e}),http:"GET",method:"listOrganizations"},[`${v}/organizations/members`]:{build:({paging:e,query:r})=>({...e,organizationId:ce(r,"organizationId")}),http:"GET",method:"listMembers"},[`${v}/organizations/invitations`]:{build:({paging:e,query:r})=>({...e,organizationId:ce(r,"organizationId")}),http:"GET",method:"listInvitations"},[`${v}/config`]:{build:()=>({}),http:"GET",method:"config"},[`${v}/organizations/teams`]:{build:({paging:e,query:r})=>({...e,organizationId:ce(r,"organizationId")}),http:"GET",method:"listTeams"},[`${v}/organizations/teams/members`]:{build:({paging:e,query:r})=>({...e,teamId:ce(r,"teamId")}),http:"GET",method:"listTeamMembers"},[`${v}/organizations/roles`]:{build:({paging:e,query:r})=>({...e,organizationId:ce(r,"organizationId")}),http:"GET",method:"listOrgRoles"},[`${v}/users/create`]:{build:({body:e})=>({data:typeof e.data=="object"&&e.data!==null&&!Array.isArray(e.data)?e.data:void 0,email:I(e,"email"),name:I(e,"name"),password:X(e,"password"),role:Ne(e.role)}),http:"POST",method:"createUser"},[`${v}/users/update`]:{build:({body:e})=>{const{data:r}=e;if(typeof r!="object"||r===null||Array.isArray(r))throw new a("`data` object is required",{code:"BAD_REQUEST",status:400});return{data:r,userId:I(e,"userId")}},http:"POST",method:"updateUser"},[`${v}/users/role`]:{build:({body:e})=>{const r=Ne(e.role);if(r===void 0||typeof r=="string"&&r.trim()==="")throw new a("`role` is required",{code:"BAD_REQUEST",status:400});return{role:r,userId:I(e,"userId")}},http:"POST",method:"setRole"},[`${v}/users/ban`]:{build:({body:e})=>({expiresInSeconds:typeof e.expiresInSeconds=="number"?e.expiresInSeconds:void 0,reason:X(e,"reason"),userId:I(e,"userId")}),http:"POST",method:"banUser"},[`${v}/users/unban`]:{build:({body:e})=>({userId:I(e,"userId")}),http:"POST",method:"unbanUser"},[`${v}/users/password`]:{build:({body:e})=>({newPassword:I(e,"newPassword"),userId:I(e,"userId")}),http:"POST",method:"setUserPassword",returns:"void"},[`${v}/users/remove`]:{build:({body:e})=>({userId:I(e,"userId")}),http:"POST",method:"removeUser",returns:"void"},[`${v}/users/impersonate`]:{build:({body:e})=>({userId:I(e,"userId")}),http:"POST",method:"impersonateUser"},[`${v}/sessions/revoke`]:{build:({body:e})=>({sessionId:I(e,"sessionId")}),http:"POST",method:"revokeUserSession",returns:"void"},[`${v}/sessions/revoke-all`]:{build:({body:e})=>({userId:I(e,"userId")}),http:"POST",method:"revokeUserSessions",returns:"void"},[`${v}/accounts/unlink`]:{build:({body:e})=>({accountId:I(e,"accountId"),userId:I(e,"userId")}),http:"POST",method:"unlinkAccount",returns:"void"},[`${v}/two-factor/disable`]:{build:({body:e})=>({userId:I(e,"userId")}),http:"POST",method:"disableTwoFactor",returns:"void"},[`${v}/passkeys/delete`]:{build:({body:e})=>({passkeyId:I(e,"passkeyId")}),http:"POST",method:"deletePasskey",returns:"void"},[`${v}/organizations/members/remove`]:{build:({body:e})=>({memberId:I(e,"memberId")}),http:"POST",method:"removeMember",returns:"void"},[`${v}/organizations/invitations/cancel`]:{build:({body:e})=>({invitationId:I(e,"invitationId")}),http:"POST",method:"cancelInvitation",returns:"void"},[`${v}/organizations/create`]:{build:({body:e})=>({logo:X(e,"logo"),metadata:Je(e,"metadata"),name:I(e,"name"),ownerId:X(e,"ownerId"),slug:X(e,"slug")}),http:"POST",method:"createOrganization"},[`${v}/organizations/update`]:{build:({body:e})=>({logo:X(e,"logo"),metadata:Je(e,"metadata"),name:X(e,"name"),organizationId:I(e,"organizationId"),slug:X(e,"slug")}),http:"POST",method:"updateOrganization"},[`${v}/organizations/remove`]:{build:({body:e})=>({organizationId:I(e,"organizationId")}),http:"POST",method:"deleteOrganization",returns:"void"},[`${v}/organizations/members/add`]:{build:({body:e})=>({organizationId:I(e,"organizationId"),role:X(e,"role"),userId:I(e,"userId")}),http:"POST",method:"addMember"},[`${v}/organizations/members/invite`]:{build:({body:e})=>({email:I(e,"email"),inviterId:X(e,"inviterId"),organizationId:I(e,"organizationId"),role:X(e,"role")}),http:"POST",method:"inviteMember"},[`${v}/organizations/members/role`]:{build:({body:e})=>{const r=Ne(e.role);if(r===void 0||typeof r=="string"&&r.trim()==="")throw new a("`role` is required",{code:"BAD_REQUEST",status:400});return{memberId:I(e,"memberId"),role:r}},http:"POST",method:"updateMemberRole"},[`${v}/organizations/teams/create`]:{build:({body:e})=>({name:I(e,"name"),organizationId:I(e,"organizationId")}),http:"POST",method:"createTeam"},[`${v}/organizations/teams/update`]:{build:({body:e})=>({name:I(e,"name"),teamId:I(e,"teamId")}),http:"POST",method:"updateTeam"},[`${v}/organizations/teams/remove`]:{build:({body:e})=>({teamId:I(e,"teamId")}),http:"POST",method:"removeTeam",returns:"void"},[`${v}/organizations/teams/members/add`]:{build:({body:e})=>({teamId:I(e,"teamId"),userId:I(e,"userId")}),http:"POST",method:"addTeamMember"},[`${v}/organizations/teams/members/remove`]:{build:({body:e})=>({teamMemberId:I(e,"teamMemberId")}),http:"POST",method:"removeTeamMember",returns:"void"},[`${v}/organizations/roles/create`]:{build:({body:e})=>({organizationId:I(e,"organizationId"),permission:Ve(e),role:I(e,"role")}),http:"POST",method:"createOrgRole"},[`${v}/organizations/roles/update`]:{build:({body:e})=>({permission:Ve(e),roleId:I(e,"roleId")}),http:"POST",method:"updateOrgRole"},[`${v}/organizations/roles/remove`]:{build:({body:e})=>({roleId:I(e,"roleId")}),http:"POST",method:"deleteOrgRole",returns:"void"}},kr=e=>{const r=async s=>{try{return await s()}catch(i){if(i instanceof a)throw i;const u=i,l=typeof u.code=="string"?u.code:"AUTH_ADMIN_ERROR";throw console.error("[lunora] auth admin operation failed:",i),new a("auth admin operation failed",{code:l,status:Dr[l]??500})}},t=async(s,i)=>{if(e.assertAdmin(s),s.method!==i.http)throw new a(`Auth admin endpoint requires ${i.http}`,{code:"METHOD_NOT_ALLOWED",status:405});const u=e.getAuthAdmin();if(u===void 0)throw new a("auth endpoints require an `authAdmin` on the worker",{code:"AUTH_NOT_CONFIGURED",status:400});const l=u[i.method];if(l===void 0)throw new a(`auth admin does not support \`${i.method}\``,{code:"AUTH_OP_NOT_SUPPORTED",status:400});const y=new URL(s.url),O={body:i.http==="POST"?await e.readJsonBody(s):{},paging:e.parsePaging(s),query:g=>e.queryParameter(y,g)},A=i.build(O),w=await r(()=>l(A));return Response.json(i.returns==="void"?{ok:!0}:w,{headers:{"content-type":"application/json"},status:200})},n={};for(const[s,i]of Object.entries(vr))n[s]=u=>t(u,i);return n},Ye=500,Ir=(e,r,t)=>{if(typeof e!="object"||e===null||Array.isArray(e))throw new a("each batch call must be an object",{code:"BAD_REQUEST",status:400});const n=e;if(typeof n.functionPath!="string")throw new a("each batch call needs a string `functionPath`",{code:"BAD_REQUEST",status:400});if(n.functionPath.startsWith("__lunora_relation__:")||n.functionPath.startsWith("__lunora_admin__"))throw new a("reserved function path cannot be batched",{code:"FORBIDDEN",status:403});if(n.args!==void 0&&(typeof n.args!="object"||n.args===null||Array.isArray(n.args)))throw new a("each batch call `args` must be an object",{code:"BAD_REQUEST",status:400});return{entry:{args:n.args===void 0?{}:n.args,clientId:typeof n.clientId=="string"?n.clientId:void 0,clientSeq:typeof n.clientSeq=="number"?n.clientSeq:void 0,functionPath:n.functionPath,id:typeof n.id=="number"?n.id:r,mutationId:typeof n.mutationId=="string"?n.mutationId:void 0},shardKey:typeof n.shardKey=="string"?n.shardKey:t}},Pr=(e,r)=>{if(e.length>Ye)throw new a(`RPC batch exceeds the ${String(Ye)}-call limit`,{code:"BAD_REQUEST",status:400});const t=new Map;for(const[n,s]of e.entries()){const{entry:i,shardKey:u}=Ir(s,n,r),l=t.get(u)??[];l.push(i),t.set(u,l)}return t},ge=1048576,ae=async(e,r=ge)=>{if(!e.body)return"";const t=e.body.getReader(),n=new TextDecoder;let s=0,i="";for(;;){const{done:u,value:l}=await t.read();if(u)break;if(l){if(s+=l.byteLength,s>r)throw await t.cancel().catch(()=>{}),new a("Body too large",{code:"PAYLOAD_TOO_LARGE",status:413});i+=n.decode(l,{stream:!0})}}return i+=n.decode(),i},Nr=async(e,r=ge)=>{if(!e.body)return new ArrayBuffer(0);const t=e.body.getReader(),n=[];let s=0;for(;;){const{done:l,value:y}=await t.read();if(l)break;if(y){if(s+=y.byteLength,s>r)throw await t.cancel().catch(()=>{}),new a("Body too large",{code:"PAYLOAD_TOO_LARGE",status:413});n.push(y)}}const i=new Uint8Array(s);let u=0;for(const l of n)i.set(l,u),u+=l.byteLength;return i.buffer},Z=async(e,r=ge)=>{try{const t=await ae(e,r);return t===""?{}:JSON.parse(t)}catch(t){throw t instanceof a?t:new a("Request body must be valid JSON",{code:"BAD_REQUEST",status:400})}},Ur=new TextEncoder,qr=e=>{const r=JSON.stringify(e),t=Ur.encode(r);let n="";for(const s of t)n+=String.fromCodePoint(s);return btoa(n).replaceAll("+","-").replaceAll("/","_").replaceAll("=","")},$r=e=>{const r={g:0,s:{},v:1};if(typeof e!="string"||e.length===0)return r;try{const t=atob(e.replaceAll("-","+").replaceAll("_","/")),n=new Uint8Array(t.length);for(let l=0;l<t.length;l+=1)n[l]=t.codePointAt(l)??0;const s=JSON.parse(new TextDecoder().decode(n)),i=s.s&&typeof s.s=="object"?s.s:{},u={};for(const[l,y]of Object.entries(i))typeof y=="number"&&Number.isFinite(y)&&(u[l]=y);return{g:typeof s.g=="number"&&Number.isFinite(s.g)?s.g:0,s:u,v:1}}catch{return r}},Lr=e=>{const r=typeof e.table=="string"?e.table:"",t=typeof e.op=="string"?e.op:"",n=t==="delete"||t==="insert"||t==="update"?t:"upsert",s=typeof e.id=="string"?e.id:void 0;return{doc:(e.doc&&typeof e.doc=="object"?e.doc:void 0)??(s===void 0?{}:{_id:s}),op:n,table:r}},Xe=(e,r,t)=>{for(const n of r)e.push(Lr(n));return t!==void 0&&r.length>=t},Br="/_lunora/admin/export",xr="/_lunora/admin/import",Cr="/_lunora/admin/sync",jr="/_lunora/admin/connector/sync",Gr="/_lunora/admin/apply",Kr="/_lunora/admin/export-tap/run",Mr=new TextEncoder,Qr=async e=>{let r;try{const s=await ae(e);r=s===""?{}:JSON.parse(s)}catch(s){throw s instanceof a?s:new a("Export body must be valid JSON",{code:"BAD_REQUEST",status:400})}const t=r??{};if(t.tables===void 0)return{tables:void 0};if(!Array.isArray(t.tables))throw new a("Export `tables` must be a string array",{code:"BAD_REQUEST",status:400});const n=[];for(const s of t.tables){if(typeof s!="string"||s.length===0)throw new a("Export `tables` entries must be non-empty strings",{code:"BAD_REQUEST",status:400});n.push(s)}return{tables:n}},Fr=e=>{const{applyGlobals:r,exportCursorStore:t,exportSinks:n,knownTables:s,queryCoordinator:i,requireAdminOption:u,resolveForwardContext:l,shardDO:y,streamExportRows:O,streamingImport:A,syncGlobals:w}=e,g=async(E,q)=>{const B=fe(E,["POST"]);if(B)return B;const K=u(E,i,{code:"BAD_REQUEST",message:"Export endpoint requires a `queryCoordinator` on the worker"}),N=await Qr(E),{headers:M}=await l(E,q),Q=new ReadableStream({async pull(Y){const x=G=>{Y.enqueue(Mr.encode(`${JSON.stringify(G)}
2
- `))};try{await O(K,M,N.tables,x),Y.close()}catch(G){Y.error(G)}}});return new Response(Q,{headers:{"content-type":"application/x-ndjson"},status:200})},p=async(E,q)=>{const B=fe(E,["POST"]);if(B)return B;const K=u(E,i,{code:"BAD_REQUEST",message:"Sync endpoint requires a `queryCoordinator` on the worker"}),N=await Z(E),M=typeof N.cursors=="object"&&N.cursors!==null?N.cursors:{},Q=typeof N.limit=="number"?N.limit:void 0,Y=typeof N.globalCursor=="number"?N.globalCursor:0,x=Array.isArray(N.tables)?N.tables.filter(ne=>typeof ne=="string"):void 0,{headers:G}=await l(E,q),J=x??s(),re=await K.orchestrateCdcSync(y,{cursors:M,headers:G,limit:Q,tables:J}),se=w?await w({limit:Q,sinceSeq:Y}):void 0;return Response.json({global:se,shards:re.shards},{status:200})},f=async(E,q)=>{const B=fe(E,["POST"]);if(B)return B;const K=u(E,i,{code:"BAD_REQUEST",message:"Connector sync endpoint requires a `queryCoordinator` on the worker"}),N=await Z(E),M=$r(N.cursor),Q=typeof N.limit=="number"&&N.limit>0?N.limit:void 0,Y=Array.isArray(N.tables)?N.tables.filter(ee=>typeof ee=="string"):void 0,{headers:x}=await l(E,q),G=Y??s(),J=await K.orchestrateCdcSync(y,{cursors:M.s,headers:x,limit:Q,tables:G}),re=[],se={...M.s};let ne=!1;for(const ee of J.shards)ne=Xe(re,ee.changes??[],Q)||ne,se[ee.shardKey]=ee.cursor;let le=M.g;if(w){const ee=await w({limit:Q,sinceSeq:M.g});ne=Xe(re,ee.changes,Q)||ne,le=ee.cursor}const we=qr({g:le,s:se,v:1}),be={changes:re,hasMore:ne,nextCursor:we};return Response.json(be,{status:200})},_=async(E,q)=>{const B=fe(E,["POST"]);if(B)return B;const K=u(E,i,{code:"BAD_REQUEST",message:"Apply endpoint requires a `queryCoordinator` on the worker"}),N=await Z(E),M=(Array.isArray(N.batches)?N.batches:[]).map(J=>J).filter(J=>J!==null&&typeof J=="object"&&typeof J.shardKey=="string"&&Array.isArray(J.changes)),Q=Array.isArray(N.globalChanges)?N.globalChanges:[],{headers:Y}=await l(E,q),x=await K.orchestrateApplyCdc(y,{batches:M,headers:Y}),G=Q.length>0&&r?await r({changes:Q}):0;return Response.json({applied:x.applied+G,failed:x.failed,ok:x.ok},{status:200})},R=async(E,q)=>{const B=fe(E,["POST"]);if(B)return B;u(E,i,{code:"BAD_REQUEST",message:"Import endpoint requires a `queryCoordinator` on the worker"});const{headers:K}=await l(E,q),N=await A(E,K);return Response.json(N,{headers:{"content-type":"application/json"},status:200})},P=async(E,q)=>{const B=fe(E,["POST"]);if(B)return B;const K=u(E,i,{code:"BAD_REQUEST",message:"Export-tap endpoint requires a `queryCoordinator` on the worker"});if(n===void 0||Object.keys(n).length===0||t===void 0)throw new a("Export-tap endpoint requires `exportSinks` + `exportCursorStore` on the worker",{code:"EXPORT_TAP_NOT_CONFIGURED",status:400});const N=await Z(E),M=typeof N.sink=="string"?N.sink:void 0,Q=typeof N.limit=="number"&&N.limit>0?N.limit:void 0,Y=Array.isArray(N.tables)?N.tables.filter(se=>typeof se=="string"):void 0;if(M===void 0)throw new a("Export-tap `sink` must name a configured sink",{code:"BAD_REQUEST",status:400});const x=n[M];if(x===void 0)throw new a(`Export-tap sink "${M}" is not configured`,{code:"NOT_FOUND",status:404});const{headers:G}=await l(E,q),J=Y??s(),re=await tr({coordinator:K,cursorStore:t,headers:G,limit:Q,shardDO:y,sink:x,tables:J});return Response.json(re,{headers:{"content-type":"application/json"},status:200})};return{[Gr]:_,[jr]:f,[Br]:g,[Kr]:P,[xr]:R,[Cr]:p}},pt=e=>[],zr=(e,r)=>{const t=[],n=[];if(r&&r.length>0)for(const s of r)e.resolveTableSharding?.(s)?.mode.kind==="global"?n.push(s):t.push(s);return{globalTables:n,shardLocalTables:t}},Wr=async(e,r,t,n,s,i,u)=>{if(n!==void 0&&s.length===0)return;const l=n===void 0?[]:s,y=n===void 0?pt():[],O=l.length>0?l:y,A=await r.orchestrateExport(u,{args:{tables:l},headers:t,tables:O});for(const w of A.shards)if(!w.error)for(const g of w.rows??[])i(g)},Ze=async(e,r,t,n,s,i)=>{const{globalTables:u,shardLocalTables:l}=zr(e,n);await Wr(e,r,t,n,l,s,i);const y=e.exportGlobals;if((n===void 0||u.length>0)&&y){const O=n===void 0?[]:u;for await(const A of y({tables:O}))s(A)}},Hr=(e,r)=>{let t;try{t=JSON.parse(e)}catch{return{error:{code:"BAD_ROW",line:r,message:"line is not valid JSON",table:""},ok:!1}}if(!t||typeof t!="object"||Array.isArray(t))return{error:{code:"BAD_ROW",line:r,message:"row must be a JSON object",table:""},ok:!1};const n=t;return typeof n.table!="string"||n.table.length===0?{error:{code:"BAD_ROW",line:r,message:"row is missing `table`",table:""},ok:!1}:!n.doc||typeof n.doc!="object"||Array.isArray(n.doc)?{error:{code:"BAD_ROW",line:r,message:"row is missing or malformed `doc`",table:n.table},ok:!1}:{doc:n.doc,ok:!0,table:n.table}},Jr=(e,r,t,n,s)=>{if(t?.mode.kind==="shardBy"&&typeof t.mode.field=="string"){const i=e[t.mode.field];return i==null?{error:{code:"BAD_ROW",line:s,message:`row missing shard field "${t.mode.field}" for table "${r}"`,table:r},ok:!1}:{ok:!0,shardKey:typeof i=="string"?i:JSON.stringify(i)}}return{ok:!0,shardKey:n}},Vr=async(e,r,t)=>{if(!e.body)throw new a("Import endpoint requires a request body",{code:"BAD_REQUEST",status:400});const n=[],s=[],i=new Map;let u=0;const l=e.body.getReader(),y=new TextDecoder;let O="",A=0;const w=g=>{u+=1;const p=g.trim();if(p.length===0)return;const f=Hr(p,u);if(!f.ok){n.push(f.error);return}const{doc:_,table:R}=f,P=r.resolveTableSharding?.(R);if(P?.mode.kind==="global"){s.push({doc:_,line:u,table:R});return}const E=Jr(_,R,P,t,u);if(!E.ok){n.push(E.error);return}const q=i.get(E.shardKey);q?q.rows.push({doc:_,table:R}):i.set(E.shardKey,{rows:[{doc:_,table:R}],shardKey:E.shardKey,startLine:u})};for(;;){const{done:g,value:p}=await l.read();if(g)break;if(p&&(A+=p.byteLength,A>ge))throw await l.cancel().catch(()=>{}),new a("Body too large",{code:"PAYLOAD_TOO_LARGE",status:413});O+=y.decode(p,{stream:!0});let f=O.indexOf(`
3
- `);for(;f!==-1;){const _=O.slice(0,f);O=O.slice(f+1),w(_),f=O.indexOf(`
4
- `)}}return O.length>0&&w(O),{errors:n,globalRows:s,perShard:i}},et=(e,r)=>{for(const[t,n]of Object.entries(r.inserted))e.inserted[t]=(e.inserted[t]??0)+n;for(const t of r.errors)e.errors.push({...t});e.conflicts+=r.conflicts},Yr=async(e,r,t,n)=>{const s=r.defaultShardKey??"__root__",{errors:i,globalRows:u,perShard:l}=await Vr(e,r,s),y={conflicts:0,errors:i,inserted:{}};if(l.size>0){const O=r.queryCoordinator;if(!O)throw new a("Import endpoint requires a `queryCoordinator` on the worker",{code:"BAD_REQUEST",status:400});const A=await O.orchestrateImport(n,{batches:[...l.values()],headers:t});et(y,A)}if(u.length>0)if(r.importGlobals){const O=u[0]?.line??1,A=await r.importGlobals({rows:u,startLine:O});et(y,A)}else for(const O of u)y.errors.push({code:"GLOBAL_NOT_CONFIGURED",line:O.line,message:`row targets global table "${O.table}" but no \`importGlobals\` is configured`,table:O.table});return{conflicts:y.conflicts,errors:y.errors,inserted:y.inserted}},Ue=e=>typeof e=="object"&&e!==null?e:{},qe=e=>typeof e.kind=="string"?e.kind:"unknown",Xr=(e,r)=>{let t=Ue(r),n=!1;qe(t)==="optional"&&(n=!0,t=Ue(t._meta?.inner));const s=qe(t),i=t._meta??{},u={kind:s,name:e,optional:n};if(s==="id"&&typeof i.tableName=="string"&&(u.table=i.tableName),s==="array"){const l=qe(Ue(i.inner));l!=="unknown"&&(u.element=l)}return u},Zr=e=>typeof e!="object"||e===null?[]:Object.entries(e).map(([r,t])=>Xr(r,t)).toSorted((r,t)=>r.name.localeCompare(t.name)),en="/_lunora/admin/functions",tn="/_lunora/admin/cron-jobs",rn="/_lunora/admin/openapi",nn="/_lunora/admin/openrpc",on="/_lunora/admin/global/tables",an="/_lunora/admin/global/table",sn="/_lunora/admin/global/facet",tt=e=>{if(e===void 0||e==="")return;let r;try{r=JSON.parse(e)}catch{return}if(!Array.isArray(r))return;const t=r.flatMap(n=>{if(typeof n!="object"||n===null||typeof n.column!="string")return[];const{column:s,value:i}=n;return[{column:s,value:i}]});return t.length===0?void 0:t},dn=Object.freeze({info:{description:'No OpenAPI spec is configured on this worker. Run `lunora codegen`, then wire the generated module to `createWorker`: `import { openApiSpec } from "./lunora/_generated/openapi"`.',title:"Lunora API",version:"0.0.0"},openapi:"3.1.0",paths:{}}),un=Object.freeze({info:{description:'No OpenRPC spec is configured on this worker. Run `lunora codegen --api-spec openrpc` (or `both`), then wire the generated module to `createWorker`: `import { openRpcSpec } from "./lunora/_generated/openrpc"`.',title:"Lunora RPC",version:"0.0.0"},methods:[],openrpc:"1.3.2"}),cn=e=>{const{assertAdmin:r,options:t,parsePaging:n,queryParameter:s,requireAdminOption:i}=e,u=p=>{if(p.method!=="GET")throw new a("Functions endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});const f=i(p,t.functions,{code:"FUNCTIONS_NOT_CONFIGURED",message:"functions endpoint requires a `functions` registry on the worker"}),_=Object.entries(f).flatMap(([R,P])=>P.visibility==="internal"||P.kind==="stream"?[]:[{args:Zr(P.args),kind:P.kind,path:R}]).toSorted((R,P)=>R.path.localeCompare(P.path));return Response.json({functions:_},{headers:{"content-type":"application/json"},status:200})},l=p=>{if(p.method!=="GET")throw new a("Cron-jobs endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});const f=i(p,t.cronJobs,{code:"CRON_JOBS_NOT_CONFIGURED",message:"cron-jobs endpoint requires a `cronJobs` map on the worker"}),_=Object.entries(f).flatMap(([R,P])=>P.map(E=>({args:E.args,cron:R,functionPath:E.functionPath,name:E.name,shardKey:E.shardKey,workflow:E.workflow}))).toSorted((R,P)=>R.name.localeCompare(P.name));return Response.json({jobs:_},{headers:{"content-type":"application/json"},status:200})},y=p=>{if(p.method!=="GET")throw new a("OpenAPI endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});return r(p),Response.json(t.openApiSpec??dn,{headers:{"content-type":"application/json"},status:200})},O=p=>{if(p.method!=="GET")throw new a("OpenRPC endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});return r(p),Response.json(t.openRpcSpec??un,{headers:{"content-type":"application/json"},status:200})},A=async p=>{if(p.method!=="GET")throw new a("Global-tables endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});const f=i(p,t.globalIntrospector,{code:"GLOBALS_NOT_CONFIGURED",message:"global endpoints require a `globalIntrospector` on the worker"});return Response.json(await f.listTables(),{headers:{"content-type":"application/json"},status:200})},w=async p=>{if(p.method!=="GET")throw new a("Global-table endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});const f=i(p,t.globalIntrospector,{code:"GLOBALS_NOT_CONFIGURED",message:"global endpoints require a `globalIntrospector` on the worker"}),_=new URL(p.url),R=s(_,"table");if(R===void 0)throw new a("Global-table endpoint requires a `table` query param",{code:"BAD_REQUEST",status:400});const P=await f.readTablePage({...n(p),filters:tt(s(_,"filters")),table:R});return Response.json(P,{headers:{"content-type":"application/json"},status:200})},g=async p=>{if(p.method!=="GET")throw new a("Global-facet endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});const f=i(p,t.globalIntrospector,{code:"GLOBALS_NOT_CONFIGURED",message:"global endpoints require a `globalIntrospector` on the worker"}),_=new URL(p.url),R=s(_,"table"),P=s(_,"column");if(R===void 0||P===void 0)throw new a("Global-facet endpoint requires `table` and `column` query params",{code:"BAD_REQUEST",status:400});const E=s(_,"limit"),q=E===void 0?void 0:Number(E),B=await f.facetColumn({column:P,filters:tt(s(_,"filters")),limit:q!==void 0&&Number.isFinite(q)?q:void 0,table:R});return Response.json(B,{headers:{"content-type":"application/json"},status:200})};return{[tn]:l,[en]:u,[sn]:g,[an]:w,[on]:A,[rn]:y,[nn]:O}},ln="/_lunora/admin/kv/namespaces",hn="/_lunora/admin/kv/keys",ft="/_lunora/admin/kv/value",mt=32*1048576,rt=60,pn=e=>{const{readJsonBody:r,requireAdminOption:t}=e,n=w=>t(w,e.kvIntrospector,{code:"KV_NOT_CONFIGURED",message:"KV endpoints require a `kvIntrospector` on the worker"}),s=w=>Response.json(w,{headers:{"content-type":"application/json"},status:200}),i=(w,g)=>{const p=new URL(w.url),f=p.searchParams.get("namespace")??"",_=p.searchParams.get("key")??"";if(f==="")throw new a(`KV-value ${g} request requires a \`namespace\` query parameter`,{code:"BAD_REQUEST",status:400});if(_==="")throw new a(`KV-value ${g} request requires a \`key\` query parameter`,{code:"BAD_REQUEST",status:400});return{key:_,namespace:f}},u=async(w,g)=>{if(!(await w.listNamespaces()).some(p=>p.binding===g))throw new a(`Unknown KV namespace binding \`${g}\``,{code:"NOT_FOUND",status:404})},l=async w=>{if(w.method!=="GET")throw new a("KV-namespaces endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});return s({namespaces:await n(w).listNamespaces()})},y=async w=>{if(w.method!=="GET")throw new a("KV-keys endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});const g=n(w),p=new URL(w.url),f=p.searchParams.get("namespace")??"";if(f==="")throw new a("KV-keys request requires a `namespace` query parameter",{code:"BAD_REQUEST",status:400});const _=p.searchParams.get("prefix")??void 0,R=p.searchParams.get("cursor")??void 0,P=p.searchParams.get("limit"),E=P===null?void 0:Number.parseInt(P,10);if(E!==void 0&&(!Number.isInteger(E)||E<1))throw new a("KV-keys `limit` must be a positive integer",{code:"BAD_REQUEST",status:400});const q=E===void 0?void 0:Math.min(E,1e3);return await u(g,f),s(await g.listKeys({cursor:R,limit:q,namespace:f,prefix:_}))},O={DELETE:async w=>{const g=n(w),p=i(w,"DELETE");return await u(g,p.namespace),await g.deleteKey(p),s({deleted:!0})},GET:async w=>{const g=n(w),p=i(w,"GET");return await u(g,p.namespace),s(await g.getValue(p))},PUT:async w=>{const g=n(w),p=await r(w,mt);if(typeof p.namespace!="string"||p.namespace==="")throw new a("KV-value PUT request requires a `namespace` string",{code:"BAD_REQUEST",status:400});if(typeof p.key!="string"||p.key==="")throw new a("KV-value PUT request requires a `key` string",{code:"BAD_REQUEST",status:400});if(typeof p.value!="string")throw new a("KV-value PUT request requires a `value` string",{code:"BAD_REQUEST",status:400});if(p.expirationTtl!==void 0&&(typeof p.expirationTtl!="number"||!Number.isInteger(p.expirationTtl)||p.expirationTtl<rt))throw new a("KV-value PUT `expirationTtl` must be an integer ≥ 60",{code:"BAD_REQUEST",status:400});const f=Math.floor(Date.now()/1e3)+rt;if(p.expiration!==void 0&&(typeof p.expiration!="number"||!Number.isInteger(p.expiration)||p.expiration<f))throw new a("KV-value PUT `expiration` must be a Unix-seconds timestamp at least 60 seconds in the future",{code:"BAD_REQUEST",status:400});return await u(g,p.namespace),await g.putValue({expiration:p.expiration,expirationTtl:p.expirationTtl,key:p.key,metadata:p.metadata,namespace:p.namespace,value:p.value}),s({ok:!0})}},A=w=>{const g=O[w.method];if(!g)throw new a("KV-value endpoint requires GET, PUT, or DELETE",{code:"METHOD_NOT_ALLOWED",status:405});return g(w)};return{[ln]:l,[hn]:y,[ft]:A}},fn="/_lunora/migrate",mn="/_lunora/admin/pitr",wn="/_lunora/admin/rank",yn="/_lunora/admin/rankpage",gn="/_lunora/admin/shard-traffic",bn=new Set(["__lunora_admin__:migrationStatus","__lunora_admin__:runMigration"]),On=new Set(["__lunora_admin__:getPitrBookmark","__lunora_admin__:pitrRestore"]),En=async e=>{let r;try{const n=await ae(e);r=n===""?{}:JSON.parse(n)}catch(n){throw n instanceof a?n:new a("Migration body must be valid JSON",{code:"BAD_REQUEST",status:400})}const t=r??{};if(typeof t.table!="string"||t.table.length===0)throw new a("Migration request is missing `table`",{code:"BAD_REQUEST",status:400});if(typeof t.functionPath!="string"||!bn.has(t.functionPath))throw new a("Migration request `functionPath` must be a migration admin op",{code:"BAD_REQUEST",status:400});return{args:t.args??{},functionPath:t.functionPath,table:t.table}},Tn=async e=>{let r;try{const n=await ae(e);r=n===""?{}:JSON.parse(n)}catch(n){throw n instanceof a?n:new a("Rank body must be valid JSON",{code:"BAD_REQUEST",status:400})}const t=r??{};if(typeof t.table!="string"||t.table.length===0)throw new a("Rank request is missing `table`",{code:"BAD_REQUEST",status:400});if(typeof t.index!="string"||t.index.length===0)throw new a("Rank request is missing `index`",{code:"BAD_REQUEST",status:400});if(typeof t.partitionKey!="string")throw new a("Rank request `partitionKey` must be a string",{code:"BAD_REQUEST",status:400});if(typeof t.rowId!="string"||t.rowId.length===0)throw new a("Rank request is missing `rowId`",{code:"BAD_REQUEST",status:400});if(!Array.isArray(t.sortValues))throw new a("Rank request `sortValues` must be an array",{code:"BAD_REQUEST",status:400});return{index:t.index,partitionKey:t.partitionKey,rowId:t.rowId,sortValues:t.sortValues,table:t.table}},_n=e=>{if(e!==void 0){if(!Array.isArray(e)||e.some(r=>r!=="asc"&&r!=="desc"))throw new a('Rank page request `directions` must be an array of "asc"|"desc"',{code:"BAD_REQUEST",status:400});return e}},Rn=e=>{if(typeof e.table!="string"||e.table.length===0)throw new a("Rank page request is missing `table`",{code:"BAD_REQUEST",status:400});if(typeof e.index!="string"||e.index.length===0)throw new a("Rank page request is missing `index`",{code:"BAD_REQUEST",status:400});if(e.partitionKey!==void 0&&typeof e.partitionKey!="string")throw new a("Rank page request `partitionKey` must be a string",{code:"BAD_REQUEST",status:400});if(e.take!==void 0&&(typeof e.take!="number"||!Number.isFinite(e.take)))throw new a("Rank page request `take` must be a number",{code:"BAD_REQUEST",status:400});if(e.cursor!==void 0&&e.cursor!==null&&typeof e.cursor!="string")throw new a("Rank page request `cursor` must be a string or null",{code:"BAD_REQUEST",status:400})},Sn=async e=>{let r;try{const s=await ae(e);r=s===""?{}:JSON.parse(s)}catch(s){throw s instanceof a?s:new a("Rank page body must be valid JSON",{code:"BAD_REQUEST",status:400})}const t=r??{};Rn(t);const n=_n(t.directions);return{cursor:typeof t.cursor=="string"?t.cursor:null,directions:n,index:t.index,partitionKey:typeof t.partitionKey=="string"?t.partitionKey:void 0,table:t.table,take:typeof t.take=="number"?t.take:void 0}},An=async e=>{let r;try{const n=await ae(e);r=n===""?{}:JSON.parse(n)}catch(n){throw n instanceof a?n:new a("Shard-traffic body must be valid JSON",{code:"BAD_REQUEST",status:400})}const t=r??{};if(typeof t.table!="string"||t.table.length===0)throw new a("Shard-traffic request is missing `table`",{code:"BAD_REQUEST",status:400});return{table:t.table}},Dn=async e=>{const r=await Z(e);if(typeof r.functionPath!="string"||!On.has(r.functionPath))throw new a("PITR request `functionPath` must be a PITR admin op",{code:"BAD_REQUEST",status:400});if(r.shardKey!==void 0&&typeof r.shardKey!="string")throw new a("PITR `shardKey` must be a string",{code:"BAD_REQUEST",status:400});return{args:r.args??{},functionPath:r.functionPath,shardKey:r.shardKey}},vn=e=>{const{defaultShard:r,forwardToShard:t,isAdmin:n,queryCoordinator:s,resolveForwardContext:i,shardDO:u}=e,l=async(g,p)=>{if(g.method!=="POST")throw new a("Migration endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});if(!n(g))throw new a("Admin auth required",{code:"FORBIDDEN",status:403});if(!s)throw new a("Migration endpoint requires a `queryCoordinator` on the worker",{code:"BAD_REQUEST",status:400});const f=await En(g),{headers:_}=await i(g,p),R=await s.orchestrateMigration(u,{args:f.args,functionPath:f.functionPath,headers:_,table:f.table});return Response.json(R,{headers:{"content-type":"application/json"},status:200})},y=async(g,p)=>{if(g.method!=="POST")throw new a("Rank endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});if(!n(g))throw new a("Admin auth required",{code:"FORBIDDEN",status:403});if(!s)throw new a("Rank endpoint requires a `queryCoordinator` on the worker",{code:"BAD_REQUEST",status:400});const f=await Tn(g),{headers:_}=await i(g,p),R=await s.orchestrateRank(u,{headers:_,index:f.index,partitionKey:f.partitionKey,rowId:f.rowId,sortValues:f.sortValues,table:f.table});return Response.json(R,{headers:{"content-type":"application/json"},status:200})},O=async(g,p)=>{if(g.method!=="POST")throw new a("Rank page endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});if(!n(g))throw new a("Admin auth required",{code:"FORBIDDEN",status:403});if(!s)throw new a("Rank page endpoint requires a `queryCoordinator` on the worker",{code:"BAD_REQUEST",status:400});const f=await Sn(g),{headers:_}=await i(g,p),R=await s.orchestrateRankPage(u,{...f,headers:_});return Response.json(R,{headers:{"content-type":"application/json"},status:200})},A=async(g,p)=>{if(g.method!=="POST")throw new a("Shard-traffic endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});if(!n(g))throw new a("Admin auth required",{code:"FORBIDDEN",status:403});if(!s)throw new a("Shard-traffic endpoint requires a `queryCoordinator` on the worker",{code:"BAD_REQUEST",status:400});const f=await An(g),{headers:_}=await i(g,p),R=await s.orchestrateShardTraffic(u,{headers:_,table:f.table});return Response.json(R,{headers:{"content-type":"application/json"},status:200})},w=async(g,p)=>{if(g.method!=="POST")throw new a("PITR endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});if(!n(g))throw new a("admin PITR endpoint requires a valid admin bearer",{code:"ADMIN_FORBIDDEN",status:403});const f=await Dn(g),{headers:_}=await i(g,p),R=new Request("https://shard.internal/rpc",{body:JSON.stringify({args:f.args,functionPath:f.functionPath}),headers:_,method:"POST"});return t(u,f.shardKey??r,R)};return{[fn]:l,[mn]:w,[wn]:y,[yn]:O,[gn]:A}},kn=1,In=0,Pn=32,Nn=512,Un=/^[a-z][\d_a-z*/-]{0,255}(?:@[a-z][\d_a-z*/-]{0,13})?=[\u0020-\u002B\u002D-\u003C\u003E-\u007E]{1,256}$/,qn=e=>{if(e==null)return;const r=e.trim();if(r.length===0||r.length>Nn)return;const t=r.split(",");if(!(t.length>Pn)){for(const n of t)if(!Un.test(n.trim()))return;return r}},$n=e=>{const r=ur(e.headers.get("traceparent"));if(r===void 0)return;const t=qn(e.headers.get("tracestate"));return{parentSpanId:r.parentSpanId,sampled:r.sampled,traceId:r.traceId,...t===void 0?{}:{traceState:t}}},Ln=(e,r={})=>{const t=$n(e),n=r.trustInbound===!0?t:void 0,s=Fe(8),i=n?.traceId??Fe(16),u=ir(r.sampling,n===void 0?s:i),l=u.isTraced&&(n===void 0||n.sampled);return{decision:u,ignoredUpstream:t!==void 0&&n===void 0,trace:{sampled:l,spanId:s,traceFlags:l?kn:In,traceId:i,...n?.parentSpanId===void 0?{}:{parentSpanId:n.parentSpanId},...n?.traceState===void 0?{}:{traceState:n.traceState}}}},Bn=(e,r)=>{r.traceparent=dr(e.traceId,e.spanId,e.sampled),e.traceState!==void 0&&(r.tracestate=e.traceState)},xn=(e,r)=>{let t;return()=>{if(t===void 0){const n=pr(e),s=r===void 0?void 0:r.cf;t=cr(hr(n),lr(n,s))}return t}},Cn="/_lunora/admin/scheduled",jn="/_lunora/admin/scheduled/status",Gn="/_lunora/admin/scheduled/ws",Kn="/_lunora/admin/scheduled/cancel",Mn="/_lunora/admin/scheduled/dead",Qn="/_lunora/admin/scheduled/dead/retry",Fn="/_lunora/admin/scheduled/dead/cancel",zn=e=>{const{checkWsAdmin:r,requireSchedulerNamespace:t,resolveSchedulerStub:n,schedulerInstanceName:s}=e,i=async w=>{if(w.method!=="GET")throw new a("Scheduled-list endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});return n(w).fetch(new Request("https://scheduler.internal/list",{method:"GET"}))},u=async w=>{if(w.method!=="GET")throw new a("Scheduler-status endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});return n(w).fetch(new Request("https://scheduler.internal/status",{method:"GET"}))},l=async w=>{if(w.headers.get("Upgrade")!=="websocket")throw new a("WebSocket upgrade header missing",{code:"BAD_REQUEST",status:426});if(!await r(w))throw new a("admin authorization required",{code:"ADMIN_FORBIDDEN",status:403});const g=t();return _e(g,s).fetch(new Request("https://scheduler.internal/ws",{headers:{Upgrade:"websocket"}}))},y=async w=>{if(w.method!=="POST")throw new a("Scheduled-cancel endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});const g=n(w),p=await w.json().catch(()=>{});if(typeof p?.id!="string"||p.id==="")throw new a("Scheduled-cancel requires a string `id`",{code:"BAD_REQUEST",status:400});return g.fetch(new Request("https://scheduler.internal/cancel",{body:JSON.stringify({id:p.id}),headers:{"content-type":"application/json"},method:"POST"}))},O=async w=>{if(w.method!=="GET")throw new a("Scheduled dead-letter endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});return n(w).fetch(new Request("https://scheduler.internal/dead",{method:"GET"}))},A=w=>async g=>{if(g.method!=="POST")throw new a("Scheduled dead-letter action requires POST",{code:"METHOD_NOT_ALLOWED",status:405});const p=n(g),f=await g.json().catch(()=>{});if(typeof f?.id!="string"||f.id==="")throw new a("Scheduled dead-letter action requires a string `id`",{code:"BAD_REQUEST",status:400});return p.fetch(new Request(`https://scheduler.internal${w}`,{body:JSON.stringify({id:f.id}),headers:{"content-type":"application/json"},method:"POST"}))};return{[Kn]:y,[Fn]:A("/dead/cancel"),[Mn]:O,[Qn]:A("/dead/retry"),[Cn]:i,[jn]:u,[Gn]:l}},Wn="/_lunora/admin/storage",Hn="/_lunora/admin/storage/url",Jn="/_lunora/admin/storage/buckets",Vn=10080*60,Yn=e=>{const{assertAdmin:r,parsePaging:t,queryParameter:n,readBodyBytes:s,requireAdminOption:i,storage:u}=e,l=f=>{const _=n(f,"key");if(_===void 0)throw new a("Storage endpoint requires a `key` query parameter",{code:"BAD_REQUEST",status:400});return _},y=async f=>{const _=i(f,u.storageList,{code:"STORAGE_NOT_CONFIGURED",message:"storage endpoint requires a `storageList` function on the worker"}),R=new URL(f.url),P=await _(n(R,"prefix"),{bucket:n(R,"bucket"),cursor:n(R,"cursor"),...t(f)});return Response.json(P,{headers:{"content-type":"application/json"},status:200})},O=f=>{if(f.method!=="GET")throw new a("Storage-buckets endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});return r(f),Response.json({buckets:u.storageBuckets??[]},{headers:{"content-type":"application/json"},status:200})},A=async f=>{const _=i(f,u.storageDelete,{code:"STORAGE_DELETE_NOT_CONFIGURED",message:"storage delete requires a `storageDelete` function on the worker"}),R=new URL(f.url),P=l(R);return await _(P,{bucket:n(R,"bucket")}),Response.json({deleted:!0,key:P},{headers:{"content-type":"application/json"},status:200})},w=async f=>{const _=i(f,u.storageUpload,{code:"STORAGE_UPLOAD_NOT_CONFIGURED",message:"storage upload requires a `storageUpload` function on the worker"}),R=new URL(f.url),P=l(R),E=await s(f),q=f.headers.get("content-type"),B=q===null||q===""?void 0:q,K=await _(P,E,{bucket:n(R,"bucket"),contentType:B});return Response.json(K,{headers:{"content-type":"application/json"},status:200})},g=async f=>{switch(f.method){case"DELETE":return A(f);case"GET":return y(f);case"POST":case"PUT":return w(f);default:throw new a("Storage endpoint requires GET, PUT, POST, or DELETE",{code:"METHOD_NOT_ALLOWED",status:405})}},p=async f=>{if(f.method!=="GET")throw new a("Storage URL endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});const _=i(f,u.storageSignedUrl,{code:"STORAGE_URL_NOT_CONFIGURED",message:"storage URL endpoint requires a `storageSignedUrl` function on the worker"}),R=new URL(f.url),P=l(R),E=Number(n(R,"expiresIn")??""),q=Number.isFinite(E)&&E>0?Math.min(E,Vn):void 0,B=await _(P,{bucket:n(R,"bucket"),expiresInSeconds:q});return Response.json({key:P,url:B},{headers:{"content-type":"application/json"},status:200})};return{[Jn]:O,[Wn]:g,[Hn]:p}},Xn=(e,...r)=>{let t=e.cf;for(const n of r){if(typeof t!="object"||t===null)return;t=t[n]}return typeof t=="string"?t:void 0},Zn={mtls:e=>Xn(e,"tlsClientAuth","certVerified")==="SUCCESS"},eo=e=>e===void 0||e===!1?()=>!1:e===!0?()=>!0:typeof e=="function"?e:Object.entries(Zn).find(([r])=>r===e)?.[1]??(()=>!1),to=e=>{if(e!==void 0)return()=>{};let r=!1;return()=>{r||(r=!0,console.warn('[lunora] Ignored an inbound `traceparent`, so this request starts a new trace instead of joining the caller\'s. That is the safe default: the header is caller-supplied, and trusting it lets any client choose which trace its spans and logs join. If this worker sits behind a gateway, service mesh, or Cloudflare Access that sets `traceparent` itself, set `trustInboundTraceContext: true` on createWorker() (or `"mtls"` to trust only edge-verified client certificates). Set it to `false` to keep this behaviour and silence this message.'))}},ro="/_lunora/admin/vector/indexes",no="/_lunora/admin/vector/query",oo=e=>{const{readJsonBody:r,requireAdminOption:t}=e,n=async i=>{if(i.method!=="GET")throw new a("Vector-indexes endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});const u=t(i,e.vectorIntrospector,{code:"VECTORS_NOT_CONFIGURED",message:"vector endpoints require a `vectorIntrospector` on the worker"});return Response.json({indexes:await u.listIndexes()},{headers:{"content-type":"application/json"},status:200})},s=async i=>{if(i.method!=="POST")throw new a("Vector-query endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});const u=t(i,e.vectorIntrospector,{code:"VECTORS_NOT_CONFIGURED",message:"vector endpoints require a `vectorIntrospector` on the worker"});if(u.queryIndex===void 0)throw new a("vector index querying is not enabled on this worker",{code:"VECTOR_QUERY_UNSUPPORTED",status:400});const l=await r(i);if(typeof l.name!="string"||l.name==="")throw new a("Vector-query request requires a `name` string",{code:"BAD_REQUEST",status:400});if(typeof l.text!="string"||l.text==="")throw new a("Vector-query request requires a `text` string",{code:"BAD_REQUEST",status:400});if(l.topK!==void 0&&(typeof l.topK!="number"||!Number.isInteger(l.topK)||l.topK<1))throw new a("Vector-query `topK` must be a positive integer",{code:"BAD_REQUEST",status:400});const y=await u.queryIndex({name:l.name,text:l.text,topK:l.topK});return Response.json(y,{headers:{"content-type":"application/json"},status:200})};return{[ro]:n,[no]:s}},ao="/_lunora/admin/workflows/instances",so="/_lunora/admin/workflows/instance",io="/_lunora/admin/workflows/status",uo={complete:!0,errored:!0,paused:!0,queued:!0,running:!0,terminated:!0,unknown:!0,waiting:!0,waitingForPause:!0},co=e=>e!==null&&Object.hasOwn(uo,e)?e:void 0,nt=(e,r)=>{const t=e.searchParams.get(r);if(t===null)return;const n=Number(t);return Number.isInteger(n)&&n>0?n:void 0},$e=(e,r)=>{const t=e.searchParams.get(r);if(t===null||t==="")throw new a(`Workflows admin endpoint requires a \`${r}\` query parameter`,{code:"BAD_REQUEST",status:400});return t},ot=()=>{throw new a("Workflow inspection is unconfigured. Set CLOUDFLARE_ACCOUNT_ID + CLOUDFLARE_API_TOKEN in your .dev.vars to enable it.",{code:"WORKFLOWS_NOT_CONFIGURED",status:501})},lo=e=>{const{assertAdmin:r,resolveWorkflowsClient:t}=e,n=async(u,l,y)=>{if(u.method!=="GET")throw new a("Workflows instances endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});r(u);const O=t(l);if(!O)return Response.json({configured:!1,instances:[],page:1,perPage:0,totalCount:0});const A=$e(y,"name"),w=co(y.searchParams.get("status"));return Response.json(await O.listInstances({page:nt(y,"page"),perPage:nt(y,"perPage"),status:w,workflowName:A}))},s=async(u,l,y)=>{if(u.method!=="GET")throw new a("Workflows instance endpoint requires GET",{code:"METHOD_NOT_ALLOWED",status:405});r(u);const O=t(l);return O?Response.json(await O.getInstance({instanceId:$e(y,"id"),workflowName:$e(y,"name")})):ot()},i=async(u,l)=>{if(u.method!=="POST")throw new a("Workflows status endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});r(u);const y=t(l);if(!y)return ot();const O=await u.json().catch(()=>{});if(typeof O?.name!="string"||O.name===""||typeof O.id!="string"||O.id==="")throw new a("Workflows status action requires string `name` and `id`",{code:"BAD_REQUEST",status:400});const{action:A}=O;if(A!=="pause"&&A!=="resume"&&A!=="terminate")throw new a("Workflows status action must be one of: pause, resume, terminate",{code:"BAD_REQUEST",status:400});return Response.json(await y.setInstanceStatus({action:A,instanceId:O.id,workflowName:O.name}))};return{[so]:s,[ao]:n,[io]:i}},ho=new TextEncoder,at="/_lunora/rpc",po="/_lunora/rpc-batch",fo="/_lunora/ws",Ee=(e,r,t)=>({resourceAttributes:xn(e,r),...t===void 0?{}:{waitUntil:t}}),st=e=>({spanId:e.spanId,traceFlags:e.traceFlags,traceId:e.traceId,...e.parentSpanId===void 0?{}:{parentSpanId:e.parentSpanId}}),Le=e=>{const{method:r}=e,t=e.headers.get("user-agent")??void 0;let n;try{n=new URL(e.url)}catch{return{method:r,userAgent:t}}const s=n.port===""?void 0:Number(n.port);return{host:n.hostname,method:r,path:n.pathname,port:Number.isNaN(s)?void 0:s,scheme:n.protocol.replace(":",""),userAgent:t}},it="/_lunora/voice/",mo="/_lunora/scheduler/dispatch",wo="/_lunora/admin/cron-jobs/run",yo="/_lunora/admin/ws-token",go="/_lunora/admin/",bo="/_lunora/migrate",Oo="/_lunora/status",Eo=e=>e.startsWith(go)||e===bo,To=new Set(["1","enabled","on","true","yes"]),_o=e=>{const r=e.headers.get("x-lunora-userid"),t=e.headers.get("x-lunora-identity");if(!(r===null&&t===null))return{...t===null?{}:{identity:t},...r===null?{}:{userId:r}}},Ro="/api/auth",So="__lunora_admin__:recordAuthEvent",Ao="__lunora_admin__:listPushSubscriptions",Do=["/sign-in","/sign-up","/callback"],vo=(e,r)=>{const t=r.endsWith("/")?r.slice(0,-1):r;if(!e.startsWith(`${t}/`))return!1;const n=e.slice(t.length);return Do.some(s=>n===s||n.startsWith(`${s}/`))},Be=(e,r,t,n)=>{const s=Vt(t),i=s?t.code:"INTERNAL_SERVER_ERROR",u=s?t.status:500,l=t instanceof Error?t.message:String(t);return{durationMs:r,error:{code:i,message:l,status:u},functionPath:e,ok:!1,...n.fanOut?{fanOut:{failed:0,shards:0,table:n.fanOut.table}}:{},...n.shardKey?{shardKey:n.shardKey}:{}}},ko=e=>{const{exp:r,expiresAtMs:t}=e;if(typeof t=="number"&&Number.isFinite(t))return t;if(typeof r=="number"&&Number.isFinite(r))return r*1e3},de=async(e,r,t)=>{const n={"content-type":"application/json"},s=e.headers.get("authorization"),i=e.headers.get("cookie"),u=e.headers.get("x-d1-bookmark"),l=e.headers.get("x-lunora-mutation-id"),y=e.headers.get("x-lunora-client-id"),O=e.headers.get("x-lunora-client-seq");s&&(n.authorization=s),i&&(n.cookie=i),u&&(n["x-d1-bookmark"]=u),l&&(n["x-lunora-mutation-id"]=l),y&&(n["x-lunora-client-id"]=y),O&&(n["x-lunora-client-seq"]=O);const A=e.headers.get("cf-connecting-ip");if(A&&(n["x-lunora-client-ip"]=A),!t)return{claims:null,headers:n,identity:null,userId:null};const w=await t(e,r);if(!w||typeof w.userId!="string"||w.userId.length===0)return{claims:null,headers:n,identity:null,userId:null};n["x-lunora-userid"]=w.userId;const g=ko(w);g!==void 0&&(n["x-lunora-identity-exp"]=String(g));const{userId:p,...f}=w,_=Object.keys(f).length>0?f:null;return _&&(n["x-lunora-identity"]=JSON.stringify(_)),{claims:_,headers:n,identity:w,userId:p}},Io=new Set(["concat","first","groupBy","max","min","rank","sum","topK"]),Po=e=>{if(e===void 0)return;if(!e||typeof e!="object")throw new a("RPC `fanOut` must be an object",{code:"BAD_REQUEST",status:400});const r=e;if(typeof r.table!="string"||r.table.length===0)throw new a("RPC `fanOut.table` must be a non-empty string",{code:"BAD_REQUEST",status:400});if(!r.merge||typeof r.merge!="object")throw new a("RPC `fanOut.merge` must be an object",{code:"BAD_REQUEST",status:400});const t=r.merge;if(typeof t.kind!="string"||!Io.has(t.kind))throw new a("RPC `fanOut.merge.kind` is not a recognized merge strategy",{code:"BAD_REQUEST",status:400});if(t.kind==="topK"){if(typeof t.k!="number"||!Number.isInteger(t.k)||t.k<0)throw new a("RPC `fanOut.merge.k` must be a non-negative integer",{code:"BAD_REQUEST",status:400});if(typeof t.by!="string"||t.by.length===0)throw new a("RPC `fanOut.merge.by` must be a non-empty string",{code:"BAD_REQUEST",status:400})}return r},No=(e,r)=>{e?.LUNORA_DEBUG_RPC&&console.warn(`[lunora:rpc] ${r.fanOut?"fan-out":`shard=${r.shardKey??"(root)"}`} ${r.functionPath}`)},dt=(e,r)=>{const t=r.functions?.[e.functionPath]?.x402;if(t){if(e.fanOut)throw new a("a paid (`.x402`) function cannot be fanned out",{code:"BAD_REQUEST",status:400});if(!r.x402Charge)throw new a(`function "${e.functionPath}" is marked paid (.x402) but no x402Charge gate is configured on the worker`,{code:"MISCONFIGURED",status:500});return t}},Uo=async e=>{const r=await ae(e);let t;try{t=JSON.parse(r)}catch{throw new a("RPC body must be valid JSON",{code:"BAD_REQUEST",status:400})}if(!t||typeof t!="object"||typeof t.functionPath!="string")throw new a("RPC envelope is missing `functionPath`",{code:"BAD_REQUEST",status:400});const n=t;if(n.args!==void 0&&(typeof n.args!="object"||n.args===null||Array.isArray(n.args)))throw new a("RPC `args` must be an object",{code:"BAD_REQUEST",status:400});if(n.shardKey!==void 0&&typeof n.shardKey!="string")throw new a("RPC `shardKey` must be a string",{code:"BAD_REQUEST",status:400});const s=t,i=Po(s.fanOut),u=s.args??{};if(i&&s.functionPath.startsWith("__lunora_relation__:")){const l=u.table;if(typeof l=="string"&&l!==i.table)throw new a("RPC `args.table` must match the authorized `fanOut.table` for a relation fan-out",{code:"BAD_REQUEST",status:400});u.table=i.table}return{args:u,fanOut:i,functionPath:s.functionPath,shardKey:s.shardKey}},oe=async(e,r,t)=>_e(e,r).fetch(t),Te=new Map,qo=5e3,$o=4096,Lo=async(e,r)=>{const t=Date.now(),n=Te.get(r);if(n!==void 0&&n.expiresMs>t)return n.relayCount;n!==void 0&&Te.delete(r);let s=0;try{const i=await _e(e,r).fetch(new Request("https://shard.internal/_lunora/route"));if(i.ok){const u=(await i.json()).relayCount;typeof u=="number"&&u>0&&(s=Math.floor(u))}}catch{s=0}return ct(Te,$o),Te.set(r,{expiresMs:t+qo,relayCount:s}),s},Bo=(e,r)=>{if(!(e===null||typeof e!="object")){for(const[t,n]of Object.entries(e))if(n===r)return t}},Ce=(e,r)=>{const t=Math.max(e.length,r.length);let n=e.length^r.length;for(let s=0;s<t;s+=1){const i=s<e.length?e.codePointAt(s)??0:0,u=s<r.length?r.codePointAt(s)??0:0;n|=i^u}return n===0},xo=async(e,r,t)=>{if(e.length===0||t.length===0)return!1;const n=new TextEncoder,s=await crypto.subtle.importKey("raw",n.encode(e),{hash:"SHA-256",name:"HMAC"},!1,["sign"]),i=await crypto.subtle.sign("HMAC",s,n.encode(r)),u=new Uint8Array(i);let l="";for(const O of u)l+=String.fromCodePoint(O);const y=btoa(l).replaceAll("+","-").replaceAll("/","_").replaceAll("=","");return Ce(y,t)},ut=(e,r)=>{if(!r||r.length===0)return!1;const t=e.headers.get("authorization");if(!t)return!1;const[n,...s]=t.split(" ");return n?.toLowerCase()!=="bearer"?!1:Ce(r,s.join(" ").trim())},Co=async(e,r,t)=>{if(!r||r.length===0)return!1;const n=new URL(e.url).searchParams.get("token");return n===null?!1:await Ar(r,n)?!0:t?!1:Ce(r,n)},jo=(e,r)=>{if(r===null||typeof r!="object"&&typeof r!="function")return;const t=r;if(typeof t.prepare=="function"&&typeof t.batch=="function"&&typeof t.dump=="function")return or(`d1:${e}`,r);if(typeof t.list=="function"&&typeof t.head=="function"&&typeof t.createMultipartUpload=="function")return ke(`r2:${e}`,!0);if(typeof t.send=="function"&&typeof t.sendBatch=="function"&&typeof t.get!="function")return ke(`queue:${e}`,!0);if(typeof t.connectionString=="string")return ke(`hyperdrive:${e}`,!0)},wt=e=>{const r=eo(e.trustInboundTraceContext),t=to(e.trustInboundTraceContext),n=e.defaultShardKey??"__root__",s=ar(e.resolveIdentity,e.identity),i=ze(e.shardDO,e.jurisdiction),u=e.schedulerDO===void 0?void 0:ze(e.schedulerDO,e.jurisdiction);let l;const y=()=>e.adminToken??l;let O;const A=()=>e.requireEphemeralWsToken??O??!1,w=o=>{const d=o??{};if(O===void 0&&e.requireEphemeralWsToken===void 0){const c=d.LUNORA_REQUIRE_EPHEMERAL_WS_TOKEN;typeof c=="string"&&c.length>0&&(O=To.has(c.trim().toLowerCase()))}if(l!==void 0||e.adminToken!==void 0)return;const h=d.LUNORA_ADMIN_TOKEN;typeof h=="string"&&h.length>0&&(l=h)},g=new WeakSet,p=o=>ut(o,y())||g.has(o),f=async(o,d)=>{const h=await de(o,d,e.resolveIdentity);if(g.has(o)&&h.headers.authorization===void 0){const c=y();c!==void 0&&(h.headers.authorization=`Bearer ${c}`)}return h};let _=!1;const R=o=>{if(!e.allowUnauthenticatedShardAccess){const d=o==="fan-out"?"authorizeFanOut":"authorizeShard";throw new a(`${o} access is default-denied: configure \`${d}\` on the worker, or set \`allowUnauthenticatedShardAccess: true\` to explicitly allow unauthenticated ${o} access (relying solely on per-row RLS).`,{code:o==="fan-out"?"FORBIDDEN_FANOUT":"FORBIDDEN_SHARD",status:403})}_||(_=!0,console.warn([`[lunora] SECURITY: serving ${o} access with \`allowUnauthenticatedShardAccess: true\` and no \`authorizeShard\`/\`authorizeFanOut\` — `,"any caller (including unauthenticated ones) can target any shard / fan out across the table. ","This is safe only if every table is protected by per-row RLS. Configure `authorizeShard`/`authorizeFanOut` to gate it."].join("")))},P=vn({defaultShard:n,forwardToShard:oe,isAdmin:p,queryCoordinator:e.queryCoordinator,resolveForwardContext:f,shardDO:i}),E=async(o,d,h,c,m)=>{if(e.authorizeShard&&!await e.authorizeShard(null,h))throw new a("Forbidden shard",{code:"FORBIDDEN_SHARD",status:403});const b={"content-type":"application/json","x-lunora-system":"1"};m?.userId!==void 0&&m.userId.length>0&&(b["x-lunora-userid"]=m.userId),m?.identity!==void 0&&m.identity.length>0&&(b["x-lunora-identity"]=m.identity),c!==void 0&&c.length>0&&(b["x-lunora-mutation-id"]=c);const S=new Request("https://shard.internal/rpc",{body:JSON.stringify({args:d,functionPath:o}),headers:b,method:"POST"});return oe(i,h,S)},q=async(o,d,h,c)=>{const m=h?.[o];if(!m||typeof m.create!="function")throw new a(`${c} targets workflow binding "${o}", which is not bound on env`,{code:"CRON_JOB_FAILED",status:500});await m.create({params:d})},B=async(o,d,h)=>q(o,d.args??{},h,`cron job "${d.name}"`),K=async(o,d)=>{if(o.workflow){await B(o.workflow,o,d);return}if(o.functionPath===void 0)throw new a(`cron job "${o.name}" has neither a function target nor a workflow target`,{code:"CRON_JOB_FAILED",status:500});const h=await E(o.functionPath,o.args??{},o.shardKey??n);if(!h.ok)throw new a(`cron job "${o.name}" (${o.functionPath}) failed with shard status ${String(h.status)}`,{code:"CRON_JOB_FAILED",status:500})},N=async(o,d,h,c)=>{const m=e.cronJobs?.[o];if(m)for(const b of m)try{await K(b,d)}catch(S){h.push(c(S))}},M=async(o,d)=>{if(!p(o))throw new a("admin endpoint requires a valid admin bearer",{code:"ADMIN_FORBIDDEN",status:403});if(o.method!=="POST")throw new a("cron-jobs run endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});if(!e.cronJobs)throw new a("cron-jobs run endpoint requires a `cronJobs` map on the worker",{code:"CRON_JOBS_NOT_CONFIGURED",status:400});const h=await Z(o),c=typeof h.name=="string"?h.name:"";if(c==="")throw new a("cron-jobs run endpoint requires a job `name`",{code:"BAD_REQUEST",status:400});const m=Object.values(e.cronJobs).flat().find(b=>b.name===c);if(!m)throw new a(`no cron job named "${c}" is registered`,{code:"CRON_JOB_NOT_FOUND",status:404});return await K(m,d),Response.json({name:c,ran:!0},{status:200})},Q=async o=>{const d=typeof o.pool=="string"&&o.pool.length>0?o.pool:void 0;if(!d||!u||typeof o.id!="string")return;const h=typeof o.instanceName=="string"&&o.instanceName.length>0?o.instanceName:"default";try{await u.get(u.idFromName(h)).fetch(new Request("https://scheduler.internal/complete",{body:JSON.stringify({id:o.id,pool:d}),headers:{"content-type":"application/json"},method:"POST"}))}catch{}},Y=async(o,d)=>{if(o.method!=="POST")throw new a("Scheduler dispatch endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});const h=await ae(o),c=d??{},m=typeof c.LUNORA_SCHEDULER_SECRET=="string"?c.LUNORA_SCHEDULER_SECRET:void 0,b=e.adminToken??(typeof c.LUNORA_ADMIN_TOKEN=="string"?c.LUNORA_ADMIN_TOKEN:void 0),S=o.headers.get("x-lunora-scheduler-signature");let T=!1;if(S&&m?T=await xo(m,h,S):b&&(T=ut(o,b)),!T)throw new a("Scheduler dispatch requires a valid signature or admin bearer",{code:"FORBIDDEN",status:403});let D;try{D=JSON.parse(h)}catch{throw new a("Scheduler dispatch body must be valid JSON",{code:"BAD_REQUEST",status:400})}const k=D??{},U=k.args??{};if(typeof k.workflow=="string"&&k.workflow.length>0)return await q(k.workflow,U,d,"scheduled workflow"),Response.json({ok:!0},{status:200});if(typeof k.functionPath!="string"||k.functionPath.length===0)throw new a("Scheduler dispatch is missing `functionPath`",{code:"BAD_REQUEST",status:400});const L=typeof k.shardKey=="string"&&k.shardKey.length>0?k.shardKey:n,$=typeof k.id=="string"&&k.id.length>0?k.id:void 0,C=_o(o),W=await E(k.functionPath,U,L,$,C);return await Q(k),W},x=o=>{if(!p(o))throw new a("admin endpoint requires a valid admin bearer",{code:"ADMIN_FORBIDDEN",status:403})},G=(o,d,h)=>{if(x(o),d===void 0)throw new a(h.message,{code:h.code,status:400});return d},J=er({assertAdmin:x,getReader:()=>e.authAuditReader}),re=async(o,d)=>{x(o);const h=e.notifySubscriptionStore;if(h===void 0)return Response.json({subscriptions:[]},{headers:{"content-type":"application/json"},status:200});const c=d?.kind,m=d?.userId,b=typeof c=="string"&&c!==""?c:void 0,S=typeof m=="string"&&m!==""?m:void 0,T=(await h.list()).filter(D=>(b===void 0||D.kind===b)&&(S===void 0||D.userId===S)).map(({keys:D,token:k,...U})=>U);return Response.json({subscriptions:T},{headers:{"content-type":"application/json"},status:200})},se=async(o,d)=>{if(!d.fanOut){if(d.functionPath===Zt)return J(o,d.args??{});if(d.functionPath===Ao)return re(o,d.args)}},ne=Fr({applyGlobals:e.applyGlobals,exportCursorStore:e.exportCursorStore,exportSinks:e.exportSinks,knownTables:()=>pt(),queryCoordinator:e.queryCoordinator,requireAdminOption:G,resolveForwardContext:f,shardDO:i,streamExportRows:(o,d,h,c)=>Ze(e,o,d,h,c,i),streamingImport:(o,d)=>Yr(o,e,d,i),syncGlobals:e.syncGlobals}),le=(o,d)=>{const h=o.searchParams.get(d);return h===null||h===""?void 0:h},we=o=>{const d=new URL(o.url),h=d.searchParams.get("limit"),c=d.searchParams.get("offset"),m=h===null?void 0:Number.parseInt(h,10),b=c===null?void 0:Number.parseInt(c,10);return{limit:m!==void 0&&Number.isFinite(m)&&m>=0?m:void 0,offset:b!==void 0&&Number.isFinite(b)&&b>=0?b:void 0}},be=()=>{if(u===void 0)throw new a("scheduled endpoints require a `schedulerDO` namespace on the worker",{code:"SCHEDULER_NOT_CONFIGURED",status:400});return u},ee=zn({checkWsAdmin:async o=>p(o)||Co(o,y(),A()),requireSchedulerNamespace:be,resolveSchedulerStub:o=>(x(o),_e(be(),e.schedulerInstanceName??"default")),schedulerInstanceName:e.schedulerInstanceName??"default"}),yt=lo({assertAdmin:x,resolveWorkflowsClient:e.workflowsClient??(()=>{})}),gt=Yn({assertAdmin:x,parsePaging:we,queryParameter:le,readBodyBytes:Nr,requireAdminOption:G,storage:{storageBuckets:e.storageBuckets,storageDelete:e.storageDelete,storageList:e.storageList,storageSignedUrl:e.storageSignedUrl,storageUpload:e.storageUpload}}),bt=oo({readJsonBody:Z,requireAdminOption:G,vectorIntrospector:e.vectorIntrospector}),Ot=pn({kvIntrospector:e.kvIntrospector,readJsonBody:Z,requireAdminOption:G}),Et=sr({logArchive:e.logArchive,readJsonBody:Z,requireAdminOption:G}),Tt=cn({assertAdmin:x,options:{cronJobs:e.cronJobs,functions:e.functions,globalIntrospector:e.globalIntrospector,openApiSpec:e.openApiSpec,openRpcSpec:e.openRpcSpec},parsePaging:we,queryParameter:le,requireAdminOption:G}),_t=o=>{const d=[],h=i??o?.SHARD;if(h!==void 0&&d.push(nr("durable-object",h,n)),e.health?.disableBindingProbes!==!0)for(const[c,m]of Object.entries(o??{})){const b=jo(c,m);b!==void 0&&d.push(b)}for(const c of e.health?.probes??[])d.push(c);return d},Rt=rr({appName:e.health?.appName,appVersion:e.health?.appVersion,auth:e.health?.auth??"public",isAdmin:p,resolveProbes:_t}),St=async(o,d,h)=>{const{claims:c,headers:m,userId:b}=await de(o,d,s),S=async(T,D={})=>{const k=T.__lunoraRef;if(typeof k!="string")throw new a("ctx.run*: expected a function reference from the generated `api`",{code:"BAD_REQUEST",status:400});const U=new Request("https://shard.internal/rpc",{body:JSON.stringify({args:D,functionPath:k}),headers:m,method:"POST"}),L=await oe(i,n,U),$=await L.json();if($.error)throw new a($.error.message??"shard RPC failed",{code:$.error.code??"INTERNAL",status:L.status});return $.result};return{auth:{getIdentity:()=>Promise.resolve(c),userId:b},cache:h.cache,fetch:globalThis.fetch.bind(globalThis),runAction:S,runMutation:S,runQuery:S}},At=async(o,d,h)=>{if(!e.httpRouter)return;const c=await St(o,d,h);try{return await e.httpRouter.fetch(o,{...d,__lunoraCtx:c},h)}catch(m){return console.error("[lunora] httpRouter (SSR) handler threw:",m),new Response("Internal Server Error",{status:500})}},Dt=async(o,d,h)=>{if(o.headers.get("Upgrade")!=="websocket")throw new a("WebSocket upgrade header missing",{code:"BAD_REQUEST",status:426});const c=He(o,ie);if(c)return c;const m=h.searchParams.get("shard")??n,{headers:b,identity:S}=await de(o,d,s);if(e.authorizeShard){if(!await e.authorizeShard(S,m))throw new a("Forbidden shard",{code:"FORBIDDEN_SHARD",status:403})}else m!==n&&R("shard");const T=new Headers(o.headers),D=[...T.keys()];for(const C of D)C.startsWith("x-lunora-")&&T.delete(C);const k=b["x-lunora-userid"],U=b["x-lunora-identity"],L=b["x-lunora-identity-exp"];k!==void 0&&T.set("x-lunora-userid",k),U!==void 0&&T.set("x-lunora-identity",U),L!==void 0&&T.set("x-lunora-identity-exp",L);const $=Bo(d,e.shardDO);if($!==void 0){T.set("x-lunora-shard-binding",$);const C=await Lo(i,m);if(C>0){const W=gr(m,Math.floor(Math.random()*C));return oe(i,W,new Request(o,{headers:T}))}}return oe(i,m,new Request(o,{headers:T}))},vt=async(o,d,h)=>{const{voiceAgents:c}=e;if(c===void 0)return new Response("Not found",{status:404});if(o.headers.get("Upgrade")!=="websocket")return new Response("Expected a WebSocket upgrade",{headers:{allow:"GET"},status:426});const m=He(o,ie);if(m)return m;let b;try{b=decodeURIComponent(h.pathname.slice(it.length))}catch{return new Response("Unknown voice agent",{status:404})}const S=Object.hasOwn(c,b)?c[b]:void 0;if(S===void 0)return new Response("Unknown voice agent",{status:404});const T=h.searchParams.get("threadKey");if(T===null||T.length===0)return new Response("Missing threadKey",{status:400});const{headers:D,identity:k}=await de(o,d,s);if(e.authorizeShard){if(!await e.authorizeShard(k,T))return new Response("Forbidden",{status:403})}else R("shard");const U=new Headers(o.headers);U.delete("x-lunora-userid"),U.delete("x-lunora-identity"),U.delete("x-lunora-identity-exp");const L=D["x-lunora-userid"],$=D["x-lunora-identity"],C=D["x-lunora-identity-exp"];return L!==void 0&&U.set("x-lunora-userid",L),$!==void 0&&U.set("x-lunora-identity",$),C!==void 0&&U.set("x-lunora-identity-exp",C),oe(S,T,new Request(o,{headers:U}))},kt=async(o,d,h)=>{if(e.authorizeFanOut){if(!await e.authorizeFanOut(h,o.table,d))throw new a("Forbidden fan-out",{code:"FORBIDDEN_FANOUT",status:403});return}if(d.startsWith("__lunora_relation__:"))throw new a("reverse cross-backend relation reads (`__lunora_relation__:*`) require `authorizeFanOut` to be configured on the worker",{code:"FORBIDDEN_FANOUT",status:403});if(e.authorizeShard)throw new a("Fan-out requires `authorizeFanOut` to be configured on the worker when `authorizeShard` is set",{code:"FORBIDDEN_FANOUT",status:403});R("fan-out")},Oe=async(o,d)=>{if(!(!o.fanOut&&o.functionPath.startsWith("__lunora_admin__:"))){if(o.fanOut){await kt(o.fanOut,o.functionPath,d);return}if(e.authorizeShard){const h=o.shardKey??n;if(!await e.authorizeShard(d,h))throw new a("Forbidden shard",{code:"FORBIDDEN_SHARD",status:403})}else o.shardKey!==void 0&&o.shardKey!==n&&R("shard")}},Re=async(o,d,h,c,m,b)=>{const S=Date.now(),{observability:T,sampling:D}=e,k=Le(o),{decision:U,ignoredUpstream:L,trace:$}=Ln(o,{...D===void 0?{}:{sampling:D},trustInbound:r(o)});L&&t();const C={...m,"x-lunora-sample-errors":U.keepErrors?"1":"0"};Bn($,C);const W=new Request("https://shard.internal/rpc",{body:JSON.stringify({args:h,functionPath:d}),headers:C,method:"POST"});try{const j=await oe(i,c,W);return me(T,{...k,...st($),durationMs:Date.now()-S,functionPath:d,ok:j.ok,shardKey:c,...j.ok?{}:{error:{code:"SHARD_ERROR",message:`shard returned ${String(j.status)}`,status:j.status}}},b,D),j}catch(j){throw me(T,{...k,...st($),...Be(d,Date.now()-S,j,{shardKey:c})},b,D),j}},It=o=>{if(o.fanOut&&o.shardKey)throw new a("RPC envelope cannot set both `shardKey` and `fanOut`",{code:"BAD_REQUEST",status:400});if(!o.fanOut&&o.functionPath.startsWith("__lunora_relation__:"))throw new a("`__lunora_relation__:*` is a fan-out-only reserved RPC and cannot be dispatched to a single shard",{code:"FORBIDDEN",status:403});if(o.fanOut&&!e.queryCoordinator)throw new a("RPC envelope set `fanOut` but no `queryCoordinator` is configured on the worker",{code:"BAD_REQUEST",status:400})},Pt=async(o,d,h)=>{if(o.method!=="POST")throw new a("RPC endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});const c=await Uo(o);No(d,c),It(c);const m=await se(o,c);if(m!==void 0)return m;const{headers:b,identity:S}=await de(o,d,s);await Oe(c,S);const T=dt(c,e);{const D=Date.now(),{observability:k}=e,U=Le(o),L=Ee(d,o,h&&(W=>h.waitUntil?.(W)));if(c.fanOut){const W=e.queryCoordinator;if(!W)throw new a("RPC envelope set `fanOut` but no `queryCoordinator` is configured on the worker",{code:"BAD_REQUEST",status:400});try{const j=await W.fanOut(i,{args:c.args??{},fanOut:c.fanOut,functionPath:c.functionPath,headers:b});return me(k,{durationMs:Date.now()-D,fanOut:{failed:j.failed,shards:j.ok+j.failed,table:c.fanOut.table},functionPath:c.functionPath,...U,ok:!0},L),Response.json(j,{headers:{"content-type":"application/json"},status:200})}catch(j){throw me(k,{...Be(c.functionPath,Date.now()-D,j,{fanOut:{table:c.fanOut.table}}),...U},L),j}}const $=c.shardKey??n,C=()=>Re(o,c.functionPath,c.args??{},$,b,L);return T&&e.x402Charge?e.x402Charge(o,{functionPath:c.functionPath,price:T.price},C):C()}},Nt=async(o,d,h)=>{if(o.method!=="POST")throw new a("RPC batch endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});const c=await ae(o);let m;try{m=JSON.parse(c)}catch{throw new a("RPC batch body must be valid JSON",{code:"BAD_REQUEST",status:400})}if(typeof m!="object"||m===null||Array.isArray(m))throw new a("RPC batch body must be an object",{code:"BAD_REQUEST",status:400});const{calls:b}=m;if(!Array.isArray(b))throw new a("RPC batch `calls` must be an array",{code:"BAD_REQUEST",status:400});const{headers:S,identity:T}=await de(o,d,s),D=Pr(b,n);for(const F of D.values())for(const z of F)if(e.functions?.[z.functionPath]?.x402)throw new a(`paid (\`.x402\`) function "${z.functionPath}" cannot be called in a batch; dispatch it individually over ${at}`,{code:"BAD_REQUEST",status:400});await Promise.all([...D.entries()].flatMap(([F,z])=>z.map(te=>Oe({functionPath:te.functionPath,shardKey:F},T))));const{observability:k}=e,U=Ee(d,o,h&&(F=>h.waitUntil?.(F))),L=Le(o),$=[],C=[],W=(F,z,te,ue)=>({body:{error:{code:te,message:ue}},id:F.id,status:z}),j=(F,z,te,ue,he)=>{for(const H of F)me(k,he(H),U),$.push(W(H,z,te,ue))},zt=(F,z,te,ue,he)=>{for(const H of F){const pe=ue.get(H.id)??he,ye=pe<400;me(k,{durationMs:te,functionPath:H.functionPath,...L,ok:ye,shardKey:z,...ye?{}:{error:{code:"SHARD_ERROR",message:`batched call returned ${String(pe)}`,status:pe}}},U)}};await Promise.all([...D.entries()].map(async([F,z])=>{const te=new Headers(S);te.set("content-type","application/json");const ue=new Request("https://shard.internal/rpc-batch",{body:JSON.stringify({calls:z}),headers:te,method:"POST"}),he=Date.now();let H;try{H=await oe(i,F,ue)}catch(V){const ve=Date.now()-he,{body:Me}=Yt(V,{fallbackCode:"SHARD_UNAVAILABLE",redactedMessage:"shard unavailable"});j(z,502,Me.code,Me.message,Jt=>({...Be(Jt.functionPath,ve,V,{shardKey:F}),...L}));return}const pe=Date.now()-he,ye=H.headers.get("x-d1-bookmark");ye&&C.push(ye);let Ae;try{Ae=await H.json()}catch{const V=`shard batch returned a non-JSON response (${String(H.status)})`;j(z,H.status,"SHARD_ERROR",V,ve=>({durationMs:pe,error:{code:"SHARD_ERROR",message:V,status:H.status},functionPath:ve.functionPath,...L,ok:!1,shardKey:F}));return}const De=Array.isArray(Ae.results)?Ae.results:[],Wt=new Map(De.map(V=>[V.id,V.status??H.status])),Ht=new Set(De.map(V=>V.id));zt(z,F,pe,Wt,H.status),$.push(...De);for(const V of z)Ht.has(V.id)||$.push(W(V,H.status,"SHARD_ERROR",`shard batch omitted result for call ${String(V.id)}`))}));const Ge={"content-type":"application/json"},[Ke]=C;return C.length===1&&Ke!==void 0&&(Ge["x-d1-bookmark"]=Ke),Response.json({results:$},{headers:Ge,status:200})},Ut=async(o,d,h,c={},m={})=>{try{const b=h.__lunoraRef;if(typeof b!="string")throw new a("serverQuery: expected a function reference from the generated `api`",{code:"BAD_REQUEST",status:400});const{headers:S,identity:T}=await de(o,d,s);await Oe({functionPath:b,shardKey:m.shardKey},T);const D=m.shardKey??n,k=Ee(d,o,m.waitUntil);return await Re(o,b,c,D,S,k)}catch(b){return Qe(b)}},qt=1e3,$t=async(o,d)=>{const h=e.backupRetain;if(h===void 0||h<=0)return;const c=[];let m;for(let S=0;S<qt;S+=1){const T=await o.list({cursor:m,prefix:d});for(const D of T.objects)D.key.endsWith(".manifest.json")&&c.push(D.key);if(!T.truncated||T.cursor===void 0)break;m=T.cursor}const b=c.toSorted((S,T)=>T.localeCompare(S)).slice(h);await Promise.all(b.flatMap(S=>{const T=S.slice(0,-14);return[o.delete(S),o.delete(T)]}))},Lt=async o=>{const d=e.backupStore,h=e.queryCoordinator;if(!d)throw new a("scheduled backup requires a `backupStore` on the worker",{code:"BACKUP_NOT_CONFIGURED",status:500});if(!h)throw new a("scheduled backup requires a `queryCoordinator` on the worker",{code:"BACKUP_NOT_CONFIGURED",status:500});const c=y();if(!c||c.length===0)throw new a("scheduled backup requires an `adminToken` (or `env.LUNORA_ADMIN_TOKEN`) to authenticate the per-shard export gate",{code:"BACKUP_NOT_CONFIGURED",status:500});const m={authorization:`Bearer ${c}`,"content-type":"application/json"},b=e.backupTables;let S=0,T=0;const D=[];await Ze(e,h,m,b,W=>{const j=`${JSON.stringify(W)}
5
- `;S+=1,T+=ho.encode(j).byteLength,D.push(j)},i);const k=e.backupPrefix??"backups/",U=new Date(o.scheduledTime).toISOString(),L=`${k}lunora-backup-${U.replaceAll(/[.:]/gu,"-")}.ndjson`,$=`${L}.manifest.json`;await d.put(L,new Blob(D,{type:"application/x-ndjson"}),{httpMetadata:{contentType:"application/x-ndjson"}});const C={bytes:T,createdAt:U,cron:o.cron,file:L,id:U,rows:S,scheduledTime:o.scheduledTime,...b?{tables:b.join(",")}:{}};await d.put($,`${JSON.stringify(C,void 0,2)}
6
- `,{httpMetadata:{contentType:"application/json"}}),await $t(d,k)},Bt=async(o,d,h)=>{w(d);const c=[],m=T=>T instanceof Error?T:new Error(String(T)),b=e.crons?.[o.cron];if(b)try{await b(o,d,h)}catch(T){c.push(m(T))}if(await N(o.cron,d,c,m),e.backupStore&&e.backupCron!==void 0&&e.backupCron===o.cron)try{await Lt(o)}catch(T){c.push(m(T))}const[S]=c;if(c.length===1&&S)throw S;if(c.length>1)throw new AggregateError(c,`scheduled("${o.cron}") had ${String(c.length)} failure(s)`)},xt=async(o,d)=>{try{const h=o??{},c=e.adminToken??(typeof h.LUNORA_ADMIN_TOKEN=="string"?h.LUNORA_ADMIN_TOKEN:void 0);if(!c||c.length===0)return;const m=new Request("https://shard.internal/rpc",{body:JSON.stringify({args:{outcome:d},functionPath:So}),headers:{authorization:`Bearer ${c}`,"content-type":"application/json"},method:"POST"});await oe(i,n,m)}catch{}},Ct=async(o,d,h,c)=>{if(!e.authHandler)return;const m=await e.authHandler(o);if(!m)return;const b=e.authBasePath??Ro;return vo(h.pathname,b)&&c.waitUntil?.(xt(d,m.status>=400?"fail":"ok")),m},jt=async({args:o,env:d,functionPath:h,request:c,shardKey:m,waitUntil:b})=>{const S={functionPath:h,...m===void 0?{}:{shardKey:m}},{headers:T,identity:D}=await de(c,d,s);await Oe(S,D);const k=m??n,U=Ee(d,c,b),L=()=>Re(c,h,o,k,T,U),$=dt(S,e);return $&&e.x402Charge?e.x402Charge(c,{functionPath:h,price:$.price},L):L()},Gt=fr({functions:e.functions??{},invoke:jt,readJsonBody:Z,...e.restRateLimit?{rateLimit:e.restRateLimit}:{}}),Se=e.routes!==void 0&&Object.keys(e.routes).length>0?e.routes:void 0,Kt={[Oo]:o=>o.method!=="GET"&&o.method!=="HEAD"?new Response(void 0,{headers:{allow:"GET, HEAD"},status:405}):Response.json({ok:!0},{headers:{"cache-control":"no-store"}}),[fo]:(o,d,h)=>Dt(o,d,h),[at]:(o,d,h,c)=>Pt(o,d,c),[po]:(o,d,h,c)=>Nt(o,d,c),[mo]:(o,d)=>Y(o,d),[wo]:(o,d)=>M(o,d),[yo]:async o=>{if(o.method!=="POST")throw new a("ws-token endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});x(o);const d=y();if(d===void 0)throw new a("ws-token minting requires a configured admin token",{code:"ADMIN_TOKEN_NOT_CONFIGURED",status:400});const h=await Sr(d);return Response.json(h,{headers:{"cache-control":"no-store"}})},...P,...ne,...ee,...yt,...gt,...bt,...Ot,...Et,...Tt,...Rt,...Gt,...kr({assertAdmin:x,getAuthAdmin:()=>e.authAdmin,parsePaging:we,queryParameter:le,readJsonBody:Z})};let ie=We(e.security),je=!1;const Mt=o=>{je||(je=!0,ie=We(e.security,o??{}))},Qt=async(o,d)=>{if(!(e.adminGate===void 0||!Eo(d)))try{await e.adminGate(o)&&g.add(o)}catch{}},Ft=async(o,d,h)=>{const c=new URL(o.url);if(o.method==="POST"||o.method==="PUT"){const T=Number(o.headers.get("content-length")??""),D=c.pathname===ft?mt:ge;if(Number.isFinite(T)&&T>D)throw new a("Body too large",{code:"PAYLOAD_TOO_LARGE",status:413})}const m=await Ct(o,d,c,h);if(m)return m;if(Se){const T=`${o.method} ${c.pathname}`,D=Se[T]??Se[c.pathname];if(D)return D(o,d,h)}const b=Kt[c.pathname];return b?(await Qt(o,c.pathname),b(o,d,c,h)):e.voiceAgents!==void 0&&c.pathname.startsWith(it)?vt(o,d,c):await At(o,d,h)||new Response("Not found",{status:404})};return{async fetch(o,d,h){e.passThroughOnException&&h.passThroughOnException?.(),Mt(d),w(d);const c=mr(o,ie);if(c)return c;const m=wr(o,ie);if(m)return Ie(m,o,ie);try{const b=await Ft(o,d,h);return Ie(b,o,ie)}catch(b){return Ie(Qe(b),o,ie)}},async queue(o,d,h){await e.queue?.(o,d,h)},async scheduled(o,d,h){await Bt(o,d,h)},serverQuery:Ut}},Go=e=>wt(e),Ko=e=>typeof e=="function"?{fetch:e}:e,Mo=e=>!!(e.crons??e.cronJobs??e.backupCron),aa=(e,r)=>{const t=Ko(e),n=typeof e=="object"&&typeof e.scheduled=="function"?e.scheduled:void 0,s=u=>{const l=Go({...u,httpRouter:t});return n!==void 0&&!Mo(u)?{...l,scheduled:async(y,O,A)=>{await n(y,O,A)}}:l};if(typeof r!="function")return s(r);const i=r;return{fetch:(u,l,y)=>s(i(l)).fetch(u,l,y),queue:(u,l,y)=>s(i(l)).queue?.(u,l,y)??Promise.resolve(),scheduled:(u,l,y)=>s(i(l)).scheduled(u,l,y),serverQuery:(u,l,y,O,A)=>s(i(l)).serverQuery(u,l,y,O,A)}},Qo=(e,r)=>{if(typeof e=="function")return e(r);const t=e.shardDO??r?.SHARD;if(!t)throw new a("@lunora/runtime: no shard Durable Object namespace found. Bind `SHARD` in wrangler.jsonc, or pass `createLunoraHandler({ shardDO: env.MY_SHARD })`.");return{...e,shardDO:t}},sa=(e={})=>(r,t,n)=>wt(Qo(e,t)).fetch(r,t,n??Xt),ia=e=>e;export{Zt as GET_AUTH_AUDIT_LOG_OP,Xt as NOOP_EXECUTION_CONTEXT,ca as composeIdentityResolvers,Go as composeWorker,sa as createLunoraHandler,wt as createWorker,ia as defineRpcEnvelope,Lo as probeRelayCount,Qo as resolveLunoraOptions,la as routeIdentityResolvers,aa as withFrameworkWorker};
@@ -1 +0,0 @@
1
- import{e as a,a as m}from"./observability-D3GeW_py.mjs";export{a as emitLogEvent,m as emitRpcEvent};
@@ -1 +0,0 @@
1
- const a=r=>{const e=Number.parseInt(r.slice(0,8),16);return Number.isFinite(e)?e/4294967296:0},s=(r,e=1)=>e>=1?!0:e<=0?!1:a(r)<e,c=(r,e)=>({isTraced:s(e,r?.headRate??1),keepErrors:r?.alwaysSampleErrors??!0}),n=(r,e)=>r.isTraced||r.keepErrors&&e,i=(r,e,o,t)=>{if(r?.onRpc&&!(t!==void 0&&e.traceId!==void 0&&!n(c(t,e.traceId),!e.ok)))try{r.onRpc(e,o)}catch{}},p=(r,e,o)=>{if(r?.onLog)try{r.onLog(e,o)}catch{}};export{i as a,p as e,c as o};
@@ -1 +0,0 @@
1
- const p={debug:5,error:17,fatal:21,info:9,log:9,trace:1,warn:13},v=e=>`${String(Math.round(e))}000000`,O=e=>{const t=new Uint8Array(e);crypto.getRandomValues(t);let r="";for(const o of t)r+=o.toString(16).padStart(2,"0");return r},a=/^[0-9a-f]+$/,b=(e,t,r=!0)=>`00-${e}-${t}-${r?"01":"00"}`,E=e=>{if(e==null)return;const t=e.trim().toLowerCase().split("-"),[r,o,n,s]=t;if(!(t.length<4||r===void 0||r.length!==2||!a.test(r)||r==="ff"||r==="00"&&t.length!==4||o===void 0||n===void 0||s===void 0||s.length!==2||!a.test(s)||o.length!==32||n.length!==16||!a.test(o)||!a.test(n)||o==="00000000000000000000000000000000"||n==="0000000000000000"))return{parentSpanId:n,sampled:(Number.parseInt(s,16)&1)===1,traceId:o}},f=(e,t)=>typeof t=="boolean"?{key:e,value:{boolValue:t}}:typeof t=="number"?Number.isFinite(t)?Number.isSafeInteger(t)?{key:e,value:{intValue:String(t)}}:{key:e,value:{doubleValue:t}}:{key:e,value:{stringValue:String(t)}}:{key:e,value:{stringValue:t}},m=(e,t,r)=>{const o={},n=new Map,s=(i,c)=>{const l=i.toLowerCase(),d=n.get(l);d===void 0?(n.set(l,i),o[i]=c):o[d]=c};for(const[i,c]of Object.entries(e))s(i,c);for(const[i,c]of Object.entries(t??{}))s(i,c);return r!==void 0&&r.length>0&&s("authorization",`Bearer ${r}`),o},u=(e,t)=>{const r={"service.name":e};for(const[o,n]of Object.entries(t??{}))r[o]=n;return Object.entries(r).map(([o,n])=>f(o,n))},C=(e,t,r,o)=>({resourceSpans:[{resource:{attributes:u(r,o)},scopeSpans:[{scope:{name:t},spans:[e]}]}]}),N=(e,t,r,o)=>({resourceLogs:[{resource:{attributes:u(r,o)},scopeLogs:[{logRecords:[e],scope:{name:t}}]}]}),S=(e,t,r,o)=>({resourceMetrics:[{resource:{attributes:u(r,o)},scopeMetrics:[{metrics:[e],scope:{name:t}}]}]}),I=e=>t=>{const r=e?.[t];return typeof r=="string"&&r.length>0?r:void 0},g=(e,t)=>{if(typeof e!="object"||e===null)return;const r=e[t];return typeof r=="string"&&r.length>0?r:void 0},V=e=>{const t={},r=e("SERVICE_VERSION")??e("CF_VERSION_METADATA")??e("VERCEL_GIT_COMMIT_SHA")??e("GITHUB_SHA")??e("COMMIT_SHA");r!==void 0&&(t["service.version"]=r);const o=e("DEPLOYMENT_ENVIRONMENT")??e("ENVIRONMENT")??e("NODE_ENV");return o!==void 0&&(t["deployment.environment"]=o),t},_=(e,t)=>{if(!(t!==void 0||e("CLOUDFLARE")!==void 0||e("CF_ACCOUNT_ID")!==void 0))return{};const r={"cloud.provider":"cloudflare"},o=g(t,"colo")??e("CF_COLO")??e("CLOUDFLARE_COLO");return o!==void 0&&(r["cloud.region"]=o),r},y=(...e)=>{const t={};for(const r of e)if(r!==void 0)for(const[o,n]of Object.entries(r))t[o]=n;return t};export{S as L,b as O,y as R,m as V,C as a,v as b,f as c,_ as d,p as e,O as f,V as i,E as m,I as s,N as w};