@lunora/bindings 1.0.0-alpha.33 → 1.0.0-alpha.35

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.
@@ -91,6 +91,16 @@ interface AnalyticsSqlConfig {
91
91
  * so the SQL path never touches the network.
92
92
  */
93
93
  fetch?: typeof globalThis.fetch;
94
+ /**
95
+ * Milliseconds before an in-flight query (the fetch AND its body read) is
96
+ * aborted and surfaced as an `AnalyticsSqlError` with status 504. Defaults
97
+ * to 60_000 — analytical scans legitimately run tens of seconds.
98
+ * `undefined` means the default, not unbounded.
99
+ *
100
+ * The deadline is carried by the request's `signal`, so a custom `fetch`
101
+ * (above) that ignores `signal` leaves the query unbounded.
102
+ */
103
+ timeoutMs?: number;
94
104
  }
95
105
  /**
96
106
  * One column descriptor in a SQL-API response's `meta` array: the column `name`
@@ -91,6 +91,16 @@ interface AnalyticsSqlConfig {
91
91
  * so the SQL path never touches the network.
92
92
  */
93
93
  fetch?: typeof globalThis.fetch;
94
+ /**
95
+ * Milliseconds before an in-flight query (the fetch AND its body read) is
96
+ * aborted and surfaced as an `AnalyticsSqlError` with status 504. Defaults
97
+ * to 60_000 — analytical scans legitimately run tens of seconds.
98
+ * `undefined` means the default, not unbounded.
99
+ *
100
+ * The deadline is carried by the request's `signal`, so a custom `fetch`
101
+ * (above) that ignores `signal` leaves the query unbounded.
102
+ */
103
+ timeoutMs?: number;
94
104
  }
95
105
  /**
96
106
  * One column descriptor in a SQL-API response's `meta` array: the column `name`
@@ -1 +1 @@
1
- import{createAnalytics as e}from"../packem_shared/createAnalytics-BXTNc57d.mjs";import{AnalyticsSqlError as a,createAnalyticsSqlClient as c}from"../packem_shared/AnalyticsSqlError-cZQ6kiae.mjs";export{a as AnalyticsSqlError,e as createAnalytics,c as createAnalyticsSqlClient};
1
+ import{createAnalytics as e}from"../packem_shared/createAnalytics-BXTNc57d.mjs";import{AnalyticsSqlError as a,createAnalyticsSqlClient as c}from"../packem_shared/AnalyticsSqlError-BEKML_Dg.mjs";export{a as AnalyticsSqlError,e as createAnalytics,c as createAnalyticsSqlClient};
@@ -288,6 +288,21 @@ interface ImageDeliveryUrlOptions {
288
288
  * Pure and deterministic — usable from any handler.
289
289
  */
290
290
  declare const buildImageDeliveryUrl: (options: ImageDeliveryUrlOptions) => string;
291
+ /**
292
+ * Parse a verified transform string (the `t` query value handed back by
293
+ * {@link verifySignedImageUrl}) back into the {@link TransformOptions} it was
294
+ * serialized from, so the Worker can apply exactly the signed transform via
295
+ * `ctx.images.transform(...)` without hand-writing the inverse encoding.
296
+ *
297
+ * The exact inverse of `serializeTransform` above — the two MUST evolve
298
+ * together (the round-trip test in
299
+ * `__tests__/images/signed-delivery-url.test.ts` pins the pairing). Throws a
300
+ * `TypeError` on an unknown key or an uncoercible value: the input is meant to
301
+ * be a string whose HMAC already verified, so a parse failure means
302
+ * encoder/decoder drift in the library, never user input — fail loud rather
303
+ * than silently un-binding the transform the signature protects.
304
+ */
305
+ declare const parseSignedTransform: (t: string) => TransformOptions;
291
306
  interface SignedImageUrlOptions {
292
307
  /** Delivery / Worker origin the signed URL points at (e.g. `https://cdn.acme.test`). */
293
308
  baseUrl: string;
@@ -324,6 +339,15 @@ interface VerifyImageResult {
324
339
  reason?: "bad_signature" | "expired" | "malformed";
325
340
  /** The raw, verified transform string (the `t` query value), when present. */
326
341
  transform?: string;
342
+ /**
343
+ * The verified transform decoded back into the options object to pass to
344
+ * `ctx.images.transform(...)` — {@link parseSignedTransform} applied to
345
+ * `transform`. Left `undefined` when `transform` is absent, and also when a
346
+ * genuinely signed transform carries a key this build does not know (an
347
+ * old URL minted before a key was renamed): the request stays `valid`, the
348
+ * raw `transform` is still returned, and the caller decides.
349
+ */
350
+ transformOptions?: TransformOptions;
327
351
  valid: boolean;
328
352
  }
329
353
  /**
@@ -335,4 +359,4 @@ interface VerifyImageResult {
335
359
  declare const verifySignedImageUrl: (input: string | URL, secret: string, options?: {
336
360
  expectedHost?: string;
337
361
  }) => Promise<VerifyImageResult>;
338
- 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, verifySignedImageUrl };
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 };
@@ -288,6 +288,21 @@ interface ImageDeliveryUrlOptions {
288
288
  * Pure and deterministic — usable from any handler.
289
289
  */
290
290
  declare const buildImageDeliveryUrl: (options: ImageDeliveryUrlOptions) => string;
291
+ /**
292
+ * Parse a verified transform string (the `t` query value handed back by
293
+ * {@link verifySignedImageUrl}) back into the {@link TransformOptions} it was
294
+ * serialized from, so the Worker can apply exactly the signed transform via
295
+ * `ctx.images.transform(...)` without hand-writing the inverse encoding.
296
+ *
297
+ * The exact inverse of `serializeTransform` above — the two MUST evolve
298
+ * together (the round-trip test in
299
+ * `__tests__/images/signed-delivery-url.test.ts` pins the pairing). Throws a
300
+ * `TypeError` on an unknown key or an uncoercible value: the input is meant to
301
+ * be a string whose HMAC already verified, so a parse failure means
302
+ * encoder/decoder drift in the library, never user input — fail loud rather
303
+ * than silently un-binding the transform the signature protects.
304
+ */
305
+ declare const parseSignedTransform: (t: string) => TransformOptions;
291
306
  interface SignedImageUrlOptions {
292
307
  /** Delivery / Worker origin the signed URL points at (e.g. `https://cdn.acme.test`). */
293
308
  baseUrl: string;
@@ -324,6 +339,15 @@ interface VerifyImageResult {
324
339
  reason?: "bad_signature" | "expired" | "malformed";
325
340
  /** The raw, verified transform string (the `t` query value), when present. */
326
341
  transform?: string;
342
+ /**
343
+ * The verified transform decoded back into the options object to pass to
344
+ * `ctx.images.transform(...)` — {@link parseSignedTransform} applied to
345
+ * `transform`. Left `undefined` when `transform` is absent, and also when a
346
+ * genuinely signed transform carries a key this build does not know (an
347
+ * old URL minted before a key was renamed): the request stays `valid`, the
348
+ * raw `transform` is still returned, and the caller decides.
349
+ */
350
+ transformOptions?: TransformOptions;
327
351
  valid: boolean;
328
352
  }
329
353
  /**
@@ -335,4 +359,4 @@ interface VerifyImageResult {
335
359
  declare const verifySignedImageUrl: (input: string | URL, secret: string, options?: {
336
360
  expectedHost?: string;
337
361
  }) => Promise<VerifyImageResult>;
338
- 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, verifySignedImageUrl };
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 };
@@ -1 +1 @@
1
- import{createImages as m}from"../packem_shared/createImages-CHgMZP4g.mjs";import{buildImageDeliveryUrl as i}from"../packem_shared/buildImageDeliveryUrl-Brqs-dcZ.mjs";import{buildSignedImageUrl as o,verifySignedImageUrl as a}from"../packem_shared/buildSignedImageUrl-fucJNAbd.mjs";export{i as buildImageDeliveryUrl,o as buildSignedImageUrl,m as createImages,a as verifySignedImageUrl};
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-DHlSjlqb.mjs";export{g as buildImageDeliveryUrl,o as buildSignedImageUrl,m as createImages,l as parseSignedTransform,d as verifySignedImageUrl};
@@ -0,0 +1 @@
1
+ import{LunoraError as h}from"@lunora/errors";const m="https://api.cloudflare.com/client/v4/accounts",w=6e4;class r extends h{constructor(o,a){super("ANALYTICS_SQL_ERROR",`Analytics Engine SQL API returned ${String(o)}: ${a}`,{name:"AnalyticsSqlError",status:o})}}const p=e=>{const o=e.fetch??globalThis.fetch,a=`${m}/${encodeURIComponent(e.accountId)}/analytics_engine/sql`,i=e.timeoutMs??w;return{query:async u=>{const n=new AbortController,d=setTimeout(()=>{n.abort()},i);try{const t=await o(a,{body:u,headers:{Authorization:`Bearer ${e.apiToken}`,"Content-Type":"text/plain"},method:"POST",signal:n.signal});if(!t.ok)throw new r(t.status,await t.text().catch(()=>"<error body unavailable: the request deadline fired before it was read>"));let c;try{c=await t.json()}catch(y){throw n.signal.aborted?y:new r(t.status,"Analytics Engine SQL API returned a non-JSON body.")}const s=c,l=s.data??[];return{columns:s.meta??[],rowCount:s.rows??l.length,rows:l}}catch(t){throw n.signal.aborted&&!(t instanceof r)?new r(504,`query timed out after ${String(i)}ms (AnalyticsSqlConfig.timeoutMs)`):t}finally{clearTimeout(d)}}}};export{r as AnalyticsSqlError,p as createAnalyticsSqlClient};
@@ -0,0 +1 @@
1
+ import{LunoraError as b}from"@lunora/errors";import f from"./SelectBuilder-C3dn71re.mjs";import{ident as m,toText as h}from"./Sql-CJr-IlfQ.mjs";const R="https://api.sql.cloudflarestorage.com/api/v1/accounts",T=6e4,$=e=>e[0]===void 0?[]:Object.keys(e[0]).map(s=>({name:s}));class c extends b{constructor(s,l){super("R2_SQL_ERROR",`R2 SQL query failed (${String(s)}): ${l}`,{name:"R2SqlError",status:s})}}const O=e=>{const s=e.fetch??globalThis.fetch,S=`${e.endpoint??R}/${encodeURIComponent(e.accountId)}/r2-sql/query/${encodeURIComponent(e.bucket)}`,w=`${e.accountId}_${e.bucket}`,u=e.timeoutMs??T,n=async t=>{const a=new AbortController,y=setTimeout(()=>{a.abort()},u);try{const r=await s(S,{body:JSON.stringify({query:t,warehouse:w}),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(p){throw a.signal.aborted?p: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 i=o.result?.rows??[];return{columns:o.result?.schema??$(i),rowCount:i.length,rows:i}}catch(r){throw a.signal.aborted&&!(r instanceof c)?new c(504,`query timed out after ${String(u)}ms (R2SqlConfig.timeoutMs)`):r}finally{clearTimeout(y)}};return{describe:async t=>n(`DESCRIBE ${m(t)}`),explain:async(t,a)=>n(`EXPLAIN ${a?.format==="json"?"FORMAT JSON ":""}${h(t)}`),from:t=>new f(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,O as createR2Sql};
@@ -0,0 +1,4 @@
1
+ const E=(e,t)=>{if(e.size<t)return;const n=e.keys().next().value;n!==void 0&&e.delete(n)},f=new TextEncoder,$=10080*60,R=/^[a-z][a-z0-9+\-.]*:\/\//i,_=Array.from({length:32},(e,t)=>t),C=new RegExp(`[${_.map(e=>String.fromCodePoint(e)).join("")}]`,"u"),x=e=>{const t=String.fromCodePoint(...e);return btoa(t).replaceAll("+","-").replaceAll("/","_").replaceAll("=","")},A=e=>{const t=e.replaceAll("-","+").replaceAll("_","/")+"===".slice((e.length+3)%4),n=atob(t),r=new Uint8Array(n.length);for(let s=0;s<n.length;s+=1)r[s]=n.codePointAt(s)??0;return r},N=64,u=new Map,y=async e=>{const t=u.get(e);if(t)return t;E(u,N);const n=crypto.subtle.importKey("raw",f.encode(e),{hash:"SHA-256",name:"HMAC"},!1,["sign","verify"]);return u.set(e,n),n},h=e=>{try{return new URL(e).host}catch{return e.replace(R,"").split("/")[0]??""}},p=e=>{if(C.test(e))throw new TypeError("hmac-url: value must not contain control characters (including CR/LF)")},T=/^\/+$/u,U=e=>T.test(e),O=(e,t)=>{if(!Number.isFinite(e)||e<=0)return"expiresInSeconds must be a positive finite number";if(e>t){const n=` (${String(t/86400)} days)`;return`expiresInSeconds must not exceed ${String(t)} seconds${n}`}},L=async(e,t)=>{const n=await y(e),r=await crypto.subtle.sign("HMAC",n,f.encode(t));return x(new Uint8Array(r))},I=async(e,t,n)=>{const r=await y(e);return crypto.subtle.verify("HMAC",r,n,f.encode(t))},b=/^\//,H=e=>{let t=e.length;for(;t>0&&e[t-1]==="/";)t-=1;return e.slice(0,t)},K=e=>e===void 0?"":Object.entries(e).filter(([,t])=>t!==void 0).toSorted(([t],[n])=>(t>n?1:0)-(t<n?1:0)).map(([t,n])=>`${t}=${typeof n=="object"?JSON.stringify(n):String(n)}`).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"},S=new Map(Object.entries(k)),P=e=>{const t=[];for(const n of e.split("&")){const r=n.indexOf("="),s=r!==-1&&S.has(n.slice(0,r)),o=t.at(-1);s||o===void 0?t.push(n):t[t.length-1]=`${o}&${n}`}return t},M=(e,t,n)=>{if(t==="string"||t==="string-or-json"&&!n.startsWith("{"))return n;if(t==="number"){const r=Number(n);if(n===""||!Number.isFinite(r))throw new TypeError(`@lunora/bindings/images: transform key "${e}" expects a number, got "${n}"`);return r}try{return JSON.parse(n)}catch{throw new TypeError(`@lunora/bindings/images: transform key "${e}" carries malformed JSON`)}},w=(e,t,n,r)=>`${e.toLowerCase()}
2
+ ${t}
3
+ ${String(n)}
4
+ ${r}`,j=e=>e.split("/").map(t=>encodeURIComponent(t)).join("/"),D=e=>{if(e==="")return{};const t={};for(const n of P(e)){const r=n.indexOf("=");if(r===-1)throw new TypeError(`@lunora/bindings/images: malformed transform segment "${n}" — expected key=value`);const s=n.slice(0,r),o=S.get(s);if(o===void 0)throw new TypeError(`@lunora/bindings/images: unknown transform key "${s}" — the serialized transform does not match this version's TransformOptions`);t[s]=M(s,o,n.slice(r+1))}return t},z=async e=>{const t=e.expiresInSeconds??3600,n=O(t,$);if(n!==void 0)throw new TypeError(`@lunora/bindings/images: ${n}`);let r="";try{r=new URL(e.baseUrl).pathname}catch{}if(r!==""&&!U(r))throw new TypeError(`@lunora/bindings/images: baseUrl must not carry a path ("${r}") — the key is verified from the full URL pathname, so a subpath base would make every signed URL fail verification`);const s=Math.floor(Date.now()/1e3)+t,o=h(e.baseUrl),c=K(e.transform),a=e.key.replace(b,"");p(a);const i=await L(e.secret,w(o,a,s,c)),l=H(e.baseUrl),m=j(a),g=c===""?"":`&t=${encodeURIComponent(c)}`;return`${l}/${m}?exp=${String(s)}&sig=${i}${g}`},F=async(e,t,n)=>{let r;try{r=e instanceof URL?e:new URL(e)}catch{return{reason:"malformed",valid:!1}}const s=r.searchParams.get("exp"),o=s===null?Number.NaN:Number(s),c=r.searchParams.get("sig"),a=r.searchParams.get("t")??"";if(!c||!Number.isInteger(o))return{reason:"malformed",valid:!1};if(o<Math.floor(Date.now()/1e3))return{reason:"expired",valid:!1};let i,l;try{i=r.pathname.replace(b,"").split("/").map(v=>decodeURIComponent(v)).join("/"),p(i),l=A(c)}catch{return{reason:"malformed",valid:!1}}const m=n?.expectedHost===void 0?r.host:h(n.expectedHost);if(!await I(t,w(m,i,o,a),l))return{reason:"bad_signature",valid:!1};if(a==="")return{key:i,valid:!0};let d;try{d=D(a)}catch{d=void 0}return{key:i,transform:a,transformOptions:d,valid:!0}};export{z as buildSignedImageUrl,D as parseSignedTransform,F as verifySignedImageUrl};
@@ -93,6 +93,16 @@ interface R2SqlConfig {
93
93
  * so a query never touches the network.
94
94
  */
95
95
  fetch?: typeof globalThis.fetch;
96
+ /**
97
+ * Milliseconds before an in-flight query (the fetch AND its body read) is
98
+ * aborted and surfaced as an `R2SqlError` with status 504. Defaults to
99
+ * 60_000 — analytical scans legitimately run tens of seconds. `undefined`
100
+ * means the default, not unbounded.
101
+ *
102
+ * The deadline is carried by the request's `signal`, so a custom `fetch`
103
+ * (above) that ignores `signal` leaves the query unbounded.
104
+ */
105
+ timeoutMs?: number;
96
106
  }
97
107
  /**
98
108
  * One column descriptor in a result's schema: the column `name` and, when the
@@ -93,6 +93,16 @@ interface R2SqlConfig {
93
93
  * so a query never touches the network.
94
94
  */
95
95
  fetch?: typeof globalThis.fetch;
96
+ /**
97
+ * Milliseconds before an in-flight query (the fetch AND its body read) is
98
+ * aborted and surfaced as an `R2SqlError` with status 504. Defaults to
99
+ * 60_000 — analytical scans legitimately run tens of seconds. `undefined`
100
+ * means the default, not unbounded.
101
+ *
102
+ * The deadline is carried by the request's `signal`, so a custom `fetch`
103
+ * (above) that ignores `signal` leaves the query unbounded.
104
+ */
105
+ timeoutMs?: number;
96
106
  }
97
107
  /**
98
108
  * One column descriptor in a result's schema: the column `name` and, when the
@@ -1 +1 @@
1
- import{default as o}from"../packem_shared/SelectBuilder-C3dn71re.mjs";import{R2SqlError as l,createR2Sql as f}from"../packem_shared/R2SqlError-Ba9yHVqU.mjs";import{asc as d,desc as i,renderOrderTerm as n}from"../packem_shared/asc-DQLvku7R.mjs";import{default as s}from"../packem_shared/SetOperation-DwBivS9U.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-CJr-IlfQ.mjs";import{WindowFunction as R,fn as T}from"../packem_shared/WindowFunction-BAPoVyhc.mjs";import{default as j}from"../packem_shared/WindowExpression-D2wkQ8zz.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-C3dn71re.mjs";import{R2SqlError as l,createR2Sql as f}from"../packem_shared/R2SqlError-D51drQVA.mjs";import{asc as d,desc as i,renderOrderTerm as n}from"../packem_shared/asc-DQLvku7R.mjs";import{default as s}from"../packem_shared/SetOperation-DwBivS9U.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-CJr-IlfQ.mjs";import{WindowFunction as R,fn as T}from"../packem_shared/WindowFunction-BAPoVyhc.mjs";import{default as j}from"../packem_shared/WindowExpression-D2wkQ8zz.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};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/bindings",
3
- "version": "1.0.0-alpha.33",
3
+ "version": "1.0.0-alpha.35",
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",
@@ -65,7 +65,7 @@
65
65
  },
66
66
  "dependencies": {
67
67
  "@lunora/errors": "1.0.0-alpha.22",
68
- "@lunora/platform": "1.0.0-alpha.15"
68
+ "@lunora/platform": "1.0.0-alpha.16"
69
69
  },
70
70
  "engines": {
71
71
  "node": "^22.15.0 || >=24.11.0"
@@ -1 +0,0 @@
1
- import{LunoraError as l}from"@lunora/errors";const u="https://api.cloudflare.com/client/v4/accounts";class c extends l{constructor(e,o){super("ANALYTICS_SQL_ERROR",`Analytics Engine SQL API returned ${String(e)}: ${o}`,{name:"AnalyticsSqlError",status:e})}}const h=n=>{const e=n.fetch??globalThis.fetch,o=`${u}/${encodeURIComponent(n.accountId)}/analytics_engine/sql`;return{query:async i=>{const t=await e(o,{body:i,headers:{Authorization:`Bearer ${n.apiToken}`,"Content-Type":"text/plain"},method:"POST"});if(!t.ok)throw new c(t.status,await t.text());let a;try{a=await t.json()}catch{throw new c(t.status,"Analytics Engine SQL API returned a non-JSON body.")}const r=a,s=r.data??[];return{columns:r.meta??[],rowCount:r.rows??s.length,rows:s}}}};export{c as AnalyticsSqlError,h as createAnalyticsSqlClient};
@@ -1 +0,0 @@
1
- import{LunoraError as h}from"@lunora/errors";import m from"./SelectBuilder-C3dn71re.mjs";import{ident as l,toText as d}from"./Sql-CJr-IlfQ.mjs";const y="https://api.sql.cloudflarestorage.com/api/v1/accounts",w=e=>e[0]===void 0?[]:Object.keys(e[0]).map(s=>({name:s}));class c extends h{constructor(s,u){super("R2_SQL_ERROR",`R2 SQL query failed (${String(s)}): ${u}`,{name:"R2SqlError",status:s})}}const f=e=>{const s=e.fetch??globalThis.fetch,p=`${e.endpoint??y}/${encodeURIComponent(e.accountId)}/r2-sql/query/${encodeURIComponent(e.bucket)}`,S=`${e.accountId}_${e.bucket}`,n=async t=>{const r=await s(p,{body:JSON.stringify({query:t,warehouse:S}),headers:{Authorization:`Bearer ${e.apiToken}`,"Content-Type":"application/json"},method:"POST"});if(!r.ok)throw new c(r.status,await r.text());let i;try{i=await r.json()}catch{throw new c(r.status,"R2 SQL returned a non-JSON body.")}const o=i;if(o.success===!1||o.errors!==void 0&&o.errors.length>0)throw new c(r.status,JSON.stringify(o.errors??o));const a=o.result?.rows??[];return{columns:o.result?.schema??w(a),rowCount:a.length,rows:a}};return{describe:async t=>n(`DESCRIBE ${l(t)}`),explain:async(t,r)=>n(`EXPLAIN ${r?.format==="json"?"FORMAT JSON ":""}${d(t)}`),from:t=>new m(n,t),query:async t=>n(d(t)),showDatabases:async()=>n("SHOW DATABASES"),showTables:async t=>n(`SHOW TABLES IN ${l(t)}`)}};export{c as R2SqlError,f as createR2Sql};
@@ -1,4 +0,0 @@
1
- const S=(e,t)=>{if(e.size<t)return;const n=e.keys().next().value;n!==void 0&&e.delete(n)},y=new TextEncoder,f=10080*60,C=/^[a-z][a-z0-9+\-.]*:\/\//i,v=Array.from({length:32},(e,t)=>t),U=new RegExp(`[${v.map(e=>String.fromCodePoint(e)).join("")}]`,"u"),R=e=>{const t=String.fromCodePoint(...e);return btoa(t).replaceAll("+","-").replaceAll("/","_").replaceAll("=","")},x=e=>{const t=e.replaceAll("-","+").replaceAll("_","/")+"===".slice((e.length+3)%4),n=atob(t),r=new Uint8Array(n.length);for(let a=0;a<n.length;a+=1)r[a]=n.codePointAt(a)??0;return r},A=64,m=new Map,u=async e=>{const t=m.get(e);if(t)return t;S(m,A);const n=crypto.subtle.importKey("raw",y.encode(e),{hash:"SHA-256",name:"HMAC"},!1,["sign","verify"]);return m.set(e,n),n},g=e=>{try{return new URL(e).host}catch{return e.replace(C,"").split("/")[0]??""}},h=e=>{if(U.test(e))throw new TypeError("hmac-url: value must not contain control characters (including CR/LF)")},E=async(e,t)=>{const n=await u(e),r=await crypto.subtle.sign("HMAC",n,y.encode(t));return R(new Uint8Array(r))},_=async(e,t,n)=>{const r=await u(e);return crypto.subtle.verify("HMAC",r,n,y.encode(t))},p=/^\//,$=e=>e===void 0?"":Object.entries(e).filter(([,t])=>t!==void 0).toSorted(([t],[n])=>(t>n?1:0)-(t<n?1:0)).map(([t,n])=>`${t}=${typeof n=="object"?JSON.stringify(n):String(n)}`).join("&"),b=(e,t,n,r)=>`${e.toLowerCase()}
2
- ${t}
3
- ${String(n)}
4
- ${r}`,L=e=>e.split("/").map(t=>encodeURIComponent(t)).join("/"),I=async e=>{const t=e.expiresInSeconds??3600;if(!Number.isFinite(t)||t<=0)throw new TypeError("@lunora/bindings/images: expiresInSeconds must be a positive finite number");if(t>f)throw new TypeError(`@lunora/bindings/images: expiresInSeconds must not exceed ${String(f)} (7 days)`);let n="";try{n=new URL(e.baseUrl).pathname}catch{}if(n!==""&&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 r=Math.floor(Date.now()/1e3)+t,a=g(e.baseUrl),s=$(e.transform),o=e.key.replace(p,"");h(o);const i=await E(e.secret,b(a,o,r,s)),c=e.baseUrl.endsWith("/")?e.baseUrl.slice(0,-1):e.baseUrl,l=L(o),d=s===""?"":`&t=${encodeURIComponent(s)}`;return`${c}/${l}?exp=${String(r)}&sig=${i}${d}`},N=async(e,t,n)=>{let r;try{r=e instanceof URL?e:new URL(e)}catch{return{reason:"malformed",valid:!1}}const a=r.searchParams.get("exp"),s=a===null?Number.NaN:Number(a),o=r.searchParams.get("sig"),i=r.searchParams.get("t")??"";if(!o||!Number.isInteger(s))return{reason:"malformed",valid:!1};if(s<Math.floor(Date.now()/1e3))return{reason:"expired",valid:!1};let c,l;try{c=r.pathname.replace(p,"").split("/").map(w=>decodeURIComponent(w)).join("/"),h(c),l=x(o)}catch{return{reason:"malformed",valid:!1}}const d=n?.expectedHost===void 0?r.host:g(n.expectedHost);return await _(t,b(d,c,s,i),l)?{key:c,transform:i===""?void 0:i,valid:!0}:{reason:"bad_signature",valid:!1}};export{I as buildSignedImageUrl,N as verifySignedImageUrl};