@lunora/bindings 1.0.0-alpha.49 → 1.0.0-alpha.50

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.
@@ -27,37 +27,6 @@
27
27
  * - `lighter` — foreground and backdrop channels added (brightening).
28
28
  */
29
29
  type ImageCompositeMode = "atop" | "in" | "lighter" | "out" | "over" | "xor";
30
- /**
31
- * One overlay in a {@link TransformOptions.draw} list — the **URL-form** overlay
32
- * (the `cf.image.draw` / `/cdn-cgi/image` shape), where the overlay image is
33
- * referenced by absolute `url`. For the **binding** path use {@link ImageOverlay}
34
- * instead, which carries the overlay bytes as a stream.
35
- *
36
- * `width`/`height` accept either an integer (pixels) or a decimal in `(0, 1]`
37
- * interpreted as a fraction of the base image's corresponding dimension.
38
- */
39
- interface DrawOverlay {
40
- /** Offset, in pixels, from the bottom edge. */
41
- bottom?: number;
42
- /** Blend mode for compositing this overlay onto the image. Default `over`. */
43
- composite?: ImageCompositeMode;
44
- /** Overlay height — pixels (integer) or a `0–1` fraction of the base height. */
45
- height?: number;
46
- /** Offset, in pixels, from the left edge. */
47
- left?: number;
48
- /** Overlay opacity, `0.0` (transparent) – `1.0` (opaque). */
49
- opacity?: number;
50
- /** Tile the overlay across the base image: `true`, or a single axis `"x"`/`"y"`. */
51
- repeat?: "x" | "y" | boolean;
52
- /** Offset, in pixels, from the right edge. */
53
- right?: number;
54
- /** Offset, in pixels, from the top edge. */
55
- top?: number;
56
- /** Absolute URL of the overlay image. */
57
- url: string;
58
- /** Overlay width — pixels (integer) or a `0–1` fraction of the base width. */
59
- width?: number;
60
- }
61
30
  /**
62
31
  * Transform parameters threaded into `binding.input(stream).transform(...)`.
63
32
  * A structural subset of the real `ImageTransform`; the keys here are the
@@ -73,13 +42,6 @@ interface TransformOptions {
73
42
  brightness?: number;
74
43
  /** Contrast multiplier (1 = unchanged). */
75
44
  contrast?: number;
76
- /**
77
- * URL-form overlays composited over the result, in paint order (last entry on
78
- * top). Consumed by the URL builders ({@link DrawOverlay} references each
79
- * overlay by `url`); the binding path applies overlays via the `overlays`
80
- * argument to `Images.transform` instead, so this key is ignored there.
81
- */
82
- draw?: DrawOverlay[];
83
45
  /**
84
46
  * Resize mode. Affects how `width`/`height` are interpreted.
85
47
  *
@@ -157,9 +119,9 @@ type ImageInfoLike = {
157
119
  };
158
120
  /**
159
121
  * Binding-side overlay options for `transformer.draw(image, options)` — the
160
- * blend/position/opacity knobs. Unlike {@link DrawOverlay} there is no `url`
161
- * (the overlay bytes are passed as the stream) and no `width`/`height` (the
162
- * overlay is pre-sized via its own transform); mirrors `ImageDrawOptions`.
122
+ * blend/position/opacity knobs. There is no `url` (the overlay bytes are passed
123
+ * as the stream) and no `width`/`height` (the overlay is pre-sized via its own
124
+ * transform); mirrors `ImageDrawOptions`.
163
125
  */
164
126
  interface ImageDrawOptions {
165
127
  /** Offset, in pixels, from the bottom edge. */
@@ -359,4 +321,4 @@ interface VerifyImageResult {
359
321
  declare const verifySignedImageUrl: (input: string | URL, secret: string, options?: {
360
322
  expectedHost?: string;
361
323
  }) => Promise<VerifyImageResult>;
362
- export { type DrawOverlay, type ImageCompositeMode, type ImageDeliveryUrlOptions, type ImageDrawOptions, type ImageInfoLike, type ImageInput, type ImageOutputFormat, type ImageOverlay, type ImageTransformationResultLike, type ImageTransformerLike, type Images, type ImagesBindingLike, type LunoraImagesOptions, type OutputOptions, type R2ObjectBodyLike, type SignedImageUrlOptions, type TransformOptions, type VerifyImageResult, buildImageDeliveryUrl, buildSignedImageUrl, createImages, parseSignedTransform, verifySignedImageUrl };
324
+ export { type ImageCompositeMode, type ImageDeliveryUrlOptions, type ImageDrawOptions, type ImageInfoLike, type ImageInput, type ImageOutputFormat, type ImageOverlay, type ImageTransformationResultLike, type ImageTransformerLike, type Images, type ImagesBindingLike, type LunoraImagesOptions, type OutputOptions, type R2ObjectBodyLike, type SignedImageUrlOptions, type TransformOptions, type VerifyImageResult, buildImageDeliveryUrl, buildSignedImageUrl, createImages, parseSignedTransform, verifySignedImageUrl };
@@ -27,37 +27,6 @@
27
27
  * - `lighter` — foreground and backdrop channels added (brightening).
28
28
  */
29
29
  type ImageCompositeMode = "atop" | "in" | "lighter" | "out" | "over" | "xor";
30
- /**
31
- * One overlay in a {@link TransformOptions.draw} list — the **URL-form** overlay
32
- * (the `cf.image.draw` / `/cdn-cgi/image` shape), where the overlay image is
33
- * referenced by absolute `url`. For the **binding** path use {@link ImageOverlay}
34
- * instead, which carries the overlay bytes as a stream.
35
- *
36
- * `width`/`height` accept either an integer (pixels) or a decimal in `(0, 1]`
37
- * interpreted as a fraction of the base image's corresponding dimension.
38
- */
39
- interface DrawOverlay {
40
- /** Offset, in pixels, from the bottom edge. */
41
- bottom?: number;
42
- /** Blend mode for compositing this overlay onto the image. Default `over`. */
43
- composite?: ImageCompositeMode;
44
- /** Overlay height — pixels (integer) or a `0–1` fraction of the base height. */
45
- height?: number;
46
- /** Offset, in pixels, from the left edge. */
47
- left?: number;
48
- /** Overlay opacity, `0.0` (transparent) – `1.0` (opaque). */
49
- opacity?: number;
50
- /** Tile the overlay across the base image: `true`, or a single axis `"x"`/`"y"`. */
51
- repeat?: "x" | "y" | boolean;
52
- /** Offset, in pixels, from the right edge. */
53
- right?: number;
54
- /** Offset, in pixels, from the top edge. */
55
- top?: number;
56
- /** Absolute URL of the overlay image. */
57
- url: string;
58
- /** Overlay width — pixels (integer) or a `0–1` fraction of the base width. */
59
- width?: number;
60
- }
61
30
  /**
62
31
  * Transform parameters threaded into `binding.input(stream).transform(...)`.
63
32
  * A structural subset of the real `ImageTransform`; the keys here are the
@@ -73,13 +42,6 @@ interface TransformOptions {
73
42
  brightness?: number;
74
43
  /** Contrast multiplier (1 = unchanged). */
75
44
  contrast?: number;
76
- /**
77
- * URL-form overlays composited over the result, in paint order (last entry on
78
- * top). Consumed by the URL builders ({@link DrawOverlay} references each
79
- * overlay by `url`); the binding path applies overlays via the `overlays`
80
- * argument to `Images.transform` instead, so this key is ignored there.
81
- */
82
- draw?: DrawOverlay[];
83
45
  /**
84
46
  * Resize mode. Affects how `width`/`height` are interpreted.
85
47
  *
@@ -157,9 +119,9 @@ type ImageInfoLike = {
157
119
  };
158
120
  /**
159
121
  * Binding-side overlay options for `transformer.draw(image, options)` — the
160
- * blend/position/opacity knobs. Unlike {@link DrawOverlay} there is no `url`
161
- * (the overlay bytes are passed as the stream) and no `width`/`height` (the
162
- * overlay is pre-sized via its own transform); mirrors `ImageDrawOptions`.
122
+ * blend/position/opacity knobs. There is no `url` (the overlay bytes are passed
123
+ * as the stream) and no `width`/`height` (the overlay is pre-sized via its own
124
+ * transform); mirrors `ImageDrawOptions`.
163
125
  */
164
126
  interface ImageDrawOptions {
165
127
  /** Offset, in pixels, from the bottom edge. */
@@ -359,4 +321,4 @@ interface VerifyImageResult {
359
321
  declare const verifySignedImageUrl: (input: string | URL, secret: string, options?: {
360
322
  expectedHost?: string;
361
323
  }) => Promise<VerifyImageResult>;
362
- export { type DrawOverlay, type ImageCompositeMode, type ImageDeliveryUrlOptions, type ImageDrawOptions, type ImageInfoLike, type ImageInput, type ImageOutputFormat, type ImageOverlay, type ImageTransformationResultLike, type ImageTransformerLike, type Images, type ImagesBindingLike, type LunoraImagesOptions, type OutputOptions, type R2ObjectBodyLike, type SignedImageUrlOptions, type TransformOptions, type VerifyImageResult, buildImageDeliveryUrl, buildSignedImageUrl, createImages, parseSignedTransform, verifySignedImageUrl };
324
+ export { type ImageCompositeMode, type ImageDeliveryUrlOptions, type ImageDrawOptions, type ImageInfoLike, type ImageInput, type ImageOutputFormat, type ImageOverlay, type ImageTransformationResultLike, type ImageTransformerLike, type Images, type ImagesBindingLike, type LunoraImagesOptions, type OutputOptions, type R2ObjectBodyLike, type SignedImageUrlOptions, type TransformOptions, type VerifyImageResult, buildImageDeliveryUrl, buildSignedImageUrl, createImages, parseSignedTransform, verifySignedImageUrl };
@@ -1 +1 @@
1
- import{createImages as m}from"../packem_shared/createImages-CHgMZP4g.mjs";import{buildImageDeliveryUrl as g}from"../packem_shared/buildImageDeliveryUrl-Brqs-dcZ.mjs";import{buildSignedImageUrl as o,parseSignedTransform as l,verifySignedImageUrl as d}from"../packem_shared/buildSignedImageUrl-C1b76MYf.mjs";export{g as buildImageDeliveryUrl,o as buildSignedImageUrl,m as createImages,l as parseSignedTransform,d as verifySignedImageUrl};
1
+ import{createImages as m}from"../packem_shared/createImages-D7JExfqF.mjs";import{buildImageDeliveryUrl as g}from"../packem_shared/buildImageDeliveryUrl-Brqs-dcZ.mjs";import{buildSignedImageUrl as o,parseSignedTransform as l,verifySignedImageUrl as d}from"../packem_shared/buildSignedImageUrl-BV-iSJKA.mjs";export{g as buildImageDeliveryUrl,o as buildSignedImageUrl,m as createImages,l as parseSignedTransform,d as verifySignedImageUrl};
@@ -1 +1 @@
1
- import{LunoraError as f}from"@lunora/errors";import{c as b}from"./cap-error-body-YBKO32BF.mjs";import R from"./SelectBuilder-Dnqem9T0.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};
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};
@@ -1,4 +1,4 @@
1
- const S=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 S(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",draw:"json",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`)}},w=(e,t,r,n)=>`${e.toLowerCase()}
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
2
  ${t}
3
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,w(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(A=>decodeURIComponent(A)).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,w(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};
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
+ 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 a}from"@lunora/errors";const u=50,m=10,x=b=>{const{embedders:n,indexes:s,registry:g}=b,i=async()=>Promise.all(g.map(async e=>{const t=s[e.name];if(t?.describe===void 0)return{...e};try{const r=await t.describe();return{...e,dimensions:e.dimensions??r.dimensions,processedUpToMutation:r.processedUpToMutation,vectorsCount:r.vectorsCount}}catch{return{...e}}}));return n!==void 0&&Object.keys(n).length>0?{listIndexes:i,queryIndex:async({name:e,text:t,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=n[e];if(!Object.hasOwn(n,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(t);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{x as createVectorAdminIntrospector};
@@ -235,11 +235,11 @@ declare class SelectBuilder<Row = Record<string, unknown>> implements Queryable<
235
235
  fullJoin(table: string, on: Condition): this;
236
236
  /** `CROSS JOIN table` (no `ON`). */
237
237
  crossJoin(table: string): this;
238
- /** Add `WHERE` condition(s). Multiple calls (and multiple args) are `AND`-ed. Bind values with the `sql` tag. */
238
+ /** Add `WHERE` condition(s). Multiple calls (and multiple args) are `AND`-ed, each parenthesised. Bind values with the `sql` tag. */
239
239
  where(...conditions: Condition[]): this;
240
240
  /** `GROUP BY` column(s)/expression(s). */
241
241
  groupBy(...columns: (Sql | string)[]): this;
242
- /** Add `HAVING` condition(s) over aggregates; multiple are `AND`-ed. */
242
+ /** Add `HAVING` condition(s) over aggregates; multiple are `AND`-ed, each parenthesised. */
243
243
  having(...conditions: Condition[]): this;
244
244
  /**
245
245
  * `QUALIFY` — filter on a window function without a subquery, e.g.
@@ -235,11 +235,11 @@ declare class SelectBuilder<Row = Record<string, unknown>> implements Queryable<
235
235
  fullJoin(table: string, on: Condition): this;
236
236
  /** `CROSS JOIN table` (no `ON`). */
237
237
  crossJoin(table: string): this;
238
- /** Add `WHERE` condition(s). Multiple calls (and multiple args) are `AND`-ed. Bind values with the `sql` tag. */
238
+ /** Add `WHERE` condition(s). Multiple calls (and multiple args) are `AND`-ed, each parenthesised. Bind values with the `sql` tag. */
239
239
  where(...conditions: Condition[]): this;
240
240
  /** `GROUP BY` column(s)/expression(s). */
241
241
  groupBy(...columns: (Sql | string)[]): this;
242
- /** Add `HAVING` condition(s) over aggregates; multiple are `AND`-ed. */
242
+ /** Add `HAVING` condition(s) over aggregates; multiple are `AND`-ed, each parenthesised. */
243
243
  having(...conditions: Condition[]): this;
244
244
  /**
245
245
  * `QUALIFY` — filter on a window function without a subquery, e.g.
@@ -1 +1 @@
1
- import{default as o}from"../packem_shared/SelectBuilder-Dnqem9T0.mjs";import{R2SqlError as l,createR2Sql as f}from"../packem_shared/R2SqlError-utivPDyt.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,isSql as S,joinSql as q,lit as c,raw as u,sql as w,toText as E}from"../packem_shared/Sql-BfnxRway.mjs";import{WindowFunction as R,fn as T}from"../packem_shared/WindowFunction-CL4jYy2l.mjs";import{default as j}from"../packem_shared/WindowExpression-VX7EEV3h.mjs";export{l as R2SqlError,o as SelectBuilder,s as SetOperation,m as Sql,j as WindowExpression,R as WindowFunction,d as asc,f as createR2Sql,i as desc,T as fn,S as isSql,q as joinSql,c as lit,u as raw,n as renderOrderTerm,w as sql,E as toText};
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,isSql as S,joinSql as q,lit as c,raw as u,sql as w,toText as E}from"../packem_shared/Sql-BfnxRway.mjs";import{WindowFunction as R,fn as T}from"../packem_shared/WindowFunction-CL4jYy2l.mjs";import{default as j}from"../packem_shared/WindowExpression-VX7EEV3h.mjs";export{l as R2SqlError,o as SelectBuilder,s as SetOperation,m as Sql,j as WindowExpression,R as WindowFunction,d as asc,f as createR2Sql,i as desc,T as fn,S as isSql,q as joinSql,c as lit,u as raw,n as renderOrderTerm,w as sql,E as toText};
@@ -1 +1 @@
1
- import{createContextVectors as t,createVectorSyncHook as o}from"../packem_shared/createContextVectors-Bk6ZVCqQ.mjs";import{createVectorAdminIntrospector as a}from"../packem_shared/createVectorAdminIntrospector-DrsigTJs.mjs";import{default as m}from"../packem_shared/createVectors-DirhBYpw.mjs";export{t as createContextVectors,a as createVectorAdminIntrospector,o as createVectorSyncHook,m as createVectors};
1
+ import{createContextVectors as t,createVectorSyncHook as o}from"../packem_shared/createContextVectors-Bk6ZVCqQ.mjs";import{createVectorAdminIntrospector as a}from"../packem_shared/createVectorAdminIntrospector-1CS6sIlR.mjs";import{default as m}from"../packem_shared/createVectors-DirhBYpw.mjs";export{t as createContextVectors,a as createVectorAdminIntrospector,o as createVectorSyncHook,m as createVectors};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/bindings",
3
- "version": "1.0.0-alpha.49",
3
+ "version": "1.0.0-alpha.50",
4
4
  "description": "Lightweight Cloudflare binding helpers for Lunora — ctx.kv, ctx.images, ctx.analytics, ctx.pipelines, ctx.vectors, ctx.r2sql — one install, per-binding subpaths",
5
5
  "keywords": [
6
6
  "analytics",
@@ -64,7 +64,7 @@
64
64
  "access": "public"
65
65
  },
66
66
  "dependencies": {
67
- "@lunora/errors": "1.0.0-alpha.31",
67
+ "@lunora/errors": "1.0.0-alpha.32",
68
68
  "@lunora/platform": "1.0.0-alpha.26"
69
69
  },
70
70
  "engines": {
@@ -1 +0,0 @@
1
- import{renderOrderTerm as o}from"./asc-DP_WFiAE.mjs";import h from"./SetOperation-kiI5Wnlm.mjs";import{tableRef as s,toText as e,assertLimit as u,lit as l}from"./Sql-BfnxRway.mjs";const n={cross:"CROSS JOIN",full:"FULL OUTER JOIN",inner:"INNER JOIN",left:"LEFT JOIN",right:"RIGHT JOIN"};class I{exec;table;selectItems=[];distinctFlag=!1;distinctOnItems=[];joins=[];whereConditions=[];groupByItems=[];havingConditions=[];qualifyCondition;orderByItems=[];limitValue;constructor(t,i){this.exec=t,this.table=s(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=>o(i))),this}limit(t){return u(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?`${n[i.kind]} ${i.table}`:`${n[i.kind]} ${i.table} ON ${e(i.on)}`);return this.whereConditions.length>0&&t.push(`WHERE ${this.whereConditions.join(" AND ")}`),this.groupByItems.length>0&&t.push(`GROUP BY ${this.groupByItems.join(", ")}`),this.havingConditions.length>0&&t.push(`HAVING ${this.havingConditions.join(" AND ")}`),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 ${l(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,r){return this.joins.push({kind:t,on:r,table:s(i)}),this}setOperation(t,i){return new h(this.exec,[{query:this},{operator:t,query:i}])}}export{I as default};
@@ -1 +0,0 @@
1
- import{LunoraError as d}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),i=e=>{if(e instanceof ReadableStream)return e;if(O(e)){if(e.body===null)throw new d("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 t=e instanceof Uint8Array?e:new Uint8Array(e);return new ReadableStream({start(n){n.enqueue(t),n.close()}})},f=(e,t)=>{if(e===void 0)return{};const n=r=>{if(!Number.isFinite(r)||r<=0)throw new TypeError("@lunora/bindings/images: width/height must be a positive finite number");return Math.min(Math.floor(r),t)},o={...e};return delete o.draw,{...o,...e.width===void 0?{}:{width:n(e.width)},...e.height===void 0?{}:{height:n(e.height)}}},v=e=>{const{image:t,transform:n,...o}=e;return{drawOptions:o,image:t,transform:n}},U=e=>{const t=e?.format??A;if(!m.has(t))throw new d("INTERNAL",`@lunora/bindings/images: unsupported output format "${t}" (allowed: ${[...m].join(", ")})`);return{...e,format:t}},p=e=>{const{binding:t}=e,n=e.maxDimension??T;return{info:async o=>t.info(i(o)),transform:async(o,r,g,b)=>{const u=f(r,n),l=U(g);let a=t.input(i(o)).transform(u);for(const w of b??[]){const{drawOptions:y,image:s,transform:c}=v(w),h=c===void 0?i(s):t.input(i(s)).transform(f(c,n));a=a.draw(h,y)}return a.output(l)}}};export{p as createImages};
@@ -1 +0,0 @@
1
- import{LunoraError as a}from"@lunora/errors";const m=20,p=10,f=u=>{const{embedders:r,indexes:n,registry:b}=u,i=async()=>Promise.all(b.map(async e=>{const s=n[e.name];if(s?.describe===void 0)return{...e};try{const t=await s.describe();return{...e,dimensions:e.dimensions??t.dimensions,processedUpToMutation:t.processedUpToMutation,vectorsCount:t.vectorsCount}}catch{return{...e}}}));return r!==void 0&&Object.keys(r).length>0?{listIndexes:i,queryIndex:async({name:e,text:s,topK:t})=>{const d=n[e];if(!Object.hasOwn(n,e)||d===void 0)throw new a("INTERNAL",`@lunora/bindings/vectors: no Vectorize binding registered for index "${e}"`);const c=r[e];if(!Object.hasOwn(r,e)||c===void 0)throw new a("INTERNAL",`@lunora/bindings/vectors: no embedder registered for index "${e}" — it lists read-only`);const l=await c(s);return{matches:(await d.query(l,{returnMetadata:"all",topK:Math.min(t??p,m)})).matches.map(o=>({id:o.id,metadata:o.metadata,score:o.score}))}}}:{listIndexes:i}};export{f as createVectorAdminIntrospector};