@lunora/bindings 1.0.0-alpha.6 → 1.0.0-alpha.60
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 +81 -85
- package/dist/analytics/index.d.ts +81 -85
- package/dist/analytics/index.mjs +1 -2
- package/dist/images/index.d.mts +159 -174
- package/dist/images/index.d.ts +159 -174
- package/dist/images/index.mjs +1 -3
- package/dist/kv/index.d.mts +74 -151
- package/dist/kv/index.d.ts +74 -151
- 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-BcfM30uc.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 +24 -24
- package/dist/pipelines/index.d.ts +24 -24
- package/dist/pipelines/index.mjs +1 -1
- package/dist/r2sql/index.d.mts +169 -125
- package/dist/r2sql/index.d.ts +169 -125
- package/dist/r2sql/index.mjs +1 -7
- package/dist/vectors/index.d.mts +187 -134
- package/dist/vectors/index.d.ts +187 -134
- 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-Boygg3S0.mjs +0 -65
- package/dist/packem_shared/SelectBuilder-DHaXZwn_.mjs +0 -167
- package/dist/packem_shared/SetOperation-RDHcxccj.mjs +0 -80
- package/dist/packem_shared/Sql-DceGtcUd.mjs +0 -68
- package/dist/packem_shared/WindowExpression-Cg9s2xcr.mjs +0 -44
- package/dist/packem_shared/WindowFunction-DA3pGC3N.mjs +0 -82
- package/dist/packem_shared/asc-Cur-xO8v.mjs +0 -16
- package/dist/packem_shared/buildImageDeliveryUrl-B6_QU91n.mjs +0 -33
- package/dist/packem_shared/buildSignedImageUrl-6iibA9v1.mjs +0 -113
- package/dist/packem_shared/concurrent-Dj5sOibv.mjs +0 -23
- package/dist/packem_shared/createAnalytics-CEEI69o9.mjs +0 -57
- package/dist/packem_shared/createContextVectors-BSizpmu5.mjs +0 -140
- package/dist/packem_shared/createImages-BzRnsz3H.mjs +0 -85
- package/dist/packem_shared/createKv-7lNrS1W2.mjs +0 -143
- package/dist/packem_shared/createKvIntrospector-CrAgQp1w.mjs +0 -77
- package/dist/packem_shared/createPipelines-CfyJ6VGu.mjs +0 -10
- package/dist/packem_shared/createVectorAdminIntrospector-C-qTDWA1.mjs +0 -53
- package/dist/packem_shared/createVectors-DqxgEPQb.mjs +0 -95
|
@@ -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{c as x,U as I}from"./concurrent-vRmSvRpF.mjs";const B=(s,c)=>{if(!c.includes("."))return s[c];let n=s;for(const d of c.split(".")){if(n===null||typeof n!="object"||Array.isArray(n))return;n=n[d]}return n},C=(s,c)=>{const n=c?.namespace,d=new Set(c?.shardedIndexNames),l=(t,a)=>{if(a!==void 0)return a;if(d.has(t)){if(n!==void 0)return n;throw new Error(`@lunora/bindings/vectors: index "${t}" 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.`)}},o=async(t,a)=>{await s.upsert(t,{embed:a.embed,id:a.id,input:a.input,metadata:a.metadata,namespace:l(t,a.namespace)})},h=async(t,a,i)=>{const r=await s.getByIds(t,a);return i===void 0?r:r.filter(m=>m.namespace===i)};return{deleteByIds:async(t,a,i)=>{const r=l(t,i);if(r===void 0){await s.deleteByIds(t,a);return}const m=await h(t,a,r);m.length!==0&&await s.deleteByIds(t,m.map(u=>u.id))},getByIds:async(t,a,i)=>{const r=l(t,i);return(await h(t,a,r)).map(u=>({id:u.id,metadata:u.metadata,namespace:u.namespace,values:[...u.values]}))},query:async(t,a)=>{const i=await s.query(t,{embed:a.embed,filter:a.filter,input:a.input,namespace:l(t,a.namespace),returnMetadata:a.returnMetadata??"indexed",topK:a.topK,vector:a.vector});return{count:i.count,matches:i.matches.map(r=>({id:r.id,metadata:r.metadata,score:r.score}))}},upsert:o,upsertNow:o}},v=new Set,w=s=>{v.has(s)||(v.add(s),console.warn(`[@lunora/bindings/vectors] index "${s}" 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 }.`))},S=(s,c)=>{const n={};for(const d of c)d in s&&(n[d]=s[d]);return n},E=s=>{const{allowSharedNamespace:c,namespace:n,schema:d,vectors:l}=s;return async o=>{const t=d.tables[o.table]?.vectorIndexes??[],a=Object.entries(d.vectorIndexes).filter(([,e])=>e.table===o.table);if(t.length===0&&a.length===0)return;const i=[...t.map(e=>e.name),...a.map(([e])=>e)];if(o.op==="delete"){await Promise.all(i.map(e=>l.deleteByIds(e,[o.id])));return}const r=o.doc;if(!r)return;const m=t.map(e=>({index:e,value:B(r,e.field)})),u=m.filter(e=>e.value!==void 0&&e.value!==null),y=m.filter(e=>e.value===void 0||e.value===null);for(const{index:e,value:p}of u)if(typeof p!="string")throw new TypeError(`@lunora/bindings/vectors: inline index "${e.name}" expects a string source at "${e.field}" on table "${o.table}" (got ${typeof p}); use a standalone defineVectorIndex with a select() to derive text from non-string columns`);const f=[],b=[...y.map(e=>async()=>{await l.deleteByIds(e.index.name,[o.id])}),...u.map(e=>async()=>{!c&&n===void 0&&w(e.index.name),await l.upsert(e.index.name,{embed:e.index.embed,id:o.id,input:e.value,metadata:e.index.metadata?S(r,e.index.metadata):void 0,namespace:n}),f.push(e.index.name)}),...a.map(([e,p])=>async()=>{!c&&n===void 0&&w(e),await l.upsert(e,{embed:p.embed,id:o.id,input:p.select(r),metadata:p.metadata?.(r),namespace:n}),f.push(e)})];try{await x(b,I,async e=>e())}catch(e){const p=o.op==="insert"?i:f;throw await Promise.allSettled(p.map(g=>l.deleteByIds(g,[o.id]))),e}}};export{C as createContextVectors,E as createVectorSyncHook};
|
|
@@ -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};
|
|
@@ -1,40 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Structural types for the Cloudflare Pipelines write path (R2-backed streaming
|
|
3
|
-
* ingestion). Pipelines is the other "emit data to a sink" surface alongside
|
|
4
|
-
* Analytics Engine — telemetry/events out, no in-handler read-back. The binding
|
|
5
|
-
* is mirrored structurally (`*Like`) so a plain-object fake satisfies it in unit
|
|
6
|
-
* tests, like `@lunora/bindings/analytics`'s `AnalyticsEngineDatasetLike`.
|
|
7
|
-
*/
|
|
2
|
+
* Structural types for the Cloudflare Pipelines write path (R2-backed streaming
|
|
3
|
+
* ingestion). Pipelines is the other "emit data to a sink" surface alongside
|
|
4
|
+
* Analytics Engine — telemetry/events out, no in-handler read-back. The binding
|
|
5
|
+
* is mirrored structurally (`*Like`) so a plain-object fake satisfies it in unit
|
|
6
|
+
* tests, like `@lunora/bindings/analytics`'s `AnalyticsEngineDatasetLike`.
|
|
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
|
|
12
|
-
* real binding's `send` takes an array of records and resolves once accepted.
|
|
13
|
-
*/
|
|
11
|
+
* Minimal structural projection of workers-types' `Pipeline<T>` binding. The
|
|
12
|
+
* real binding's `send` takes an array of records and resolves once accepted.
|
|
13
|
+
*/
|
|
14
14
|
interface PipelineBindingLike<T extends PipelineRecord = PipelineRecord> {
|
|
15
15
|
send: (records: T[]) => Promise<void>;
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
|
-
* The write-side client bound to `ctx.pipelines` (the generated context imports
|
|
19
|
-
* this exact type as `import("@lunora/bindings/pipelines").PipelineClient`).
|
|
20
|
-
* Ingestion is durable, batched, and fire-and-forget — never read a record back
|
|
21
|
-
* in-handler.
|
|
22
|
-
*/
|
|
18
|
+
* The write-side client bound to `ctx.pipelines` (the generated context imports
|
|
19
|
+
* this exact type as `import("@lunora/bindings/pipelines").PipelineClient`).
|
|
20
|
+
* Ingestion is durable, batched, and fire-and-forget — never read a record back
|
|
21
|
+
* in-handler.
|
|
22
|
+
*/
|
|
23
23
|
interface PipelineClient<T extends PipelineRecord = PipelineRecord> {
|
|
24
24
|
/** Ingest one record or an array of records into the R2-backed sink. */
|
|
25
25
|
send: (records: T | T[]) => Promise<void>;
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
28
|
-
* Wrap a Cloudflare Pipelines binding in the write-side {@link PipelineClient}
|
|
29
|
-
* bound to `ctx.pipelines`. The binding is `env.PIPELINES` (the `pipelines`
|
|
30
|
-
* binding the config layer recognizes; the remote pipeline name is minted with
|
|
31
|
-
* `wrangler pipelines create`).
|
|
32
|
-
*
|
|
33
|
-
* Ingestion is durable and batched: `send` accepts one record or an array and
|
|
34
|
-
* resolves once Cloudflare has accepted them for delivery to the R2-backed sink.
|
|
35
|
-
* There is no in-handler read-back — this is a fire-and-forget egress path, so
|
|
36
|
-
* it belongs on ActionCtx only (external I/O), mirroring `ctx.images`.
|
|
37
|
-
*/
|
|
28
|
+
* Wrap a Cloudflare Pipelines binding in the write-side {@link PipelineClient}
|
|
29
|
+
* bound to `ctx.pipelines`. The binding is `env.PIPELINES` (the `pipelines`
|
|
30
|
+
* binding the config layer recognizes; the remote pipeline name is minted with
|
|
31
|
+
* `wrangler pipelines create`).
|
|
32
|
+
*
|
|
33
|
+
* Ingestion is durable and batched: `send` accepts one record or an array and
|
|
34
|
+
* resolves once Cloudflare has accepted them for delivery to the R2-backed sink.
|
|
35
|
+
* There is no in-handler read-back — this is a fire-and-forget egress path, so
|
|
36
|
+
* it belongs on ActionCtx only (external I/O), mirroring `ctx.images`.
|
|
37
|
+
*/
|
|
38
38
|
declare const createPipelines: <T extends PipelineRecord = PipelineRecord>(options: {
|
|
39
39
|
binding: PipelineBindingLike<T>;
|
|
40
40
|
}) => PipelineClient<T>;
|
|
@@ -1,40 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Structural types for the Cloudflare Pipelines write path (R2-backed streaming
|
|
3
|
-
* ingestion). Pipelines is the other "emit data to a sink" surface alongside
|
|
4
|
-
* Analytics Engine — telemetry/events out, no in-handler read-back. The binding
|
|
5
|
-
* is mirrored structurally (`*Like`) so a plain-object fake satisfies it in unit
|
|
6
|
-
* tests, like `@lunora/bindings/analytics`'s `AnalyticsEngineDatasetLike`.
|
|
7
|
-
*/
|
|
2
|
+
* Structural types for the Cloudflare Pipelines write path (R2-backed streaming
|
|
3
|
+
* ingestion). Pipelines is the other "emit data to a sink" surface alongside
|
|
4
|
+
* Analytics Engine — telemetry/events out, no in-handler read-back. The binding
|
|
5
|
+
* is mirrored structurally (`*Like`) so a plain-object fake satisfies it in unit
|
|
6
|
+
* tests, like `@lunora/bindings/analytics`'s `AnalyticsEngineDatasetLike`.
|
|
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
|
|
12
|
-
* real binding's `send` takes an array of records and resolves once accepted.
|
|
13
|
-
*/
|
|
11
|
+
* Minimal structural projection of workers-types' `Pipeline<T>` binding. The
|
|
12
|
+
* real binding's `send` takes an array of records and resolves once accepted.
|
|
13
|
+
*/
|
|
14
14
|
interface PipelineBindingLike<T extends PipelineRecord = PipelineRecord> {
|
|
15
15
|
send: (records: T[]) => Promise<void>;
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
|
-
* The write-side client bound to `ctx.pipelines` (the generated context imports
|
|
19
|
-
* this exact type as `import("@lunora/bindings/pipelines").PipelineClient`).
|
|
20
|
-
* Ingestion is durable, batched, and fire-and-forget — never read a record back
|
|
21
|
-
* in-handler.
|
|
22
|
-
*/
|
|
18
|
+
* The write-side client bound to `ctx.pipelines` (the generated context imports
|
|
19
|
+
* this exact type as `import("@lunora/bindings/pipelines").PipelineClient`).
|
|
20
|
+
* Ingestion is durable, batched, and fire-and-forget — never read a record back
|
|
21
|
+
* in-handler.
|
|
22
|
+
*/
|
|
23
23
|
interface PipelineClient<T extends PipelineRecord = PipelineRecord> {
|
|
24
24
|
/** Ingest one record or an array of records into the R2-backed sink. */
|
|
25
25
|
send: (records: T | T[]) => Promise<void>;
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
28
|
-
* Wrap a Cloudflare Pipelines binding in the write-side {@link PipelineClient}
|
|
29
|
-
* bound to `ctx.pipelines`. The binding is `env.PIPELINES` (the `pipelines`
|
|
30
|
-
* binding the config layer recognizes; the remote pipeline name is minted with
|
|
31
|
-
* `wrangler pipelines create`).
|
|
32
|
-
*
|
|
33
|
-
* Ingestion is durable and batched: `send` accepts one record or an array and
|
|
34
|
-
* resolves once Cloudflare has accepted them for delivery to the R2-backed sink.
|
|
35
|
-
* There is no in-handler read-back — this is a fire-and-forget egress path, so
|
|
36
|
-
* it belongs on ActionCtx only (external I/O), mirroring `ctx.images`.
|
|
37
|
-
*/
|
|
28
|
+
* Wrap a Cloudflare Pipelines binding in the write-side {@link PipelineClient}
|
|
29
|
+
* bound to `ctx.pipelines`. The binding is `env.PIPELINES` (the `pipelines`
|
|
30
|
+
* binding the config layer recognizes; the remote pipeline name is minted with
|
|
31
|
+
* `wrangler pipelines create`).
|
|
32
|
+
*
|
|
33
|
+
* Ingestion is durable and batched: `send` accepts one record or an array and
|
|
34
|
+
* resolves once Cloudflare has accepted them for delivery to the R2-backed sink.
|
|
35
|
+
* There is no in-handler read-back — this is a fire-and-forget egress path, so
|
|
36
|
+
* it belongs on ActionCtx only (external I/O), mirroring `ctx.images`.
|
|
37
|
+
*/
|
|
38
38
|
declare const createPipelines: <T extends PipelineRecord = PipelineRecord>(options: {
|
|
39
39
|
binding: PipelineBindingLike<T>;
|
|
40
40
|
}) => PipelineClient<T>;
|
package/dist/pipelines/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import{createPipelines as i}from"../packem_shared/createPipelines-CIvqrc7E.mjs";export{i as createPipelines};
|