@lunora/bindings 1.0.0-alpha.72 → 1.0.0-alpha.74
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.
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{LunoraError as x}from"@lunora/errors";import{c as b,U as g}from"./concurrent-vRmSvRpF.mjs";const B=(t,a)=>{if(!a.includes("."))return t[a];let s=t;for(const e of a.split(".")){if(s===null||typeof s!="object"||Array.isArray(s))return;s=s[e]}return s},T=(t,a)=>{const s=a?.namespace,e=new Set(a?.shardedIndexNames),n=(c,l)=>{if(l!==void 0)return l;if(e.has(c)){if(s!==void 0)return s;throw new Error(`@lunora/bindings/vectors: index "${c}" belongs to a sharded table, but this DO instance has no shard key (it is the root/default DO) and no explicit namespace was given. A namespace-less operation here would reach every tenant's vectors — Vectorize indexes are account-global. Pass an explicit namespace, or issue this call from the sharded DO instance that owns the tenant.`)}},i=a?.deferAfterCommit,d=async(c,l,u)=>{await t.upsert(c,{embed:l.embed,id:l.id,input:l.input,metadata:l.metadata,namespace:u})},f=async(c,l)=>{await d(c,l,n(c,l.namespace))},o=i===void 0?f:async(c,l)=>{const u=n(c,l.namespace);await i(async()=>d(c,l,u))},r=async(c,l,u)=>{const m=await t.getByIds(c,l);return u===void 0?m:m.filter(h=>h.namespace===u)};return{deleteByIds:async(c,l,u)=>{const m=n(c,u);if(m===void 0){await t.deleteByIds(c,l);return}const h=await r(c,l,m);h.length!==0&&await t.deleteByIds(c,h.map(p=>p.id))},getByIds:async(c,l,u)=>{const m=n(c,u);return(await r(c,l,m)).map(p=>({id:p.id,metadata:p.metadata,namespace:p.namespace,values:[...p.values]}))},query:async(c,l)=>{const u=await t.query(c,{embed:l.embed,filter:l.filter,input:l.input,namespace:n(c,l.namespace),returnMetadata:l.returnMetadata??"indexed",topK:l.topK,vector:l.vector});return{count:u.count,matches:u.matches.map(m=>({id:m.id,metadata:m.metadata,score:m.score}))}},upsert:o,upsertNow:f}},w=new Set,I=t=>{w.has(t)||(w.add(t),console.warn(`[@lunora/bindings/vectors] index "${t}" syncs vectors without a namespace — in a
|
|
2
|
+
multi-tenant/sharded app this exposes one tenant's vectors (and any captured
|
|
3
|
+
metadata) to every other tenant, since Vectorize indexes are account-global.
|
|
4
|
+
Pass \`namespace\` (the shard/tenant key) on both write and query — query-side
|
|
5
|
+
namespace filtering is mandatory for multi-tenant apps. Single-tenant apps that
|
|
6
|
+
legitimately have no tenant key suppress this via { allowSharedNamespace: true }.`))},A=(t,a)=>{const s={};for(const e of a)e in t&&(s[e]=t[e]);return s},v=(t,a)=>{a.input.trim()===""?t.deletes.push(a.name):t.upserts.push(a)},C=(t,a,s)=>{const e=B(t,a.field);if(e!=null){if(typeof e!="string")throw new TypeError(`@lunora/bindings/vectors: inline index "${a.name}" expects a string source at "${a.field}" on table "${s}" (got ${typeof e}); use a standalone defineVectorIndex with a select() to derive text from non-string columns`);return e}},k=(t,a)=>{const s=t.tables[a.table],e=s?.vectorIndexes??[],n=Object.entries(t.vectorIndexes).filter(([,r])=>r.table===a.table);if(e.length===0&&n.length===0)return;const i=s?.softDeleteMode?.field,d=i!==void 0&&a.doc?.[i]!==void 0&&a.doc[i]!==null;if(a.op==="delete"||d)return{deletes:[...e.map(r=>r.name),...n.map(([r])=>r)],upserts:[]};const f=a.doc;if(!f)return;const o={deletes:[],upserts:[]};for(const r of e){const c=C(f,r,a.table);c===void 0?o.deletes.push(r.name):v(o,{embed:r.embed,input:c,metadata:r.metadata?A(f,r.metadata):void 0,name:r.name})}for(const[r,c]of n)v(o,{embed:c.embed,input:c.select(f),metadata:c.metadata?.(f),name:r});return o},j=t=>{const{allowSharedNamespace:a,namespace:s,schema:e,vectors:n}=t;return async i=>{const d=k(e,i);if(!d)return;const f=[...d.deletes.map(o=>async()=>{await n.deleteByIds(o,[i.id])}),...d.upserts.map(o=>async()=>{!a&&s===void 0&&I(o.name),await n.upsertNow(o.name,{embed:o.embed,id:i.id,input:o.input,metadata:o.metadata,namespace:s})})];await b(f,g,async o=>o())}},S=1e3,E=(t,a)=>{const s=[];for(let e=0;e<t.length;e+=a)s.push(t.slice(e,e+a));return s},y=t=>{if(typeof t!="object"||t===null)return"unknown";const{name:a,status:s,statusCode:e}=t,n=typeof s=="number"?s:e;if(typeof n=="number"){if(n>=500||n===401||n===403||n===408||n===429)return"service";if(n>=400)return"row"}return a==="TimeoutError"||a==="AbortError"?"service":t instanceof TypeError||t instanceof RangeError?"row":"unknown"},M=async(t,a)=>{const s=await b(t,g,async d=>{try{return{item:d,ok:!0,value:await a(d)}}catch(f){return{error:f,item:d,ok:!1}}}),e=s.flatMap(d=>d.ok?[{item:d.item,value:d.value}]:[]),n=s.flatMap(d=>d.ok?[]:[{error:d.error,item:d.item}]),i=n.find(({error:d})=>y(d)==="service");if(i)throw i.error;if(t.length>=2&&e.length===0&&n.some(({error:d})=>y(d)!=="row"))throw n[0]?.error;return{failed:n,ok:e}},D=(t,a,s,e)=>{const n=new Map,i=[];for(const{doc:d,id:f}of s){let o;try{o=k(t,{doc:d,id:f,op:"update",table:a})}catch(r){e.set(f,r);continue}for(const r of o?.deletes??[])n.set(r,[...n.get(r)??[],f]);for(const r of o?.upserts??[])i.push({id:f,upsert:r})}return{deletes:n,pending:i}},O=async(t,a,s,e)=>{const{allowSharedNamespace:n,namespace:i,upsertMany:d,vectors:f}=t;!n&&i===void 0&&I(a);const o=s.map(({id:r,upsert:c,values:l})=>({embed:()=>l,id:r,input:c.input,metadata:c.metadata,namespace:i}));for(const r of E(o,S))try{await d(a,r)}catch{const c=await M(r,async l=>f.upsertNow(a,l));for(const{error:l,item:u}of c.failed)e.set(u.id,l)}},V=async(t,a,s)=>{const e=new Map,{deletes:n,pending:i}=D(t.schema,a,s,e),d=await M(i,async({upsert:o})=>o.embed(o.input)),f=new Map;for(const{error:o,item:r}of d.failed)e.set(r.id,o);for(const{item:o,value:r}of d.ok)f.set(o.upsert.name,[...f.get(o.upsert.name)??[],{...o,values:r}]);for(const[o,r]of n)for(const c of E(r,S))await t.vectors.deleteByIds(o,c);for(const[o,r]of f)await O(t,o,r,e);return[...e].map(([o,r])=>({error:r,id:o}))},P=t=>async(a,s)=>{try{return await V(t,a,s)}catch(e){throw y(e)==="service"?new x("SERVICE_UNAVAILABLE",e instanceof Error?e.message:String(e),{cause:e}):e}},$=t=>{const a=new Map,s=(e,n,i)=>{const d=i===void 0?n:[...n,i];a.set(e,[...a.get(e)??[],JSON.stringify(d)])};for(const[e,n]of Object.entries(t.tables))for(const i of n.vectorIndexes??[])s(e,[i.name,i.field,i.dimensions,i.metric,i.metadata??[]],i.model);for(const[e,n]of Object.entries(t.vectorIndexes))s(n.table,[e,"(select)",n.dimensions,n.metric],n.model);return[...a].map(([e,n])=>{const i=t.tables[e]?.softDeleteMode?.field;return{profile:(i===void 0?n:[...n,JSON.stringify(["(softDelete)",i])]).toSorted((f,o)=>f.localeCompare(o)).join("|"),table:e}})};export{T as createContextVectors,P as createVectorBackfillSync,j as createVectorSyncHook,$ as vectorBackfillTargets};
|
package/dist/vectors/index.d.mts
CHANGED
|
@@ -318,7 +318,9 @@ interface VectorBackfillFailure {
|
|
|
318
318
|
/**
|
|
319
319
|
* Index one page of rows for the shard's vector backfill. Resolves with the rows
|
|
320
320
|
* that failed on their own; REJECTS when the failure is the service's rather than
|
|
321
|
-
* a row's, so the caller holds its cursor and retries the page
|
|
321
|
+
* a row's, so the caller holds its cursor and retries the page — with a
|
|
322
|
+
* `SERVICE_UNAVAILABLE` `LunoraError` when the error shows the failure to be
|
|
323
|
+
* transient, and with the raw error when only the whole page failing suggests it.
|
|
322
324
|
*/
|
|
323
325
|
type VectorBackfillSync = (table: string, rows: ReadonlyArray<{
|
|
324
326
|
doc: Record<string, unknown>;
|
|
@@ -339,10 +341,14 @@ type VectorBackfillSync = (table: string, rows: ReadonlyArray<{
|
|
|
339
341
|
* these too, and a backfill that stopped on one would never finish.
|
|
340
342
|
*
|
|
341
343
|
* A SERVICE failure is transient: the embedder or Vectorize is unreachable. The
|
|
342
|
-
* call rejects, so the page is retried. It is recognised
|
|
344
|
+
* call rejects, so the page is retried. It is recognised by the error where the
|
|
345
|
+
* error says (an HTTP 5xx/408/429 status, a timeout — see {@link classifyFailure};
|
|
346
|
+
* these reject as `SERVICE_UNAVAILABLE`), and otherwise as every attempt in a
|
|
343
347
|
* group of two or more failing, and as a failed `deleteByIds` (which has no row
|
|
344
348
|
* content to blame). A batch `upsertMany` that fails is retried one row at a
|
|
345
|
-
* time to tell the two apart.
|
|
349
|
+
* time to tell the two apart. A group that fails whole on every retry — each
|
|
350
|
+
* row refused for the same reason, with no status to show it — rejects each
|
|
351
|
+
* time too; the backfill writes such a page off after a few consecutive tries.
|
|
346
352
|
*
|
|
347
353
|
* `upsertMany` is the raw binding call, so the namespace is passed explicitly —
|
|
348
354
|
* the same `namespace` the live hook scopes by.
|
|
@@ -361,15 +367,18 @@ declare const createVectorBackfillSync: (options: BackfillSyncOptions) => Vector
|
|
|
361
367
|
* backfill, which re-walks a table whose fingerprint changed.
|
|
362
368
|
*
|
|
363
369
|
* Covers what the schema can see: index names, the inline source field,
|
|
364
|
-
* dimensions, metric, inline metadata fields
|
|
370
|
+
* dimensions, metric, inline metadata fields, the declared `model`, and the
|
|
371
|
+
* table's `.softDelete()` field — a row hidden by a newly chosen marker keeps
|
|
372
|
+
* its vector until the table is walked again. A
|
|
365
373
|
* function (`embed`, a Shape B `select`/`metadata`) has no stable identity to
|
|
366
374
|
* fingerprint — its source text changes with unrelated rebuilds of the bundle,
|
|
367
375
|
* which would re-embed whole tables for nothing — so the declared `model` string
|
|
368
376
|
* stands in for `embed`, and any other change is announced by calling the
|
|
369
377
|
* backfill with `restart: true`.
|
|
370
378
|
*
|
|
371
|
-
* `model` joins a descriptor only when declared,
|
|
372
|
-
* the
|
|
379
|
+
* `model` joins a descriptor only when declared, and the soft-delete field only
|
|
380
|
+
* when the table has one, so an index without either keeps the fingerprint it
|
|
381
|
+
* was recorded under and is not re-embedded for it.
|
|
373
382
|
*/
|
|
374
383
|
declare const vectorBackfillTargets: (schema: SchemaLike) => {
|
|
375
384
|
profile: string;
|
package/dist/vectors/index.d.ts
CHANGED
|
@@ -318,7 +318,9 @@ interface VectorBackfillFailure {
|
|
|
318
318
|
/**
|
|
319
319
|
* Index one page of rows for the shard's vector backfill. Resolves with the rows
|
|
320
320
|
* that failed on their own; REJECTS when the failure is the service's rather than
|
|
321
|
-
* a row's, so the caller holds its cursor and retries the page
|
|
321
|
+
* a row's, so the caller holds its cursor and retries the page — with a
|
|
322
|
+
* `SERVICE_UNAVAILABLE` `LunoraError` when the error shows the failure to be
|
|
323
|
+
* transient, and with the raw error when only the whole page failing suggests it.
|
|
322
324
|
*/
|
|
323
325
|
type VectorBackfillSync = (table: string, rows: ReadonlyArray<{
|
|
324
326
|
doc: Record<string, unknown>;
|
|
@@ -339,10 +341,14 @@ type VectorBackfillSync = (table: string, rows: ReadonlyArray<{
|
|
|
339
341
|
* these too, and a backfill that stopped on one would never finish.
|
|
340
342
|
*
|
|
341
343
|
* A SERVICE failure is transient: the embedder or Vectorize is unreachable. The
|
|
342
|
-
* call rejects, so the page is retried. It is recognised
|
|
344
|
+
* call rejects, so the page is retried. It is recognised by the error where the
|
|
345
|
+
* error says (an HTTP 5xx/408/429 status, a timeout — see {@link classifyFailure};
|
|
346
|
+
* these reject as `SERVICE_UNAVAILABLE`), and otherwise as every attempt in a
|
|
343
347
|
* group of two or more failing, and as a failed `deleteByIds` (which has no row
|
|
344
348
|
* content to blame). A batch `upsertMany` that fails is retried one row at a
|
|
345
|
-
* time to tell the two apart.
|
|
349
|
+
* time to tell the two apart. A group that fails whole on every retry — each
|
|
350
|
+
* row refused for the same reason, with no status to show it — rejects each
|
|
351
|
+
* time too; the backfill writes such a page off after a few consecutive tries.
|
|
346
352
|
*
|
|
347
353
|
* `upsertMany` is the raw binding call, so the namespace is passed explicitly —
|
|
348
354
|
* the same `namespace` the live hook scopes by.
|
|
@@ -361,15 +367,18 @@ declare const createVectorBackfillSync: (options: BackfillSyncOptions) => Vector
|
|
|
361
367
|
* backfill, which re-walks a table whose fingerprint changed.
|
|
362
368
|
*
|
|
363
369
|
* Covers what the schema can see: index names, the inline source field,
|
|
364
|
-
* dimensions, metric, inline metadata fields
|
|
370
|
+
* dimensions, metric, inline metadata fields, the declared `model`, and the
|
|
371
|
+
* table's `.softDelete()` field — a row hidden by a newly chosen marker keeps
|
|
372
|
+
* its vector until the table is walked again. A
|
|
365
373
|
* function (`embed`, a Shape B `select`/`metadata`) has no stable identity to
|
|
366
374
|
* fingerprint — its source text changes with unrelated rebuilds of the bundle,
|
|
367
375
|
* which would re-embed whole tables for nothing — so the declared `model` string
|
|
368
376
|
* stands in for `embed`, and any other change is announced by calling the
|
|
369
377
|
* backfill with `restart: true`.
|
|
370
378
|
*
|
|
371
|
-
* `model` joins a descriptor only when declared,
|
|
372
|
-
* the
|
|
379
|
+
* `model` joins a descriptor only when declared, and the soft-delete field only
|
|
380
|
+
* when the table has one, so an index without either keeps the fingerprint it
|
|
381
|
+
* was recorded under and is not re-embedded for it.
|
|
373
382
|
*/
|
|
374
383
|
declare const vectorBackfillTargets: (schema: SchemaLike) => {
|
|
375
384
|
profile: string;
|
package/dist/vectors/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createContextVectors as t,createVectorBackfillSync as o,createVectorSyncHook as c,vectorBackfillTargets as a}from"../packem_shared/createContextVectors-
|
|
1
|
+
import{createContextVectors as t,createVectorBackfillSync as o,createVectorSyncHook as c,vectorBackfillTargets as a}from"../packem_shared/createContextVectors-DiyO3pZU.mjs";import{createVectorAdminIntrospector as l}from"../packem_shared/createVectorAdminIntrospector-Ct8v6PxJ.mjs";import{default as s}from"../packem_shared/createVectors-Dzv0ilKE.mjs";export{t as createContextVectors,l as createVectorAdminIntrospector,o as createVectorBackfillSync,c as createVectorSyncHook,s as createVectors,a as vectorBackfillTargets};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/bindings",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.74",
|
|
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.41",
|
|
68
|
-
"@lunora/platform": "1.0.0-alpha.
|
|
68
|
+
"@lunora/platform": "1.0.0-alpha.39"
|
|
69
69
|
},
|
|
70
70
|
"engines": {
|
|
71
71
|
"node": "^22.15.0 || >=24.11.0"
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import{c as w,U as v}from"./concurrent-vRmSvRpF.mjs";const M=(s,r)=>{if(!r.includes("."))return s[r];let d=s;for(const n of r.split(".")){if(d===null||typeof d!="object"||Array.isArray(d))return;d=d[n]}return d},A=(s,r)=>{const d=r?.namespace,n=new Set(r?.shardedIndexNames),c=(a,i)=>{if(i!==void 0)return i;if(n.has(a)){if(d!==void 0)return d;throw new Error(`@lunora/bindings/vectors: index "${a}" 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.`)}},e=r?.deferAfterCommit,l=async(a,i,m)=>{await s.upsert(a,{embed:i.embed,id:i.id,input:i.input,metadata:i.metadata,namespace:m})},f=async(a,i)=>{await l(a,i,c(a,i.namespace))},o=e===void 0?f:async(a,i)=>{const m=c(a,i.namespace);await e(async()=>l(a,i,m))},t=async(a,i,m)=>{const u=await s.getByIds(a,i);return m===void 0?u:u.filter(h=>h.namespace===m)};return{deleteByIds:async(a,i,m)=>{const u=c(a,m);if(u===void 0){await s.deleteByIds(a,i);return}const h=await t(a,i,u);h.length!==0&&await s.deleteByIds(a,h.map(p=>p.id))},getByIds:async(a,i,m)=>{const u=c(a,m);return(await t(a,i,u)).map(p=>({id:p.id,metadata:p.metadata,namespace:p.namespace,values:[...p.values]}))},query:async(a,i)=>{const m=await s.query(a,{embed:i.embed,filter:i.filter,input:i.input,namespace:c(a,i.namespace),returnMetadata:i.returnMetadata??"indexed",topK:i.topK,vector:i.vector});return{count:m.count,matches:m.matches.map(u=>({id:u.id,metadata:u.metadata,score:u.score}))}},upsert:o,upsertNow:f}},y=new Set,b=s=>{y.has(s)||(y.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,r)=>{const d={};for(const n of r)n in s&&(d[n]=s[n]);return d},g=(s,r)=>{const d=s.tables[r.table],n=d?.vectorIndexes??[],c=Object.entries(s.vectorIndexes).filter(([,t])=>t.table===r.table);if(n.length===0&&c.length===0)return;const e=d?.softDeleteMode?.field,l=e!==void 0&&r.doc?.[e]!==void 0&&r.doc[e]!==null;if(r.op==="delete"||l)return{deletes:[...n.map(t=>t.name),...c.map(([t])=>t)],upserts:[]};const f=r.doc;if(!f)return;const o={deletes:[],upserts:[]};for(const t of n){const a=M(f,t.field);if(a==null)o.deletes.push(t.name);else if(typeof a=="string")o.upserts.push({embed:t.embed,input:a,metadata:t.metadata?S(f,t.metadata):void 0,name:t.name});else throw new TypeError(`@lunora/bindings/vectors: inline index "${t.name}" expects a string source at "${t.field}" on table "${r.table}" (got ${typeof a}); use a standalone defineVectorIndex with a select() to derive text from non-string columns`)}for(const[t,a]of c)o.upserts.push({embed:a.embed,input:a.select(f),metadata:a.metadata?.(f),name:t});return o},D=s=>{const{allowSharedNamespace:r,namespace:d,schema:n,vectors:c}=s;return async e=>{const l=g(n,e);if(!l)return;const f=[...l.deletes.map(o=>async()=>{await c.deleteByIds(o,[e.id])}),...l.upserts.map(o=>async()=>{!r&&d===void 0&&b(o.name),await c.upsertNow(o.name,{embed:o.embed,id:e.id,input:o.input,metadata:o.metadata,namespace:d})})];await w(f,v,async o=>o())}},I=1e3,x=(s,r)=>{const d=[];for(let n=0;n<s.length;n+=r)d.push(s.slice(n,n+r));return d},k=async(s,r)=>{const d=await w(s,v,async e=>{try{return{item:e,ok:!0,value:await r(e)}}catch(l){return{error:l,item:e,ok:!1}}}),n=d.flatMap(e=>e.ok?[{item:e.item,value:e.value}]:[]),c=d.flatMap(e=>e.ok?[]:[{error:e.error,item:e.item}]);if(s.length>=2&&n.length===0)throw c[0]?.error;return{failed:c,ok:n}},B=(s,r,d,n)=>{const c=new Map,e=[];for(const{doc:l,id:f}of d){let o;try{o=g(s,{doc:l,id:f,op:"update",table:r})}catch(t){n.set(f,t);continue}for(const t of o?.deletes??[])c.set(t,[...c.get(t)??[],f]);for(const t of o?.upserts??[])e.push({id:f,upsert:t})}return{deletes:c,pending:e}},C=async(s,r,d,n)=>{const{allowSharedNamespace:c,namespace:e,upsertMany:l,vectors:f}=s;!c&&e===void 0&&b(r);const o=d.map(({id:t,upsert:a,values:i})=>({embed:()=>i,id:t,input:a.input,metadata:a.metadata,namespace:e}));for(const t of x(o,I))try{await l(r,t)}catch{const a=await k(t,async i=>f.upsertNow(r,i));for(const{error:i,item:m}of a.failed)n.set(m.id,i)}},E=s=>async(r,d)=>{const n=new Map,{deletes:c,pending:e}=B(s.schema,r,d,n),l=await k(e,async({upsert:o})=>o.embed(o.input)),f=new Map;for(const{error:o,item:t}of l.failed)n.set(t.id,o);for(const{item:o,value:t}of l.ok)f.set(o.upsert.name,[...f.get(o.upsert.name)??[],{...o,values:t}]);for(const[o,t]of c)for(const a of x(t,I))await s.vectors.deleteByIds(o,a);for(const[o,t]of f)await C(s,o,t,n);return[...n].map(([o,t])=>({error:t,id:o}))},V=s=>{const r=new Map,d=(n,c,e)=>{const l=e===void 0?c:[...c,e];r.set(n,[...r.get(n)??[],JSON.stringify(l)])};for(const[n,c]of Object.entries(s.tables))for(const e of c.vectorIndexes??[])d(n,[e.name,e.field,e.dimensions,e.metric,e.metadata??[]],e.model);for(const[n,c]of Object.entries(s.vectorIndexes))d(c.table,[n,"(select)",c.dimensions,c.metric],c.model);return[...r].map(([n,c])=>({profile:c.toSorted((e,l)=>e.localeCompare(l)).join("|"),table:n}))};export{A as createContextVectors,E as createVectorBackfillSync,D as createVectorSyncHook,V as vectorBackfillTargets};
|