@lunora/bindings 1.0.0-alpha.9 → 1.0.0-alpha.90
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/analytics/index.d.mts +21 -25
- package/dist/analytics/index.d.ts +21 -25
- package/dist/analytics/index.mjs +1 -2
- package/dist/images/index.d.mts +37 -52
- package/dist/images/index.d.ts +37 -52
- package/dist/images/index.mjs +1 -3
- package/dist/kv/index.d.mts +4 -81
- package/dist/kv/index.d.ts +4 -81
- package/dist/kv/index.mjs +1 -2
- package/dist/packem_shared/AnalyticsSqlError-CeQ3A5Eb.mjs +1 -0
- package/dist/packem_shared/R2SqlError-ZHgOWClB.mjs +1 -0
- package/dist/packem_shared/SelectBuilder-DJXNSdqC.mjs +1 -0
- package/dist/packem_shared/SetOperation-kiI5Wnlm.mjs +1 -0
- package/dist/packem_shared/Sql-BfnxRway.mjs +1 -0
- package/dist/packem_shared/WindowExpression-VX7EEV3h.mjs +1 -0
- package/dist/packem_shared/WindowFunction-CL4jYy2l.mjs +1 -0
- package/dist/packem_shared/asc-DP_WFiAE.mjs +1 -0
- package/dist/packem_shared/buildImageDeliveryUrl-Brqs-dcZ.mjs +1 -0
- package/dist/packem_shared/buildSignedImageUrl-BV-iSJKA.mjs +4 -0
- package/dist/packem_shared/cap-error-body-YBKO32BF.mjs +1 -0
- package/dist/packem_shared/concurrent-vRmSvRpF.mjs +1 -0
- package/dist/packem_shared/createAnalytics-BXTNc57d.mjs +1 -0
- package/dist/packem_shared/createContextVectors-DiyO3pZU.mjs +6 -0
- package/dist/packem_shared/createImages-D7JExfqF.mjs +1 -0
- package/dist/packem_shared/createKv-mAHanD5g.mjs +1 -0
- package/dist/packem_shared/createKvIntrospector-BpRiFRFQ.mjs +1 -0
- package/dist/packem_shared/createPipelines-CIvqrc7E.mjs +1 -0
- package/dist/packem_shared/createVectorAdminIntrospector-Ct8v6PxJ.mjs +1 -0
- package/dist/packem_shared/createVectors-Dzv0ilKE.mjs +1 -0
- package/dist/pipelines/index.d.mts +1 -1
- package/dist/pipelines/index.d.ts +1 -1
- package/dist/pipelines/index.mjs +1 -1
- package/dist/r2sql/index.d.mts +54 -10
- package/dist/r2sql/index.d.ts +54 -10
- package/dist/r2sql/index.mjs +1 -7
- package/dist/vectors/index.d.mts +236 -71
- package/dist/vectors/index.d.ts +236 -71
- package/dist/vectors/index.mjs +1 -3
- package/package.json +3 -2
- package/dist/packem_shared/AnalyticsSqlError-C2nz3jpH.mjs +0 -41
- package/dist/packem_shared/R2SqlError-drPKSCZ3.mjs +0 -65
- package/dist/packem_shared/SelectBuilder-BOqJQHEv.mjs +0 -168
- package/dist/packem_shared/SetOperation-DmPgUL8W.mjs +0 -81
- package/dist/packem_shared/Sql-B3zq2YGx.mjs +0 -74
- package/dist/packem_shared/WindowExpression-BT_uA6g1.mjs +0 -44
- package/dist/packem_shared/WindowFunction-DrnuZUF6.mjs +0 -82
- package/dist/packem_shared/asc-DZbQCxh1.mjs +0 -16
- package/dist/packem_shared/buildImageDeliveryUrl-qZ7XbqTL.mjs +0 -35
- package/dist/packem_shared/buildSignedImageUrl-DNUFfyGP.mjs +0 -130
- package/dist/packem_shared/concurrent-CkCEVwqP.mjs +0 -39
- package/dist/packem_shared/createAnalytics-CEEI69o9.mjs +0 -57
- package/dist/packem_shared/createContextVectors-DwZtnPeC.mjs +0 -140
- package/dist/packem_shared/createImages-BzRnsz3H.mjs +0 -85
- package/dist/packem_shared/createKv-C8Iyu5hD.mjs +0 -145
- package/dist/packem_shared/createKvIntrospector-Byk4GfsY.mjs +0 -77
- package/dist/packem_shared/createPipelines-CfyJ6VGu.mjs +0 -10
- package/dist/packem_shared/createVectorAdminIntrospector-DuSvcBa5.mjs +0 -53
- package/dist/packem_shared/createVectors-CTSrctiK.mjs +0 -95
package/dist/kv/index.d.ts
CHANGED
|
@@ -1,82 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* `KVNamespace` `get`/`put` body unions; declared here so the package stays
|
|
4
|
-
* runtime-agnostic and the `*Like` interfaces don't pull in
|
|
5
|
-
* `@cloudflare/workers-types` at runtime.
|
|
6
|
-
*/
|
|
7
|
-
type KvValue = ReadableStream | ArrayBuffer | ArrayBufferView | string;
|
|
8
|
-
/** How a raw KV read should decode the stored value. Mirrors KV's `type` option. */
|
|
9
|
-
type KvValueType = "text" | "json" | "arrayBuffer" | "stream";
|
|
10
|
-
/**
|
|
11
|
-
* Per-read options forwarded to the binding. `cacheTtl` is KV's edge-cache TTL
|
|
12
|
-
* (seconds, min 60); `type` selects the decode mode for {@link Kv.getRaw}.
|
|
13
|
-
*/
|
|
14
|
-
interface KvGetOptions {
|
|
15
|
-
/** KV edge-cache TTL in seconds (minimum 60). Forwarded verbatim. */
|
|
16
|
-
cacheTtl?: number;
|
|
17
|
-
/** Decode mode for a raw read. {@link Kv.get} always uses `"json"`. */
|
|
18
|
-
type?: KvValueType;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Minimal projection of Cloudflare's `KVNamespace`. Declared structurally so
|
|
22
|
-
* unit tests can pass a plain `Map`-backed double; the real binding satisfies
|
|
23
|
-
* the same shape. Mirrors `R2BucketLike` in `@lunora/storage`.
|
|
24
|
-
*/
|
|
25
|
-
interface KVNamespaceLike {
|
|
26
|
-
/** Delete a key. No-op if the key is absent. */
|
|
27
|
-
delete: (key: string) => Promise<void>;
|
|
28
|
-
/**
|
|
29
|
-
* Read a value. The real binding overloads on `options.type`; declared here
|
|
30
|
-
* as the broad union so a structural double need only return the value (or
|
|
31
|
-
* `null` when absent).
|
|
32
|
-
*/
|
|
33
|
-
get: (key: string, options?: KvGetOptions | KvValueType) => Promise<unknown>;
|
|
34
|
-
/**
|
|
35
|
-
* Read a value together with its associated metadata. Returns
|
|
36
|
-
* `{ value: null, metadata: null }` when the key is absent.
|
|
37
|
-
*/
|
|
38
|
-
getWithMetadata: (key: string, options?: KvGetOptions | KvValueType) => Promise<{
|
|
39
|
-
metadata: unknown;
|
|
40
|
-
value: unknown;
|
|
41
|
-
}>;
|
|
42
|
-
/** List keys, optionally filtered by `prefix` and paginated via `cursor`. */
|
|
43
|
-
list: (options?: {
|
|
44
|
-
cursor?: string;
|
|
45
|
-
limit?: number;
|
|
46
|
-
prefix?: string;
|
|
47
|
-
}) => Promise<KvNamespaceListResult>;
|
|
48
|
-
/** Write a value, optionally with TTL/expiration and metadata. */
|
|
49
|
-
put: (key: string, value: KvValue, options?: KvNamespacePutOptions) => Promise<void>;
|
|
50
|
-
}
|
|
51
|
-
/** The raw put options the KV binding accepts (mirrors `KVNamespacePutOptions`). */
|
|
52
|
-
interface KvNamespacePutOptions {
|
|
53
|
-
/** Absolute expiration as a Unix timestamp (seconds). Mutually exclusive with `expirationTtl`. */
|
|
54
|
-
expiration?: number;
|
|
55
|
-
/** Relative expiration in seconds from now (minimum 60). Mutually exclusive with `expiration`. */
|
|
56
|
-
expirationTtl?: number;
|
|
57
|
-
/** Arbitrary JSON metadata stored alongside the value, returned by `getWithMetadata`/`list`. */
|
|
58
|
-
metadata?: unknown;
|
|
59
|
-
}
|
|
60
|
-
/** One key entry as returned by the KV binding's `list`. */
|
|
61
|
-
interface KvListKey<Metadata = unknown> {
|
|
62
|
-
/** Absolute expiration (Unix seconds), when the key has one. */
|
|
63
|
-
expiration?: number;
|
|
64
|
-
/** The key's metadata, when set at write time. */
|
|
65
|
-
metadata?: Metadata;
|
|
66
|
-
/** The key name. */
|
|
67
|
-
name: string;
|
|
68
|
-
}
|
|
69
|
-
/** The raw `list` result shape returned by the KV binding. */
|
|
70
|
-
type KvNamespaceListResult<Metadata = unknown> = {
|
|
71
|
-
cacheStatus?: string | null;
|
|
72
|
-
cursor: string;
|
|
73
|
-
keys: KvListKey<Metadata>[];
|
|
74
|
-
list_complete: false;
|
|
75
|
-
} | {
|
|
76
|
-
cacheStatus?: string | null;
|
|
77
|
-
keys: KvListKey<Metadata>[];
|
|
78
|
-
list_complete: true;
|
|
79
|
-
};
|
|
1
|
+
import { KvGetOptions, KvListKey, KVNamespaceLike } from '@lunora/platform';
|
|
2
|
+
export type { KVNamespaceLike, KvGetOptions, KvListKey, KvNamespaceListResult, KvNamespacePutOptions, KvValue, KvValueType } from '@lunora/platform';
|
|
80
3
|
/** Construction options for the `createKv` factory. */
|
|
81
4
|
interface LunoraKvOptions {
|
|
82
5
|
/**
|
|
@@ -86,7 +9,7 @@ interface LunoraKvOptions {
|
|
|
86
9
|
* `..` or NUL in the prefix is rejected.
|
|
87
10
|
*/
|
|
88
11
|
keyPrefix?: string;
|
|
89
|
-
/** The bound KV namespace (`env
|
|
12
|
+
/** The bound KV namespace (`env.<BINDING>`). */
|
|
90
13
|
namespace: KVNamespaceLike;
|
|
91
14
|
}
|
|
92
15
|
/** Options for {@link Kv.put}. JSON-stringifies the value unless `raw` is set. */
|
|
@@ -268,4 +191,4 @@ declare const createKvIntrospector: (options: CreateKvIntrospectorOptions) => Kv
|
|
|
268
191
|
* ```
|
|
269
192
|
*/
|
|
270
193
|
declare const createKvIntrospectorFromEnv: (env: unknown) => KvIntrospectorLike;
|
|
271
|
-
export { type CreateKvIntrospectorOptions, type
|
|
194
|
+
export { type CreateKvIntrospectorOptions, type Kv, type KvIntrospectorLike, type KvListOptions, type KvListResult, type KvPutOptions, type KvValueWithMetadata, type LunoraKvOptions, createKv, createKvIntrospector, createKvIntrospectorFromEnv, scopeKey };
|
package/dist/kv/index.mjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { createKvIntrospector, createKvIntrospectorFromEnv } from '../packem_shared/createKvIntrospector-Byk4GfsY.mjs';
|
|
1
|
+
import{createKv as o,scopeKey as t}from"../packem_shared/createKv-mAHanD5g.mjs";import{createKvIntrospector as p,createKvIntrospectorFromEnv as v}from"../packem_shared/createKvIntrospector-BpRiFRFQ.mjs";export{o as createKv,p as createKvIntrospector,v as createKvIntrospectorFromEnv,t as scopeKey};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as y}from"@lunora/errors";import{c as h}from"./cap-error-body-YBKO32BF.mjs";const w="https://api.cloudflare.com/client/v4/accounts",S=6e4;class a extends y{constructor(r,o){super("ANALYTICS_SQL_ERROR",`Analytics Engine SQL API returned ${String(r)}: ${h(o)}`,{cause:o,name:"AnalyticsSqlError",status:r})}}const b=e=>{const r=e.fetch??globalThis.fetch,o=`${w}/${encodeURIComponent(e.accountId)}/analytics_engine/sql`,c=e.timeoutMs??S;return{query:async u=>{const n=new AbortController,d=setTimeout(()=>{n.abort()},c);try{const t=await r(o,{body:u,headers:{Authorization:`Bearer ${e.apiToken}`,"Content-Type":"text/plain"},method:"POST",signal:n.signal});if(!t.ok)throw new a(t.status,await t.text().catch(()=>"<error body unavailable: the request deadline fired before it was read>"));let i;try{i=await t.json()}catch(m){throw n.signal.aborted?m:new a(t.status,"Analytics Engine SQL API returned a non-JSON body.")}const s=i,l=s.data??[];return{columns:s.meta??[],rowCount:s.rows??l.length,rows:l}}catch(t){throw n.signal.aborted&&!(t instanceof a)?new a(504,`query timed out after ${String(c)}ms (AnalyticsSqlConfig.timeoutMs)`):t}finally{clearTimeout(d)}}}};export{a as AnalyticsSqlError,b as createAnalyticsSqlClient};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as f}from"@lunora/errors";import{c as b}from"./cap-error-body-YBKO32BF.mjs";import R from"./SelectBuilder-DJXNSdqC.mjs";import{ident as m,toText as h}from"./Sql-BfnxRway.mjs";const T="https://api.sql.cloudflarestorage.com/api/v1/accounts",E=6e4,$=e=>e[0]===void 0?[]:Object.keys(e[0]).map(s=>({name:s}));class c extends f{constructor(s,i){super("R2_SQL_ERROR",`R2 SQL query failed (${String(s)}): ${b(i)}`,{cause:i,name:"R2SqlError",status:s})}}const C=e=>{const s=e.fetch??globalThis.fetch,S=`${e.endpoint??T}/${encodeURIComponent(e.accountId)}/r2-sql/query/${encodeURIComponent(e.bucket)}`,p=`${e.accountId}_${e.bucket}`,l=e.timeoutMs??E,n=async t=>{const a=new AbortController,w=setTimeout(()=>{a.abort()},l);try{const r=await s(S,{body:JSON.stringify({query:t,warehouse:p}),headers:{Authorization:`Bearer ${e.apiToken}`,"Content-Type":"application/json"},method:"POST",signal:a.signal});if(!r.ok)throw new c(r.status,await r.text().catch(()=>"<error body unavailable: the request deadline fired before it was read>"));let d;try{d=await r.json()}catch(y){throw a.signal.aborted?y:new c(r.status,"R2 SQL returned a non-JSON body.")}const o=d;if(o.success===!1||o.errors!==void 0&&o.errors.length>0)throw new c(r.status,JSON.stringify(o.errors??o));const u=o.result?.rows??[];return{columns:o.result?.schema??$(u),rowCount:u.length,rows:u}}catch(r){throw a.signal.aborted&&!(r instanceof c)?new c(504,`query timed out after ${String(l)}ms (R2SqlConfig.timeoutMs)`):r}finally{clearTimeout(w)}};return{describe:async t=>n(`DESCRIBE ${m(t)}`),explain:async(t,a)=>n(`EXPLAIN ${a?.format==="json"?"FORMAT JSON ":""}${h(t)}`),from:t=>new R(n,t),query:async t=>n(h(t)),showDatabases:async()=>n("SHOW DATABASES"),showTables:async t=>n(`SHOW TABLES IN ${m(t)}`)}};export{c as R2SqlError,C as createR2Sql};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{renderOrderTerm as u}from"./asc-DP_WFiAE.mjs";import l from"./SetOperation-kiI5Wnlm.mjs";import{tableRef as n,toText as e,assertLimit as a,lit as d}from"./Sql-BfnxRway.mjs";const r={cross:"CROSS JOIN",full:"FULL OUTER JOIN",inner:"INNER JOIN",left:"LEFT JOIN",right:"RIGHT JOIN"},h=s=>s.length>1?s.map(t=>`(${t})`).join(" AND "):s.join(" AND ");class c{exec;table;selectItems=[];distinctFlag=!1;distinctOnItems=[];joins=[];whereConditions=[];groupByItems=[];havingConditions=[];qualifyCondition;orderByItems=[];limitValue;constructor(t,i){this.exec=t,this.table=n(i)}select(...t){return this.selectItems.push(...t.map(i=>e(i))),this}distinct(){return this.distinctFlag=!0,this}distinctOn(...t){return this.distinctOnItems.push(...t.map(i=>e(i))),this}innerJoin(t,i){return this.addJoin("inner",t,i)}leftJoin(t,i){return this.addJoin("left",t,i)}rightJoin(t,i){return this.addJoin("right",t,i)}fullJoin(t,i){return this.addJoin("full",t,i)}crossJoin(t){return this.addJoin("cross",t)}where(...t){return this.whereConditions.push(...t.map(i=>e(i))),this}groupBy(...t){return this.groupByItems.push(...t.map(i=>e(i))),this}having(...t){return this.havingConditions.push(...t.map(i=>e(i))),this}qualify(t){return this.qualifyCondition=e(t),this}orderBy(...t){return this.orderByItems.push(...t.map(i=>u(i))),this}limit(t){return a(t),this.limitValue=t,this}returns(){return this}union(t){return this.setOperation("UNION",t)}unionAll(t){return this.setOperation("UNION ALL",t)}intersect(t){return this.setOperation("INTERSECT",t)}except(t){return this.setOperation("EXCEPT",t)}get needsWrapForSetOperation(){return this.orderByItems.length>0||this.limitValue!==void 0}toSQL(){const t=[`${this.renderHead()} ${this.selectItems.length>0?this.selectItems.join(", "):"*"}`,`FROM ${this.table}`];for(const i of this.joins)t.push(i.on===void 0?`${r[i.kind]} ${i.table}`:`${r[i.kind]} ${i.table} ON ${e(i.on)}`);return this.whereConditions.length>0&&t.push(`WHERE ${h(this.whereConditions)}`),this.groupByItems.length>0&&t.push(`GROUP BY ${this.groupByItems.join(", ")}`),this.havingConditions.length>0&&t.push(`HAVING ${h(this.havingConditions)}`),this.qualifyCondition!==void 0&&t.push(`QUALIFY ${this.qualifyCondition}`),this.orderByItems.length>0&&t.push(`ORDER BY ${this.orderByItems.join(", ")}`),this.limitValue!==void 0&&t.push(`LIMIT ${d(this.limitValue)}`),t.join(" ")}async run(){return this.exec(this.toSQL())}renderHead(){return this.distinctOnItems.length>0?`SELECT DISTINCT ON (${this.distinctOnItems.join(", ")})`:this.distinctFlag?"SELECT DISTINCT":"SELECT"}addJoin(t,i,o){return this.joins.push({kind:t,on:o,table:n(i)}),this}setOperation(t,i){return new l(this.exec,[{query:this},{operator:t,query:i}])}}export{c as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{renderOrderTerm as o}from"./asc-DP_WFiAE.mjs";import{assertLimit as u,lit as a}from"./Sql-BfnxRway.mjs";const h=s=>{const t=s.toSQL();return s.needsWrapForSetOperation===!0?`(${t})`:t};class p{needsWrapForSetOperation=!0;exec;members;orderByItems=[];limitValue;constructor(t,r){this.exec=t,this.members=r}union(t){return this.add("UNION",t)}unionAll(t){return this.add("UNION ALL",t)}intersect(t){return this.add("INTERSECT",t)}except(t){return this.add("EXCEPT",t)}orderBy(...t){return this.orderByItems.push(...t.map(r=>o(r))),this}limit(t){return u(t),this.limitValue=t,this}returns(){return this}toSQL(){const r=this.members.map(i=>{const n=h(i.query);return i.operator===void 0?n:`${i.operator} ${n}`}).join(" "),e=[];return this.orderByItems.length>0&&e.push(`ORDER BY ${this.orderByItems.join(", ")}`),this.limitValue!==void 0&&e.push(`LIMIT ${a(this.limitValue)}`),e.length>0?`${r} ${e.join(" ")}`:r}async run(){return this.exec(this.toSQL())}add(t,r){return this.members.push({operator:t,query:r}),this}}export{p as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const o=t=>`'${t.replaceAll("'","''")}'`,c=/^\w+(?:\.\w+)*$/,p=/^\w+(?:\.\w+)*(?:\s+(?:as\s+)?\w+)?$/i;class n{text;constructor(r){this.text=r}toString(){return this.text}}const s=t=>t instanceof n,l=t=>new n(t),w=t=>s(t)?t.text:t,y=t=>{if(typeof t!="string"||!c.test(t))throw new TypeError(`r2sql: invalid identifier ${JSON.stringify(t)} — expected dotted [A-Za-z0-9_] segments (e.g. "namespace.table").`);return t},g=t=>{if(typeof t!="string"||!p.test(t))throw new TypeError(`r2sql: invalid table reference ${JSON.stringify(t)} — expected "namespace.table" with an optional "[AS] alias".`);return t},a=t=>{if(t==null)return"NULL";if(typeof t=="boolean")return t?"true":"false";if(typeof t=="bigint")return t.toString();if(typeof t=="number"){if(!Number.isFinite(t))throw new TypeError(`r2sql: cannot inline a non-finite number (${String(t)}) as a SQL literal.`);return String(t)}if(typeof t=="string")return o(t);if(t instanceof Date){if(Number.isNaN(t.getTime()))throw new TypeError("r2sql: cannot inline an invalid Date — it has no RFC3339 form. Check the value parsed before building the query.");return o(t.toISOString())}if(Array.isArray(t)){if(t.length===0)throw new TypeError("r2sql: cannot inline an empty array — `IN ()` is not valid SQL. Guard the empty case before building the query.");return`(${t.map(r=>a(r)).join(", ")})`}throw new TypeError(`r2sql: cannot inline a value of type ${typeof t} as a SQL literal. Wrap trusted SQL with raw(), or pass a primitive/Date/array.`)},S=(t,...r)=>{let e=t[0]??"";for(const[f,i]of r.entries())e+=s(i)?i.text:a(i),e+=t[f+1]??"";return new n(e)},d=(t,r)=>new n(t.map(e=>w(e)).join(r)),h=t=>{if(!Number.isInteger(t)||t<1||t>1e4)throw new RangeError(`r2sql: limit must be an integer between 1 and ${String(1e4)} (got ${String(t)}).`)};export{n as Sql,h as assertLimit,y as ident,s as isSql,d as joinSql,a as lit,l as raw,S as sql,g as tableRef,w as toText};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Sql as r,lit as i}from"./Sql-BfnxRway.mjs";const n=/^[A-Z_][\w$]*$/i,o=t=>{if(!n.test(t))throw new TypeError(`r2sql: invalid identifier ${JSON.stringify(t)} — expected a simple SQL name (letters, digits, underscore).`);return t};class p extends r{as(e){return new r(`${this.text} AS ${o(e)}`)}between(e,s){return new r(`${this.text} BETWEEN ${i(e)} AND ${i(s)}`)}eq(e){return this.compare("=",e)}gt(e){return this.compare(">",e)}gte(e){return this.compare(">=",e)}lt(e){return this.compare("<",e)}lte(e){return this.compare("<=",e)}compare(e,s){return new r(`${this.text} ${e} ${i(s)}`)}}export{p as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{renderOrderTerm as $}from"./asc-DP_WFiAE.mjs";import{toText as o,lit as s}from"./Sql-BfnxRway.mjs";import A from"./WindowExpression-VX7EEV3h.mjs";const u=r=>r===void 0?[]:Array.isArray(r)?r:[r],c=r=>{const t=[],i=u(r.partitionBy).map(a=>o(a));i.length>0&&t.push(`PARTITION BY ${i.join(", ")}`);const e=u(r.orderBy).map(a=>$(a));return e.length>0&&t.push(`ORDER BY ${e.join(", ")}`),r.frame!==void 0&&r.frame.length>0&&t.push(r.frame),`OVER (${t.join(" ")})`},m=(r,t,i)=>{const e=[o(r)];return t!==void 0&&e.push(s(t)),i!==void 0&&e.push(s(i)),e.join(", ")};class d{callText;constructor(t){this.callText=t}over(t={}){return new A(`${this.callText} ${c(t)}`)}}const n=r=>new d(r),l={avg:r=>n(`AVG(${o(r)})`),count:r=>n(`COUNT(${r===void 0?"*":o(r)})`),cumeDist:()=>n("CUME_DIST()"),denseRank:()=>n("DENSE_RANK()"),firstValue:r=>n(`FIRST_VALUE(${o(r)})`),lag:(r,t,i)=>n(`LAG(${m(r,t,i)})`),lastValue:r=>n(`LAST_VALUE(${o(r)})`),lead:(r,t,i)=>n(`LEAD(${m(r,t,i)})`),max:r=>n(`MAX(${o(r)})`),min:r=>n(`MIN(${o(r)})`),nthValue:(r,t)=>n(`NTH_VALUE(${o(r)}, ${s(t)})`),ntile:r=>n(`NTILE(${s(r)})`),percentRank:()=>n("PERCENT_RANK()"),rank:()=>n("RANK()"),rowNumber:()=>n("ROW_NUMBER()"),sum:r=>n(`SUM(${o(r)})`)};export{d as WindowFunction,l as fn};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Sql as e,toText as n}from"./Sql-BfnxRway.mjs";const o=r=>({dir:"ASC",expr:r}),i=r=>({dir:"DESC",expr:r}),s=r=>typeof r=="string"||r instanceof e?n(r):`${n(r.expr)} ${r.dir}`;export{o as asc,i as desc,s as renderOrderTerm};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as a}from"@lunora/errors";const s=/^[a-z][a-z\d+\-.]*:\/\//i,c=[",","=","#","?","/"],d=e=>e.endsWith("/")?e.slice(0,-1):e,g=e=>e.startsWith("/")?e.slice(1):e,m=e=>Object.entries(e).filter(([,r])=>r!==void 0&&(typeof r=="string"||typeof r=="number")).map(([r,i])=>{const n=String(i),t=c.find(o=>n.includes(o));if(t!==void 0)throw new a("INTERNAL",`@lunora/bindings/images: transform option \`${r}\` value \`${n}\` contains a \`${t}\`, which the /cdn-cgi/image/ option path cannot represent (\`,\`/\`=\` are the option/key-value separators; \`#\`/\`?\`/\`/\` are URL-structural). Percent-encode the value — for colors use \`%23RRGGBB\`, not \`#RRGGBB\` or \`rgb(r,g,b)\`.`);return`${r}=${n}`}).join(","),l=e=>e.split("/").map(r=>encodeURIComponent(r)).join("/"),h=e=>{const r=d(e.baseUrl);if(e.imageId!==void 0){const o=e.variant??"public";return`${r}/${encodeURIComponent(e.imageId)}/${encodeURIComponent(o)}`}if(e.key===void 0)throw new a("INTERNAL","@lunora/bindings/images: buildImageDeliveryUrl requires either `imageId` or `key`");const i=e.transform===void 0?"":m(e.transform),n=s.test(e.key)?e.key:l(g(e.key)),t=i===""?"/cdn-cgi/image":`/cdn-cgi/image/${i}`;return`${r}${t}/${n}`};export{h as buildImageDeliveryUrl};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
const w=e=>{const t=atob(e),r=new Uint8Array(t.length);for(let n=0;n<t.length;n+=1)r[n]=t.codePointAt(n)??0;return r},a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",E=e=>{let t="",r=0;const n=e.length-2;for(;r<n;r+=3){const s=e[r]<<16|e[r+1]<<8|e[r+2];t+=a.charAt(s>>18&63)+a.charAt(s>>12&63)+a.charAt(s>>6&63)+a.charAt(s&63)}const o=e.length-r;if(o===1){const s=e[r]<<16;t+=a.charAt(s>>18&63)+a.charAt(s>>12&63)}else if(o===2){const s=e[r]<<16|e[r+1]<<8;t+=a.charAt(s>>18&63)+a.charAt(s>>12&63)+a.charAt(s>>6&63)}return t},v=e=>{const t=e.replaceAll("-","+").replaceAll("_","/"),r=t+"=".repeat((4-t.length%4)%4);return w(r)},R=(e,t)=>{if(e.size<t)return;const r=e.keys().next().value;r!==void 0&&e.delete(r)},_=(e,t,r,n)=>{const o=e.get(t);if(o!==void 0)return o;R(e,n);const s=r().catch(i=>{throw e.get(t)===s&&e.delete(t),i});return e.set(t,s),s},f=new TextEncoder,T=10080*60,$=/^[a-z][a-z0-9+\-.]*:\/\//i,x=Array.from({length:32},(e,t)=>t),C=new RegExp(`[${x.map(e=>String.fromCodePoint(e)).join("")}]`,"u"),U=64,N=new Map,h=async e=>_(N,e,async()=>crypto.subtle.importKey("raw",f.encode(e),{hash:"SHA-256",name:"HMAC"},!1,["sign","verify"]),U),p=e=>{try{return new URL(e).host}catch{return e.replace($,"").split("/")[0]??""}},y=e=>{if(C.test(e))throw new TypeError("hmac-url: value must not contain control characters (including CR/LF)")},L=/^\/+$/u,O=e=>L.test(e),H=(e,t)=>{if(!Number.isFinite(e)||e<=0)return"expiresInSeconds must be a positive finite number";if(e>t){const r=` (${String(t/86400)} days)`;return`expiresInSeconds must not exceed ${String(t)} seconds${r}`}},I=async(e,t)=>{const r=await h(e),n=await crypto.subtle.sign("HMAC",r,f.encode(t));return E(new Uint8Array(n))},K=async(e,t,r)=>{const n=await h(e);return crypto.subtle.verify("HMAC",n,r,f.encode(t))},b=/^\//,P=e=>{let t=e.length;for(;t>0&&e[t-1]==="/";)t-=1;return e.slice(0,t)},D=e=>e.replaceAll("&","%26").replaceAll("=","%3D"),M=e=>e.replaceAll("%3D","=").replaceAll("%26","&"),j=e=>e===void 0?"":Object.entries(e).filter(([,t])=>t!==void 0).toSorted(([t],[r])=>(t>r?1:0)-(t<r?1:0)).map(([t,r])=>`${t}=${D(typeof r=="object"?JSON.stringify(r):String(r))}`).join("&"),k={background:"string",blur:"number",brightness:"number",contrast:"number",fit:"string",flip:"string",gamma:"number",gravity:"string-or-json",height:"number",rotate:"number",saturation:"number",segment:"string",sharpen:"number",upscale:"string",width:"number"},z=new Map(Object.entries(k)),B=(e,t,r)=>{if(t==="string"||t==="string-or-json"&&!r.startsWith("{"))return r;if(t==="number"){const n=Number(r);if(r===""||!Number.isFinite(n))throw new TypeError(`@lunora/bindings/images: transform key "${e}" expects a number, got "${r}"`);return n}try{return JSON.parse(r)}catch{throw new TypeError(`@lunora/bindings/images: transform key "${e}" carries malformed JSON`)}},A=(e,t,r,n)=>`${e.toLowerCase()}
|
|
2
|
+
${t}
|
|
3
|
+
${String(r)}
|
|
4
|
+
${n}`,F=e=>e.split("/").map(t=>encodeURIComponent(t)).join("/"),Y=e=>{if(e==="")return{};const t={};for(const r of e.split("&")){const n=r.indexOf("=");if(n===-1)throw new TypeError(`@lunora/bindings/images: malformed transform segment "${r}" — expected key=value`);const o=r.slice(0,n),s=z.get(o);if(s===void 0)throw new TypeError(`@lunora/bindings/images: unknown transform key "${o}" — the serialized transform does not match this version's TransformOptions`);t[o]=B(o,s,M(r.slice(n+1)))}return t},J=async e=>{const t=e.expiresInSeconds??3600,r=H(t,T);if(r!==void 0)throw new TypeError(`@lunora/bindings/images: ${r}`);let n="";try{n=new URL(e.baseUrl).pathname}catch{}if(n!==""&&!O(n))throw new TypeError(`@lunora/bindings/images: baseUrl must not carry a path ("${n}") — the key is verified from the full URL pathname, so a subpath base would make every signed URL fail verification`);const o=Math.floor(Date.now()/1e3)+t,s=p(e.baseUrl),i=j(e.transform),c=e.key.replace(b,"");y(c);const l=await I(e.secret,A(s,c,o,i)),m=P(e.baseUrl),d=F(c),g=i===""?"":`&t=${encodeURIComponent(i)}`;return`${m}/${d}?exp=${String(o)}&sig=${l}${g}`},V=async(e,t,r)=>{let n;try{n=e instanceof URL?e:new URL(e)}catch{return{reason:"malformed",valid:!1}}const o=n.searchParams.get("exp"),s=o===null?Number.NaN:Number(o),i=n.searchParams.get("sig"),c=n.searchParams.get("t")??"";if(!i||!Number.isInteger(s))return{reason:"malformed",valid:!1};if(s<Math.floor(Date.now()/1e3))return{reason:"expired",valid:!1};let l,m;try{l=n.pathname.replace(b,"").split("/").map(S=>decodeURIComponent(S)).join("/"),y(l),m=v(i)}catch{return{reason:"malformed",valid:!1}}const d=r?.expectedHost===void 0?n.host:p(r.expectedHost);if(!await K(t,A(d,l,s,c),m))return{reason:"bad_signature",valid:!1};if(c==="")return{key:l,valid:!0};let u;try{u=Y(c)}catch{u=void 0}return{key:l,transform:c,transformOptions:u,valid:!0}};export{J as buildSignedImageUrl,Y as parseSignedTransform,V as verifySignedImageUrl};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const _=R=>R.length>256?`${R.slice(0,256)}… (truncated)`:R;export{_ as c};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const h=8,u=async(r,c,l)=>{if(r.length===0)return[];const f=Math.max(1,Math.min(c,r.length)),n=Array.from({length:r.length});let a=0,t=!1,o;const s=Array.from({length:f},async()=>{for(;;){if(t)return;const e=a;if(a+=1,e>=r.length)return;try{n[e]=await l(r[e],e)}catch(i){t||(t=!0,o=i);return}}});if(await Promise.all(s),t)throw o;return n};export{h as U,u as c};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const _=new TextEncoder,l=n=>n===null?0:typeof n=="string"?_.encode(n).length:n.byteLength,a=(n,o,r)=>{if(o>r)throw new RangeError(`@lunora/bindings/analytics: a data point may carry at most ${String(r)} ${n} (got ${String(o)}).`)},b=(n,o,r)=>{if(o>r)throw new RangeError(`@lunora/bindings/analytics: a data point's ${n} may total at most ${String(r)} bytes (got ${String(o)}).`)},m=n=>{const o=t=>{a("blobs",t.blobs?.length??0,20),a("doubles",t.doubles?.length??0,20),a("indexes",t.indexes?.length??0,1);const s=(t.blobs??[]).reduce((e,c)=>e+l(c),0);b("blobs",s,16384);for(const e of t.indexes??[])b("index",l(e),96);n.writeDataPoint(t)};return{track:(t,s={})=>{const e=Object.entries(s.dimensions??{}),c=Object.entries(s.metrics??{}),E=[t,...e.map(([,i])=>i)],g=c.map(([,i])=>i),u=s.index===void 0?[]:[s.index];o({blobs:E,doubles:g,indexes:u});const B=e.map(([i],d)=>({column:`blob${String(d+2)}`,field:i})),S=c.map(([i],d)=>({column:`double${String(d+1)}`,field:i})),X=s.index===void 0?null:{column:"index1",field:"index"};return{dimensions:B,index:X,metrics:S,name:t}},writeDataPoint:o}};export{m as createAnalytics};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{LunoraError as x}from"@lunora/errors";import{c as b,U as g}from"./concurrent-vRmSvRpF.mjs";const B=(t,a)=>{if(!a.includes("."))return t[a];let s=t;for(const e of a.split(".")){if(s===null||typeof s!="object"||Array.isArray(s))return;s=s[e]}return s},T=(t,a)=>{const s=a?.namespace,e=new Set(a?.shardedIndexNames),n=(c,l)=>{if(l!==void 0)return l;if(e.has(c)){if(s!==void 0)return s;throw new Error(`@lunora/bindings/vectors: index "${c}" belongs to a sharded table, but this DO instance has no shard key (it is the root/default DO) and no explicit namespace was given. A namespace-less operation here would reach every tenant's vectors — Vectorize indexes are account-global. Pass an explicit namespace, or issue this call from the sharded DO instance that owns the tenant.`)}},i=a?.deferAfterCommit,d=async(c,l,u)=>{await t.upsert(c,{embed:l.embed,id:l.id,input:l.input,metadata:l.metadata,namespace:u})},f=async(c,l)=>{await d(c,l,n(c,l.namespace))},o=i===void 0?f:async(c,l)=>{const u=n(c,l.namespace);await i(async()=>d(c,l,u))},r=async(c,l,u)=>{const m=await t.getByIds(c,l);return u===void 0?m:m.filter(h=>h.namespace===u)};return{deleteByIds:async(c,l,u)=>{const m=n(c,u);if(m===void 0){await t.deleteByIds(c,l);return}const h=await r(c,l,m);h.length!==0&&await t.deleteByIds(c,h.map(p=>p.id))},getByIds:async(c,l,u)=>{const m=n(c,u);return(await r(c,l,m)).map(p=>({id:p.id,metadata:p.metadata,namespace:p.namespace,values:[...p.values]}))},query:async(c,l)=>{const u=await t.query(c,{embed:l.embed,filter:l.filter,input:l.input,namespace:n(c,l.namespace),returnMetadata:l.returnMetadata??"indexed",topK:l.topK,vector:l.vector});return{count:u.count,matches:u.matches.map(m=>({id:m.id,metadata:m.metadata,score:m.score}))}},upsert:o,upsertNow:f}},w=new Set,I=t=>{w.has(t)||(w.add(t),console.warn(`[@lunora/bindings/vectors] index "${t}" syncs vectors without a namespace — in a
|
|
2
|
+
multi-tenant/sharded app this exposes one tenant's vectors (and any captured
|
|
3
|
+
metadata) to every other tenant, since Vectorize indexes are account-global.
|
|
4
|
+
Pass \`namespace\` (the shard/tenant key) on both write and query — query-side
|
|
5
|
+
namespace filtering is mandatory for multi-tenant apps. Single-tenant apps that
|
|
6
|
+
legitimately have no tenant key suppress this via { allowSharedNamespace: true }.`))},A=(t,a)=>{const s={};for(const e of a)e in t&&(s[e]=t[e]);return s},v=(t,a)=>{a.input.trim()===""?t.deletes.push(a.name):t.upserts.push(a)},C=(t,a,s)=>{const e=B(t,a.field);if(e!=null){if(typeof e!="string")throw new TypeError(`@lunora/bindings/vectors: inline index "${a.name}" expects a string source at "${a.field}" on table "${s}" (got ${typeof e}); use a standalone defineVectorIndex with a select() to derive text from non-string columns`);return e}},k=(t,a)=>{const s=t.tables[a.table],e=s?.vectorIndexes??[],n=Object.entries(t.vectorIndexes).filter(([,r])=>r.table===a.table);if(e.length===0&&n.length===0)return;const i=s?.softDeleteMode?.field,d=i!==void 0&&a.doc?.[i]!==void 0&&a.doc[i]!==null;if(a.op==="delete"||d)return{deletes:[...e.map(r=>r.name),...n.map(([r])=>r)],upserts:[]};const f=a.doc;if(!f)return;const o={deletes:[],upserts:[]};for(const r of e){const c=C(f,r,a.table);c===void 0?o.deletes.push(r.name):v(o,{embed:r.embed,input:c,metadata:r.metadata?A(f,r.metadata):void 0,name:r.name})}for(const[r,c]of n)v(o,{embed:c.embed,input:c.select(f),metadata:c.metadata?.(f),name:r});return o},j=t=>{const{allowSharedNamespace:a,namespace:s,schema:e,vectors:n}=t;return async i=>{const d=k(e,i);if(!d)return;const f=[...d.deletes.map(o=>async()=>{await n.deleteByIds(o,[i.id])}),...d.upserts.map(o=>async()=>{!a&&s===void 0&&I(o.name),await n.upsertNow(o.name,{embed:o.embed,id:i.id,input:o.input,metadata:o.metadata,namespace:s})})];await b(f,g,async o=>o())}},S=1e3,E=(t,a)=>{const s=[];for(let e=0;e<t.length;e+=a)s.push(t.slice(e,e+a));return s},y=t=>{if(typeof t!="object"||t===null)return"unknown";const{name:a,status:s,statusCode:e}=t,n=typeof s=="number"?s:e;if(typeof n=="number"){if(n>=500||n===401||n===403||n===408||n===429)return"service";if(n>=400)return"row"}return a==="TimeoutError"||a==="AbortError"?"service":t instanceof TypeError||t instanceof RangeError?"row":"unknown"},M=async(t,a)=>{const s=await b(t,g,async d=>{try{return{item:d,ok:!0,value:await a(d)}}catch(f){return{error:f,item:d,ok:!1}}}),e=s.flatMap(d=>d.ok?[{item:d.item,value:d.value}]:[]),n=s.flatMap(d=>d.ok?[]:[{error:d.error,item:d.item}]),i=n.find(({error:d})=>y(d)==="service");if(i)throw i.error;if(t.length>=2&&e.length===0&&n.some(({error:d})=>y(d)!=="row"))throw n[0]?.error;return{failed:n,ok:e}},D=(t,a,s,e)=>{const n=new Map,i=[];for(const{doc:d,id:f}of s){let o;try{o=k(t,{doc:d,id:f,op:"update",table:a})}catch(r){e.set(f,r);continue}for(const r of o?.deletes??[])n.set(r,[...n.get(r)??[],f]);for(const r of o?.upserts??[])i.push({id:f,upsert:r})}return{deletes:n,pending:i}},O=async(t,a,s,e)=>{const{allowSharedNamespace:n,namespace:i,upsertMany:d,vectors:f}=t;!n&&i===void 0&&I(a);const o=s.map(({id:r,upsert:c,values:l})=>({embed:()=>l,id:r,input:c.input,metadata:c.metadata,namespace:i}));for(const r of E(o,S))try{await d(a,r)}catch{const c=await M(r,async l=>f.upsertNow(a,l));for(const{error:l,item:u}of c.failed)e.set(u.id,l)}},V=async(t,a,s)=>{const e=new Map,{deletes:n,pending:i}=D(t.schema,a,s,e),d=await M(i,async({upsert:o})=>o.embed(o.input)),f=new Map;for(const{error:o,item:r}of d.failed)e.set(r.id,o);for(const{item:o,value:r}of d.ok)f.set(o.upsert.name,[...f.get(o.upsert.name)??[],{...o,values:r}]);for(const[o,r]of n)for(const c of E(r,S))await t.vectors.deleteByIds(o,c);for(const[o,r]of f)await O(t,o,r,e);return[...e].map(([o,r])=>({error:r,id:o}))},P=t=>async(a,s)=>{try{return await V(t,a,s)}catch(e){throw y(e)==="service"?new x("SERVICE_UNAVAILABLE",e instanceof Error?e.message:String(e),{cause:e}):e}},$=t=>{const a=new Map,s=(e,n,i)=>{const d=i===void 0?n:[...n,i];a.set(e,[...a.get(e)??[],JSON.stringify(d)])};for(const[e,n]of Object.entries(t.tables))for(const i of n.vectorIndexes??[])s(e,[i.name,i.field,i.dimensions,i.metric,i.metadata??[]],i.model);for(const[e,n]of Object.entries(t.vectorIndexes))s(n.table,[e,"(select)",n.dimensions,n.metric],n.model);return[...a].map(([e,n])=>{const i=t.tables[e]?.softDeleteMode?.field;return{profile:(i===void 0?n:[...n,JSON.stringify(["(softDelete)",i])]).toSorted((f,o)=>f.localeCompare(o)).join("|"),table:e}})};export{T as createContextVectors,P as createVectorBackfillSync,j as createVectorSyncHook,$ as vectorBackfillTargets};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as f}from"@lunora/errors";const m=new Set(["image/avif","image/gif","image/jpeg","image/png","image/webp"]),T=1e4,A="image/webp",O=e=>typeof e!="object"?!1:"body"in e&&!(e instanceof ArrayBuffer)&&!(e instanceof Uint8Array),r=e=>{if(e instanceof ReadableStream)return e;if(O(e)){if(e.body===null)throw new f("INTERNAL","@lunora/bindings/images: R2 object body is null (object missing or already consumed)");return e.body}if(e instanceof Blob)return e.stream();const n=e instanceof Uint8Array?e:new Uint8Array(e);return new ReadableStream({start(t){t.enqueue(n),t.close()}})},c=(e,n)=>{if(e===void 0)return{};const t=o=>{if(!Number.isFinite(o)||o<=0)throw new TypeError("@lunora/bindings/images: width/height must be a positive finite number");return Math.max(1,Math.min(Math.floor(o),n))};return{...e,...e.width===void 0?{}:{width:t(e.width)},...e.height===void 0?{}:{height:t(e.height)}}},v=e=>{const{image:n,transform:t,...o}=e;return{drawOptions:o,image:n,transform:t}},U=e=>{const n=e?.format??A;if(!m.has(n))throw new f("INTERNAL",`@lunora/bindings/images: unsupported output format "${n}" (allowed: ${[...m].join(", ")})`);return{...e,format:n}},p=e=>{const{binding:n}=e,t=e.maxDimension??T;return{info:async o=>n.info(r(o)),transform:async(o,d,g,b)=>{const u=c(d,t),l=U(g);let i=n.input(r(o)).transform(u);for(const h of b??[]){const{drawOptions:w,image:a,transform:s}=v(h),y=s===void 0?r(a):n.input(r(a)).transform(c(s,t));i=i.draw(y,w)}return i.output(l)}}};export{p as createImages};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as c}from"@lunora/errors";const d=512,T=1e3,v=1024,f=new TextEncoder,m=t=>f.encode(t).length,h=(t,e)=>{if(m(t)>d)throw new c("BAD_REQUEST",`@lunora/bindings/kv: ${e} exceeds ${String(d)}-byte limit`);if(t.includes("\0"))throw new c("BAD_REQUEST",`@lunora/bindings/kv: ${e} contains NUL byte`);for(const a of t.split("/"))if(a==="."||a==="..")throw new c("BAD_REQUEST",`@lunora/bindings/kv: ${e} contains a \`.\`/\`..\` path component`)},u=t=>{if(typeof t!="string"||t.length===0)throw new TypeError("@lunora/bindings/kv: key must be a non-empty string");h(t,"key")},g=t=>{t.length>0&&h(t,"prefix")},E=(t,e)=>{u(t),u(e);const o=`${t.endsWith("/")?t.slice(0,-1):t}/${e}`;if(m(o)>d)throw new c("BAD_REQUEST",`@lunora/bindings/kv: scoped key exceeds ${String(d)}-byte limit`);return o},b=t=>{if(t.expiration!==void 0&&t.expirationTtl!==void 0)throw new c("BAD_REQUEST","@lunora/bindings/kv: `expiration` and `expirationTtl` are mutually exclusive")},x=t=>{let e;try{e=JSON.stringify(t)}catch{throw new c("BAD_REQUEST","@lunora/bindings/kv: metadata is not JSON-serializable (cyclic value, bigint, or similar)")}if(m(e)>v)throw new c("BAD_REQUEST",`@lunora/bindings/kv: metadata exceeds ${String(v)}-byte limit`)},p=t=>{const e={};return b(t),t.expiration!==void 0&&(e.expiration=t.expiration),t.expirationTtl!==void 0&&(e.expirationTtl=t.expirationTtl),t.metadata!==void 0&&(x(t.metadata),e.metadata=t.metadata),Object.keys(e).length>0?e:void 0},D=t=>{if(!t.namespace)throw new TypeError("@lunora/bindings/kv: `namespace` is required");const{keyPrefix:e,namespace:a}=t;e!==void 0&&u(e);const o=i=>e===void 0?(u(i),i):E(e,i),y=i=>{if(e===void 0)return i;const n=e.endsWith("/")?e:`${e}/`;return i.startsWith(n)?i.slice(n.length):i};return{delete:async i=>{await a.delete(o(i))},get:async(i,n={})=>await a.get(o(i),{cacheTtl:n.cacheTtl,type:"json"})??null,getRaw:async(i,n={})=>await a.get(o(i),{cacheTtl:n.cacheTtl,type:n.type??"text"})??null,getWithMetadata:async(i,n={})=>{const r=await a.getWithMetadata(o(i),{cacheTtl:n.cacheTtl,type:"json"});return{metadata:r.metadata??null,value:r.value??null}},list:async(i={})=>{if(i.limit!==void 0&&(!Number.isInteger(i.limit)||i.limit<=0))throw new TypeError("@lunora/bindings/kv: `limit` must be a positive integer");let{prefix:n}=i;if(n!==void 0&&g(n),e!==void 0){const l=e.endsWith("/")?e:`${e}/`;n=i.prefix===void 0?l:`${l}${i.prefix}`,g(n)}const r=i.limit===void 0?void 0:Math.min(i.limit,T),s=await a.list({cursor:i.cursor,limit:r,prefix:n}),w=s.keys.map(l=>({...l,name:y(l.name)}));return{cursor:s.list_complete?void 0:s.cursor,keys:w,listComplete:s.list_complete}},put:async(i,n,r={})=>{const s=r.raw?n:JSON.stringify(n);await a.put(o(i),s,p(r))}}};export{x as assertMetadataWithinLimit,b as assertOneExpirationForm,D as createKv,E as scopeKey,u as validateKey};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{assertOneExpirationForm as m,validateKey as i,assertMetadataWithinLimit as u}from"./createKv-mAHanD5g.mjs";import{LunoraError as d}from"@lunora/errors";const f=t=>{const{namespaces:a}=t,s=e=>{const r=a[e];if(!Object.hasOwn(a,e)||r===void 0)throw new d("BAD_REQUEST",`@lunora/bindings/kv: no namespace registered under binding "${e}"`);return r};return{deleteKey:async e=>{const r=s(e.namespace);i(e.key),await r.delete(e.key)},getValue:async e=>{const r=s(e.namespace);i(e.key);const n=await r.getWithMetadata(e.key,"text");return{metadata:n.metadata??null,value:n.value??null}},listKeys:async e=>{const n=await s(e.namespace).list({cursor:e.cursor,limit:e.limit,prefix:e.prefix}),l=n.keys.map(o=>({expiration:o.expiration,metadata:o.metadata,name:o.name}));return{cursor:n.list_complete?void 0:n.cursor,keys:l,listComplete:n.list_complete}},listNamespaces:()=>Promise.resolve(Object.keys(a).map(e=>({binding:e}))),putValue:async e=>{const r=s(e.namespace);m(e),i(e.key),e.metadata!==void 0&&u(e.metadata),await r.put(e.key,e.value,{expiration:e.expiration,expirationTtl:e.expirationTtl,metadata:e.metadata})}}},y=t=>{if(typeof t!="object"||t===null)return!1;const a=t;return typeof a.getWithMetadata=="function"&&typeof a.list=="function"&&typeof a.put=="function"&&typeof a.delete=="function"},b=t=>{const a={};if(typeof t=="object"&&t!==null)for(const[s,c]of Object.entries(t))y(c)&&(a[s]=c);return f({namespaces:a})};export{f as createKvIntrospector,b as createKvIntrospectorFromEnv};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const i=a=>{const{binding:e}=a;return{send:async n=>{await e.send(Array.isArray(n)?n:[n])}}};export{i as createPipelines};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as a}from"@lunora/errors";const u=50,m=10,p=b=>{const{embedders:t,indexes:s,registry:g}=b,i=async()=>Promise.all(g.map(async e=>{const n=s[e.name];if(n?.describe===void 0)return{...e};try{const r=await n.describe();return{...e,dimensions:e.dimensions??r.dimensions,processedUpToMutation:r.processedUpToMutation===void 0?void 0:String(r.processedUpToMutation),vectorsCount:r.vectorCount??r.vectorsCount}}catch{return{...e}}}));return t!==void 0&&Object.keys(t).length>0?{listIndexes:i,queryIndex:async({name:e,text:n,topK:r})=>{const d=s[e];if(!Object.hasOwn(s,e)||d===void 0)throw new a("INTERNAL",`@lunora/bindings/vectors: no Vectorize binding registered for index "${e}"`);const c=t[e];if(!Object.hasOwn(t,e)||c===void 0)throw new a("INTERNAL",`@lunora/bindings/vectors: no embedder registered for index "${e}" — it lists read-only`);if(r!==void 0&&(!Number.isInteger(r)||r<1||r>u))throw new RangeError(`@lunora/bindings/vectors: topK must be an integer in [1, ${String(u)}] (got ${String(r)})`);const l=await c(n);return{matches:(await d.query(l,{returnMetadata:"all",topK:r??m})).matches.map(o=>({id:o.id,metadata:o.metadata,score:o.score}))}}}:{listIndexes:i}};export{p as createVectorAdminIntrospector};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as b}from"@lunora/errors";import{c as w,U as h}from"./concurrent-vRmSvRpF.mjs";const a=(t,o)=>{const d=t[o];if(!Object.hasOwn(t,o)||d===void 0)throw new b("INTERNAL",`@lunora/bindings/vectors: no index registered for "${o}". Known indexes: ${Object.keys(t).join(", ")||"(none)"}`);return d},g=async t=>{const o=await t.embed(t.input);return{id:t.id,metadata:t.metadata,namespace:t.namespace,values:o}},m=100,u=50,c=1e3,y=1e3,K=t=>{if(Object.keys(t.indexes).length===0)throw new TypeError("@lunora/bindings/vectors: at least one index binding is required");return{deleteByIds:async(n,e)=>{const r=a(t.indexes,n);if(e.length>c)throw new RangeError(`@lunora/bindings/vectors: deleteByIds accepts at most ${String(c)} ids (got ${String(e.length)})`);return r.deleteByIds(e)},describe:async n=>{const e=a(t.indexes,n);if(!e.describe)throw new b("INTERNAL",`@lunora/bindings/vectors: binding for "${n}" does not implement describe()`);const r=await e.describe(),s=r.vectorCount??r.vectorsCount;return{...r,vectorCount:s,vectorsCount:s}},getByIds:async(n,e)=>{const r=a(t.indexes,n);if(e.length>c)throw new RangeError(`@lunora/bindings/vectors: getByIds accepts at most ${String(c)} ids (got ${String(e.length)})`);return r.getByIds(e)},query:async(n,e)=>{const r=a(t.indexes,n),s=e.returnValues===!0||e.returnMetadata==="all",l=s?u:m;if(e.topK!==void 0&&(!Number.isInteger(e.topK)||e.topK<1||e.topK>l)){const v=s?` (lowered to ${String(u)} because returnValues/returnMetadata:"all" is set)`:"";throw new RangeError(`@lunora/bindings/vectors: topK must be an integer in [1, ${String(l)}]${v} (got ${String(e.topK)})`)}let i;if(e.vector&&e.vector.length>0)i=e.vector;else{if(!e.embed||e.input===void 0)throw new TypeError("@lunora/bindings/vectors: query requires either `vector` or both `input` and `embed`");i=await e.embed(e.input)}return r.query(i,{filter:e.filter,namespace:e.namespace,returnMetadata:e.returnMetadata,returnValues:e.returnValues,topK:e.topK})},upsert:async(n,e)=>{const r=a(t.indexes,n),s=await g(e);return r.upsert([s])},upsertMany:async(n,e)=>{const r=a(t.indexes,n);if(e.length>y)throw new RangeError(`@lunora/bindings/vectors: upsertMany batch exceeds ${String(y)} (got ${String(e.length)}) — split across calls`);const s=await w(e,h,g);return r.upsert(s)}}};export{K as default};
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
/** One Pipelines record — a JSON object matching the stream's schema. */
|
|
9
9
|
type PipelineRecord = Record<string, unknown>;
|
|
10
10
|
/**
|
|
11
|
-
* Minimal structural projection of workers-types' `Pipeline
|
|
11
|
+
* Minimal structural projection of workers-types' `Pipeline<T>` binding. The
|
|
12
12
|
* real binding's `send` takes an array of records and resolves once accepted.
|
|
13
13
|
*/
|
|
14
14
|
interface PipelineBindingLike<T extends PipelineRecord = PipelineRecord> {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
/** One Pipelines record — a JSON object matching the stream's schema. */
|
|
9
9
|
type PipelineRecord = Record<string, unknown>;
|
|
10
10
|
/**
|
|
11
|
-
* Minimal structural projection of workers-types' `Pipeline
|
|
11
|
+
* Minimal structural projection of workers-types' `Pipeline<T>` binding. The
|
|
12
12
|
* real binding's `send` takes an array of records and resolves once accepted.
|
|
13
13
|
*/
|
|
14
14
|
interface PipelineBindingLike<T extends PipelineRecord = PipelineRecord> {
|
package/dist/pipelines/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import{createPipelines as i}from"../packem_shared/createPipelines-CIvqrc7E.mjs";export{i as createPipelines};
|
package/dist/r2sql/index.d.mts
CHANGED
|
@@ -18,13 +18,29 @@ declare const isSql: (value: unknown) => value is Sql;
|
|
|
18
18
|
declare const raw: (text: string) => Sql;
|
|
19
19
|
/** Resolve a `string | Sql` to its raw text. A bare string is taken as trusted SQL (callers pass identifiers/fragments here). */
|
|
20
20
|
declare const toText: (value: Sql | string) => string;
|
|
21
|
+
/**
|
|
22
|
+
* Validate a table/namespace/database identifier that will be spliced into R2 SQL
|
|
23
|
+
* text (which has no parameter binding and no identifier quoting we can rely on).
|
|
24
|
+
* Accepts only dotted `\w` segments and throws otherwise, so a client-supplied
|
|
25
|
+
* `describe`/`showTables` argument can't inject SQL. For a genuinely dynamic
|
|
26
|
+
* identifier you built yourself, wrap it with {@link raw}.
|
|
27
|
+
*/
|
|
28
|
+
declare const ident: (name: string) => string;
|
|
29
|
+
/**
|
|
30
|
+
* Validate a table REFERENCE for a `FROM`/`JOIN` position: a dotted identifier
|
|
31
|
+
* plus an optional `[AS] alias`. Broader than {@link ident} (which forbids the
|
|
32
|
+
* alias) but still an allowlist — no whitespace beyond the single alias, no
|
|
33
|
+
* punctuation — so a caller-supplied table string can't inject SQL. Use
|
|
34
|
+
* {@link raw} for anything more dynamic that you built yourself.
|
|
35
|
+
*/
|
|
36
|
+
declare const tableRef: (ref: string) => string;
|
|
21
37
|
/**
|
|
22
38
|
* Render a JS value as an R2 SQL literal:
|
|
23
39
|
*
|
|
24
40
|
* - `null` / `undefined` → `NULL`
|
|
25
41
|
* - `boolean` → `true` / `false`
|
|
26
42
|
* - finite `number` / `bigint` → the numeric text (non-finite throws — `NaN`/`Infinity` have no SQL literal)
|
|
27
|
-
* - `Date` → an RFC3339 string literal (R2 SQL's `timestamp` form)
|
|
43
|
+
* - `Date` → an RFC3339 string literal (R2 SQL's `timestamp` form; an invalid `Date` throws)
|
|
28
44
|
* - `string` → a single-quoted, escaped literal
|
|
29
45
|
* - `Array` → a parenthesised, comma-separated list of literals (for `IN (...)`)
|
|
30
46
|
*
|
|
@@ -93,6 +109,16 @@ interface R2SqlConfig {
|
|
|
93
109
|
* so a query never touches the network.
|
|
94
110
|
*/
|
|
95
111
|
fetch?: typeof globalThis.fetch;
|
|
112
|
+
/**
|
|
113
|
+
* Milliseconds before an in-flight query (the fetch AND its body read) is
|
|
114
|
+
* aborted and surfaced as an `R2SqlError` with status 504. Defaults to
|
|
115
|
+
* 60_000 — analytical scans legitimately run tens of seconds. `undefined`
|
|
116
|
+
* means the default, not unbounded.
|
|
117
|
+
*
|
|
118
|
+
* The deadline is carried by the request's `signal`, so a custom `fetch`
|
|
119
|
+
* (above) that ignores `signal` leaves the query unbounded.
|
|
120
|
+
*/
|
|
121
|
+
timeoutMs?: number;
|
|
96
122
|
}
|
|
97
123
|
/**
|
|
98
124
|
* One column descriptor in a result's schema: the column `name` and, when the
|
|
@@ -109,8 +135,8 @@ interface R2SqlColumn {
|
|
|
109
135
|
* (`{ success, result, errors }`); we surface the `rows` (the `result` array of
|
|
110
136
|
* column→value records), the inferred/echoed `columns`, and the `rowCount`.
|
|
111
137
|
*
|
|
112
|
-
* `Row` defaults to an open record; supply it (`from
|
|
113
|
-
* `query
|
|
138
|
+
* `Row` defaults to an open record; supply it (`from<MyRow>(…)` /
|
|
139
|
+
* `query<MyRow>(…)`) to get typed result fields — R2 SQL tables live in Iceberg,
|
|
114
140
|
* not `defineSchema`, so the row type is caller-declared rather than inferred.
|
|
115
141
|
*/
|
|
116
142
|
interface R2SqlResult<Row = Record<string, unknown>> {
|
|
@@ -225,11 +251,11 @@ declare class SelectBuilder<Row = Record<string, unknown>> implements Queryable<
|
|
|
225
251
|
fullJoin(table: string, on: Condition): this;
|
|
226
252
|
/** `CROSS JOIN table` (no `ON`). */
|
|
227
253
|
crossJoin(table: string): this;
|
|
228
|
-
/** Add `WHERE` condition(s). Multiple calls (and multiple args) are `AND`-ed. Bind values with the `sql` tag. */
|
|
254
|
+
/** Add `WHERE` condition(s). Multiple calls (and multiple args) are `AND`-ed, each parenthesised. Bind values with the `sql` tag. */
|
|
229
255
|
where(...conditions: Condition[]): this;
|
|
230
256
|
/** `GROUP BY` column(s)/expression(s). */
|
|
231
257
|
groupBy(...columns: (Sql | string)[]): this;
|
|
232
|
-
/** Add `HAVING` condition(s) over aggregates; multiple are `AND`-ed. */
|
|
258
|
+
/** Add `HAVING` condition(s) over aggregates; multiple are `AND`-ed, each parenthesised. */
|
|
233
259
|
having(...conditions: Condition[]): this;
|
|
234
260
|
/**
|
|
235
261
|
* `QUALIFY` — filter on a window function without a subquery, e.g.
|
|
@@ -263,8 +289,11 @@ declare class SelectBuilder<Row = Record<string, unknown>> implements Queryable<
|
|
|
263
289
|
}
|
|
264
290
|
/**
|
|
265
291
|
* Thrown when R2 SQL responds with a non-2xx status, an `success: false`
|
|
266
|
-
* envelope, or an unparseable body; carries the HTTP `status` and
|
|
267
|
-
* for the caller to surface
|
|
292
|
+
* envelope, or an unparseable body; carries the HTTP `status` and a capped body
|
|
293
|
+
* preview for the caller to surface, with the full body on `cause`.
|
|
294
|
+
*
|
|
295
|
+
* The preview is capped because the engine's SQL error text quotes the query
|
|
296
|
+
* back, and `R2_SQL_ERROR` is non-internal — the message reaches the browser.
|
|
268
297
|
*/
|
|
269
298
|
declare class R2SqlError extends LunoraError {
|
|
270
299
|
constructor(status: number, body: string);
|
|
@@ -310,9 +339,9 @@ declare class WindowExpression extends Sql {
|
|
|
310
339
|
gt(value: unknown): Sql;
|
|
311
340
|
/** `expr >= value`. */
|
|
312
341
|
gte(value: unknown): Sql;
|
|
313
|
-
/** `expr
|
|
342
|
+
/** `expr < value`. */
|
|
314
343
|
lt(value: unknown): Sql;
|
|
315
|
-
/** `expr
|
|
344
|
+
/** `expr <= value`. */
|
|
316
345
|
lte(value: unknown): Sql;
|
|
317
346
|
private compare;
|
|
318
347
|
}
|
|
@@ -380,4 +409,19 @@ declare const fn: {
|
|
|
380
409
|
/** `SUM(column) OVER (...)`. */
|
|
381
410
|
sum: (column: Sql | string) => WindowFunction;
|
|
382
411
|
};
|
|
383
|
-
export { type Condition, type OrderTerm, type OverSpec, type QueryExecutor, type Queryable, type R2SqlClient, type R2SqlColumn, type R2SqlConfig, R2SqlError, type R2SqlExplainOptions, type R2SqlResult,
|
|
412
|
+
export { type Condition, type OrderTerm, type OverSpec, type QueryExecutor, type Queryable, type R2SqlClient, type R2SqlColumn, type R2SqlConfig, R2SqlError, type R2SqlExplainOptions, type R2SqlResult,
|
|
413
|
+
/**
|
|
414
|
+
* `@lunora/bindings/r2sql` — typed, chainable R2 SQL for Lunora.
|
|
415
|
+
*
|
|
416
|
+
* Query Cloudflare [R2 SQL](https://developers.cloudflare.com/r2-sql/) — the
|
|
417
|
+
* serverless engine over Apache Iceberg tables in R2 Data Catalog — from a
|
|
418
|
+
* Lunora **action** via `ctx.r2sql`. First-class support for the 2026-06-21
|
|
419
|
+
* features: window functions (`fn.rowNumber().over(...)`), `DISTINCT` /
|
|
420
|
+
* `DISTINCT ON`, `QUALIFY`, and set operations (`.union()/.intersect()/.except()`).
|
|
421
|
+
*
|
|
422
|
+
* R2 SQL is non-deterministic external I/O with no Workers binding, so — like
|
|
423
|
+
* `ctx.sql` (Hyperdrive) — it is wired onto `ActionCtx` only and its reads are
|
|
424
|
+
* not tracked by Lunora live queries (see the `r2sql_outside_action` advisor
|
|
425
|
+
* lint). See the README and `createR2Sql` JSDoc.
|
|
426
|
+
*/
|
|
427
|
+
SelectBuilder, SetOperation, Sql, WindowExpression, WindowFunction, asc, createR2Sql, desc, fn, ident, isSql, joinSql, lit, raw, renderOrderTerm, sql, tableRef, toText };
|
package/dist/r2sql/index.d.ts
CHANGED
|
@@ -18,13 +18,29 @@ declare const isSql: (value: unknown) => value is Sql;
|
|
|
18
18
|
declare const raw: (text: string) => Sql;
|
|
19
19
|
/** Resolve a `string | Sql` to its raw text. A bare string is taken as trusted SQL (callers pass identifiers/fragments here). */
|
|
20
20
|
declare const toText: (value: Sql | string) => string;
|
|
21
|
+
/**
|
|
22
|
+
* Validate a table/namespace/database identifier that will be spliced into R2 SQL
|
|
23
|
+
* text (which has no parameter binding and no identifier quoting we can rely on).
|
|
24
|
+
* Accepts only dotted `\w` segments and throws otherwise, so a client-supplied
|
|
25
|
+
* `describe`/`showTables` argument can't inject SQL. For a genuinely dynamic
|
|
26
|
+
* identifier you built yourself, wrap it with {@link raw}.
|
|
27
|
+
*/
|
|
28
|
+
declare const ident: (name: string) => string;
|
|
29
|
+
/**
|
|
30
|
+
* Validate a table REFERENCE for a `FROM`/`JOIN` position: a dotted identifier
|
|
31
|
+
* plus an optional `[AS] alias`. Broader than {@link ident} (which forbids the
|
|
32
|
+
* alias) but still an allowlist — no whitespace beyond the single alias, no
|
|
33
|
+
* punctuation — so a caller-supplied table string can't inject SQL. Use
|
|
34
|
+
* {@link raw} for anything more dynamic that you built yourself.
|
|
35
|
+
*/
|
|
36
|
+
declare const tableRef: (ref: string) => string;
|
|
21
37
|
/**
|
|
22
38
|
* Render a JS value as an R2 SQL literal:
|
|
23
39
|
*
|
|
24
40
|
* - `null` / `undefined` → `NULL`
|
|
25
41
|
* - `boolean` → `true` / `false`
|
|
26
42
|
* - finite `number` / `bigint` → the numeric text (non-finite throws — `NaN`/`Infinity` have no SQL literal)
|
|
27
|
-
* - `Date` → an RFC3339 string literal (R2 SQL's `timestamp` form)
|
|
43
|
+
* - `Date` → an RFC3339 string literal (R2 SQL's `timestamp` form; an invalid `Date` throws)
|
|
28
44
|
* - `string` → a single-quoted, escaped literal
|
|
29
45
|
* - `Array` → a parenthesised, comma-separated list of literals (for `IN (...)`)
|
|
30
46
|
*
|
|
@@ -93,6 +109,16 @@ interface R2SqlConfig {
|
|
|
93
109
|
* so a query never touches the network.
|
|
94
110
|
*/
|
|
95
111
|
fetch?: typeof globalThis.fetch;
|
|
112
|
+
/**
|
|
113
|
+
* Milliseconds before an in-flight query (the fetch AND its body read) is
|
|
114
|
+
* aborted and surfaced as an `R2SqlError` with status 504. Defaults to
|
|
115
|
+
* 60_000 — analytical scans legitimately run tens of seconds. `undefined`
|
|
116
|
+
* means the default, not unbounded.
|
|
117
|
+
*
|
|
118
|
+
* The deadline is carried by the request's `signal`, so a custom `fetch`
|
|
119
|
+
* (above) that ignores `signal` leaves the query unbounded.
|
|
120
|
+
*/
|
|
121
|
+
timeoutMs?: number;
|
|
96
122
|
}
|
|
97
123
|
/**
|
|
98
124
|
* One column descriptor in a result's schema: the column `name` and, when the
|
|
@@ -109,8 +135,8 @@ interface R2SqlColumn {
|
|
|
109
135
|
* (`{ success, result, errors }`); we surface the `rows` (the `result` array of
|
|
110
136
|
* column→value records), the inferred/echoed `columns`, and the `rowCount`.
|
|
111
137
|
*
|
|
112
|
-
* `Row` defaults to an open record; supply it (`from
|
|
113
|
-
* `query
|
|
138
|
+
* `Row` defaults to an open record; supply it (`from<MyRow>(…)` /
|
|
139
|
+
* `query<MyRow>(…)`) to get typed result fields — R2 SQL tables live in Iceberg,
|
|
114
140
|
* not `defineSchema`, so the row type is caller-declared rather than inferred.
|
|
115
141
|
*/
|
|
116
142
|
interface R2SqlResult<Row = Record<string, unknown>> {
|
|
@@ -225,11 +251,11 @@ declare class SelectBuilder<Row = Record<string, unknown>> implements Queryable<
|
|
|
225
251
|
fullJoin(table: string, on: Condition): this;
|
|
226
252
|
/** `CROSS JOIN table` (no `ON`). */
|
|
227
253
|
crossJoin(table: string): this;
|
|
228
|
-
/** Add `WHERE` condition(s). Multiple calls (and multiple args) are `AND`-ed. Bind values with the `sql` tag. */
|
|
254
|
+
/** Add `WHERE` condition(s). Multiple calls (and multiple args) are `AND`-ed, each parenthesised. Bind values with the `sql` tag. */
|
|
229
255
|
where(...conditions: Condition[]): this;
|
|
230
256
|
/** `GROUP BY` column(s)/expression(s). */
|
|
231
257
|
groupBy(...columns: (Sql | string)[]): this;
|
|
232
|
-
/** Add `HAVING` condition(s) over aggregates; multiple are `AND`-ed. */
|
|
258
|
+
/** Add `HAVING` condition(s) over aggregates; multiple are `AND`-ed, each parenthesised. */
|
|
233
259
|
having(...conditions: Condition[]): this;
|
|
234
260
|
/**
|
|
235
261
|
* `QUALIFY` — filter on a window function without a subquery, e.g.
|
|
@@ -263,8 +289,11 @@ declare class SelectBuilder<Row = Record<string, unknown>> implements Queryable<
|
|
|
263
289
|
}
|
|
264
290
|
/**
|
|
265
291
|
* Thrown when R2 SQL responds with a non-2xx status, an `success: false`
|
|
266
|
-
* envelope, or an unparseable body; carries the HTTP `status` and
|
|
267
|
-
* for the caller to surface
|
|
292
|
+
* envelope, or an unparseable body; carries the HTTP `status` and a capped body
|
|
293
|
+
* preview for the caller to surface, with the full body on `cause`.
|
|
294
|
+
*
|
|
295
|
+
* The preview is capped because the engine's SQL error text quotes the query
|
|
296
|
+
* back, and `R2_SQL_ERROR` is non-internal — the message reaches the browser.
|
|
268
297
|
*/
|
|
269
298
|
declare class R2SqlError extends LunoraError {
|
|
270
299
|
constructor(status: number, body: string);
|
|
@@ -310,9 +339,9 @@ declare class WindowExpression extends Sql {
|
|
|
310
339
|
gt(value: unknown): Sql;
|
|
311
340
|
/** `expr >= value`. */
|
|
312
341
|
gte(value: unknown): Sql;
|
|
313
|
-
/** `expr
|
|
342
|
+
/** `expr < value`. */
|
|
314
343
|
lt(value: unknown): Sql;
|
|
315
|
-
/** `expr
|
|
344
|
+
/** `expr <= value`. */
|
|
316
345
|
lte(value: unknown): Sql;
|
|
317
346
|
private compare;
|
|
318
347
|
}
|
|
@@ -380,4 +409,19 @@ declare const fn: {
|
|
|
380
409
|
/** `SUM(column) OVER (...)`. */
|
|
381
410
|
sum: (column: Sql | string) => WindowFunction;
|
|
382
411
|
};
|
|
383
|
-
export { type Condition, type OrderTerm, type OverSpec, type QueryExecutor, type Queryable, type R2SqlClient, type R2SqlColumn, type R2SqlConfig, R2SqlError, type R2SqlExplainOptions, type R2SqlResult,
|
|
412
|
+
export { type Condition, type OrderTerm, type OverSpec, type QueryExecutor, type Queryable, type R2SqlClient, type R2SqlColumn, type R2SqlConfig, R2SqlError, type R2SqlExplainOptions, type R2SqlResult,
|
|
413
|
+
/**
|
|
414
|
+
* `@lunora/bindings/r2sql` — typed, chainable R2 SQL for Lunora.
|
|
415
|
+
*
|
|
416
|
+
* Query Cloudflare [R2 SQL](https://developers.cloudflare.com/r2-sql/) — the
|
|
417
|
+
* serverless engine over Apache Iceberg tables in R2 Data Catalog — from a
|
|
418
|
+
* Lunora **action** via `ctx.r2sql`. First-class support for the 2026-06-21
|
|
419
|
+
* features: window functions (`fn.rowNumber().over(...)`), `DISTINCT` /
|
|
420
|
+
* `DISTINCT ON`, `QUALIFY`, and set operations (`.union()/.intersect()/.except()`).
|
|
421
|
+
*
|
|
422
|
+
* R2 SQL is non-deterministic external I/O with no Workers binding, so — like
|
|
423
|
+
* `ctx.sql` (Hyperdrive) — it is wired onto `ActionCtx` only and its reads are
|
|
424
|
+
* not tracked by Lunora live queries (see the `r2sql_outside_action` advisor
|
|
425
|
+
* lint). See the README and `createR2Sql` JSDoc.
|
|
426
|
+
*/
|
|
427
|
+
SelectBuilder, SetOperation, Sql, WindowExpression, WindowFunction, asc, createR2Sql, desc, fn, ident, isSql, joinSql, lit, raw, renderOrderTerm, sql, tableRef, toText };
|
package/dist/r2sql/index.mjs
CHANGED
|
@@ -1,7 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { R2SqlError, createR2Sql } from '../packem_shared/R2SqlError-drPKSCZ3.mjs';
|
|
3
|
-
export { asc, desc, renderOrderTerm } from '../packem_shared/asc-DZbQCxh1.mjs';
|
|
4
|
-
export { default as SetOperation } from '../packem_shared/SetOperation-DmPgUL8W.mjs';
|
|
5
|
-
export { Sql, isSql, joinSql, lit, raw, sql, toText } from '../packem_shared/Sql-B3zq2YGx.mjs';
|
|
6
|
-
export { WindowFunction, fn } from '../packem_shared/WindowFunction-DrnuZUF6.mjs';
|
|
7
|
-
export { default as WindowExpression } from '../packem_shared/WindowExpression-BT_uA6g1.mjs';
|
|
1
|
+
import{default as o}from"../packem_shared/SelectBuilder-DJXNSdqC.mjs";import{R2SqlError as l,createR2Sql as f}from"../packem_shared/R2SqlError-ZHgOWClB.mjs";import{asc as d,desc as i,renderOrderTerm as n}from"../packem_shared/asc-DP_WFiAE.mjs";import{default as s}from"../packem_shared/SetOperation-kiI5Wnlm.mjs";import{Sql as m,ident as S,isSql as q,joinSql as c,lit as u,raw as w,sql as R,tableRef as E,toText as O}from"../packem_shared/Sql-BfnxRway.mjs";import{WindowFunction as W,fn as b}from"../packem_shared/WindowFunction-CL4jYy2l.mjs";import{default as B}from"../packem_shared/WindowExpression-VX7EEV3h.mjs";export{l as R2SqlError,o as SelectBuilder,s as SetOperation,m as Sql,B as WindowExpression,W as WindowFunction,d as asc,f as createR2Sql,i as desc,b as fn,S as ident,q as isSql,c as joinSql,u as lit,w as raw,n as renderOrderTerm,R as sql,E as tableRef,O as toText};
|