@lunora/d1 1.0.0-alpha.47 → 1.0.0-alpha.48
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/index.d.mts +5 -3
- package/dist/index.d.ts +5 -3
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/backfillD1SearchIndexes-ERQf6szv.mjs +1 -0
- package/dist/packem_shared/exportGlobalRows-CmcmGZxv.mjs +1 -0
- package/dist/packem_shared/facetGlobalColumn-R-BETSuA.mjs +1 -0
- package/dist/packem_shared/{sqliteDialect-JvN44Hjf.mjs → sqliteDialect-B43yA0ek.mjs} +1 -1
- package/package.json +3 -3
- package/dist/packem_shared/createD1CtxDb-oii8T0ys.mjs +0 -1
- package/dist/packem_shared/exportGlobalRows-CVw1hOdA.mjs +0 -1
- package/dist/packem_shared/facetGlobalColumn-T4arPSaV.mjs +0 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SchemaLike, DatabaseWriterLike } from '@lunora/do';
|
|
2
|
-
import { SqlCtxDbOptions,
|
|
2
|
+
import { SqlCtxDbOptions, SqlCtxExec, createSqlCtxDb, readSqlCdcChanges, SqlDialect } from '@lunora/sql-store';
|
|
3
3
|
export { type SqlCtxExec as D1Exec, type SqlCtxDbOptions, type SqlCtxExec, createSqlCtxDb } from '@lunora/sql-store';
|
|
4
4
|
import { BatchItem, BatchResponse } from 'drizzle-orm/batch';
|
|
5
5
|
import { DrizzleD1Database } from 'drizzle-orm/d1';
|
|
@@ -13,8 +13,10 @@ declare const runD1GlobalTableMigrations: (exec: SqlCtxExec, schema: SchemaLike)
|
|
|
13
13
|
declare const runD1AggregateMigrations: (exec: SqlCtxExec, schema: SchemaLike) => Promise<void>;
|
|
14
14
|
/** Materialize the `__rank_<index>` companion tables for the schema's rank indexes. */
|
|
15
15
|
declare const runD1RankMigrations: (exec: SqlCtxExec, schema: SchemaLike) => Promise<void>;
|
|
16
|
-
/** Materialize the `__fts_<index>` fts5 shadow tables for the schema's search indexes
|
|
16
|
+
/** Materialize (and backfill) the `__fts_<index>` fts5 shadow tables for the schema's search indexes. */
|
|
17
17
|
declare const runD1SearchMigrations: (exec: SqlCtxExec, schema: SchemaLike) => Promise<void>;
|
|
18
|
+
/** Index existing rows into every search companion, including the `staged: true` ones migrations leave empty. */
|
|
19
|
+
declare const backfillD1SearchIndexes: (exec: SqlCtxExec, schema: SchemaLike) => Promise<void>;
|
|
18
20
|
/** Create the `__cdc_log` table in D1 (idempotent; only run when CDC is enabled). */
|
|
19
21
|
declare const runD1CdcMigration: (exec: SqlCtxExec) => Promise<void>;
|
|
20
22
|
/** Read changelog entries newer than `sinceSeq` in commit order. */
|
|
@@ -345,4 +347,4 @@ declare class MigrationRunner {
|
|
|
345
347
|
* table probing. The rest of the per-statement shaping is drizzle's.
|
|
346
348
|
*/
|
|
347
349
|
declare const sqliteDialect: SqlDialect;
|
|
348
|
-
export { D1Client, type D1ContextDatabaseOptions as D1CtxDbOptions, type D1DatabaseLike, type D1PreparedStatementLike, D1Session, type D1SessionLike, type ExportGlobalArgs, type FacetGlobalColumnOptions, type ExportRow as GlobalExportRow, type GlobalFacetResult, type GlobalFacetValue, type GlobalFilterClause, type ImportError as GlobalImportError, type ImportResult as GlobalImportResult, type GlobalTableInfo, type GlobalTablePage, type ImportGlobalArgs, type Migration, MigrationRunner, type MigrationRunnerResult, type ReadGlobalTablePageOptions, createD1ContextDatabase as createD1CtxDb, exportGlobalRows, facetGlobalColumn, importGlobalRows, listGlobalTables, readD1CdcChanges, readGlobalTablePage, runD1AggregateMigrations, runD1CdcMigration, runD1GlobalTableMigrations, runD1RankMigrations, runD1SearchMigrations, selectGlobalTables, sqliteDialect, trimD1CdcChanges };
|
|
350
|
+
export { D1Client, type D1ContextDatabaseOptions as D1CtxDbOptions, type D1DatabaseLike, type D1PreparedStatementLike, D1Session, type D1SessionLike, type ExportGlobalArgs, type FacetGlobalColumnOptions, type ExportRow as GlobalExportRow, type GlobalFacetResult, type GlobalFacetValue, type GlobalFilterClause, type ImportError as GlobalImportError, type ImportResult as GlobalImportResult, type GlobalTableInfo, type GlobalTablePage, type ImportGlobalArgs, type Migration, MigrationRunner, type MigrationRunnerResult, type ReadGlobalTablePageOptions, backfillD1SearchIndexes, createD1ContextDatabase as createD1CtxDb, exportGlobalRows, facetGlobalColumn, importGlobalRows, listGlobalTables, readD1CdcChanges, readGlobalTablePage, runD1AggregateMigrations, runD1CdcMigration, runD1GlobalTableMigrations, runD1RankMigrations, runD1SearchMigrations, selectGlobalTables, sqliteDialect, trimD1CdcChanges };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SchemaLike, DatabaseWriterLike } from '@lunora/do';
|
|
2
|
-
import { SqlCtxDbOptions,
|
|
2
|
+
import { SqlCtxDbOptions, SqlCtxExec, createSqlCtxDb, readSqlCdcChanges, SqlDialect } from '@lunora/sql-store';
|
|
3
3
|
export { type SqlCtxExec as D1Exec, type SqlCtxDbOptions, type SqlCtxExec, createSqlCtxDb } from '@lunora/sql-store';
|
|
4
4
|
import { BatchItem, BatchResponse } from 'drizzle-orm/batch';
|
|
5
5
|
import { DrizzleD1Database } from 'drizzle-orm/d1';
|
|
@@ -13,8 +13,10 @@ declare const runD1GlobalTableMigrations: (exec: SqlCtxExec, schema: SchemaLike)
|
|
|
13
13
|
declare const runD1AggregateMigrations: (exec: SqlCtxExec, schema: SchemaLike) => Promise<void>;
|
|
14
14
|
/** Materialize the `__rank_<index>` companion tables for the schema's rank indexes. */
|
|
15
15
|
declare const runD1RankMigrations: (exec: SqlCtxExec, schema: SchemaLike) => Promise<void>;
|
|
16
|
-
/** Materialize the `__fts_<index>` fts5 shadow tables for the schema's search indexes
|
|
16
|
+
/** Materialize (and backfill) the `__fts_<index>` fts5 shadow tables for the schema's search indexes. */
|
|
17
17
|
declare const runD1SearchMigrations: (exec: SqlCtxExec, schema: SchemaLike) => Promise<void>;
|
|
18
|
+
/** Index existing rows into every search companion, including the `staged: true` ones migrations leave empty. */
|
|
19
|
+
declare const backfillD1SearchIndexes: (exec: SqlCtxExec, schema: SchemaLike) => Promise<void>;
|
|
18
20
|
/** Create the `__cdc_log` table in D1 (idempotent; only run when CDC is enabled). */
|
|
19
21
|
declare const runD1CdcMigration: (exec: SqlCtxExec) => Promise<void>;
|
|
20
22
|
/** Read changelog entries newer than `sinceSeq` in commit order. */
|
|
@@ -345,4 +347,4 @@ declare class MigrationRunner {
|
|
|
345
347
|
* table probing. The rest of the per-statement shaping is drizzle's.
|
|
346
348
|
*/
|
|
347
349
|
declare const sqliteDialect: SqlDialect;
|
|
348
|
-
export { D1Client, type D1ContextDatabaseOptions as D1CtxDbOptions, type D1DatabaseLike, type D1PreparedStatementLike, D1Session, type D1SessionLike, type ExportGlobalArgs, type FacetGlobalColumnOptions, type ExportRow as GlobalExportRow, type GlobalFacetResult, type GlobalFacetValue, type GlobalFilterClause, type ImportError as GlobalImportError, type ImportResult as GlobalImportResult, type GlobalTableInfo, type GlobalTablePage, type ImportGlobalArgs, type Migration, MigrationRunner, type MigrationRunnerResult, type ReadGlobalTablePageOptions, createD1ContextDatabase as createD1CtxDb, exportGlobalRows, facetGlobalColumn, importGlobalRows, listGlobalTables, readD1CdcChanges, readGlobalTablePage, runD1AggregateMigrations, runD1CdcMigration, runD1GlobalTableMigrations, runD1RankMigrations, runD1SearchMigrations, selectGlobalTables, sqliteDialect, trimD1CdcChanges };
|
|
350
|
+
export { D1Client, type D1ContextDatabaseOptions as D1CtxDbOptions, type D1DatabaseLike, type D1PreparedStatementLike, D1Session, type D1SessionLike, type ExportGlobalArgs, type FacetGlobalColumnOptions, type ExportRow as GlobalExportRow, type GlobalFacetResult, type GlobalFacetValue, type GlobalFilterClause, type ImportError as GlobalImportError, type ImportResult as GlobalImportResult, type GlobalTableInfo, type GlobalTablePage, type ImportGlobalArgs, type Migration, MigrationRunner, type MigrationRunnerResult, type ReadGlobalTablePageOptions, backfillD1SearchIndexes, createD1ContextDatabase as createD1CtxDb, exportGlobalRows, facetGlobalColumn, importGlobalRows, listGlobalTables, readD1CdcChanges, readGlobalTablePage, runD1AggregateMigrations, runD1CdcMigration, runD1GlobalTableMigrations, runD1RankMigrations, runD1SearchMigrations, selectGlobalTables, sqliteDialect, trimD1CdcChanges };
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{exportGlobalRows as
|
|
1
|
+
import{exportGlobalRows as a,importGlobalRows as o,selectGlobalTables as l}from"./packem_shared/exportGlobalRows-CmcmGZxv.mjs";import{D1Client as i,D1Session as n}from"./packem_shared/D1Client-B9m0fFLr.mjs";import{backfillD1SearchIndexes as b,createD1CtxDb as D,readD1CdcChanges as g,runD1AggregateMigrations as c,runD1CdcMigration as x,runD1GlobalTableMigrations as f,runD1RankMigrations as m,runD1SearchMigrations as p,trimD1CdcChanges as C}from"./packem_shared/backfillD1SearchIndexes-ERQf6szv.mjs";import{facetGlobalColumn as d,listGlobalTables as G,readGlobalTablePage as M}from"./packem_shared/facetGlobalColumn-R-BETSuA.mjs";import{MigrationRunner as R}from"./packem_shared/MigrationRunner-DvnPBDVT.mjs";import{default as T}from"./packem_shared/sqliteDialect-B43yA0ek.mjs";import{createSqlCtxDb as q}from"@lunora/sql-store";export{i as D1Client,n as D1Session,R as MigrationRunner,b as backfillD1SearchIndexes,D as createD1CtxDb,q as createSqlCtxDb,a as exportGlobalRows,d as facetGlobalColumn,o as importGlobalRows,G as listGlobalTables,g as readD1CdcChanges,M as readGlobalTablePage,c as runD1AggregateMigrations,x as runD1CdcMigration,f as runD1GlobalTableMigrations,m as runD1RankMigrations,p as runD1SearchMigrations,l as selectGlobalTables,T as sqliteDialect,C as trimD1CdcChanges};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{backfillSqlSearchIndexes as n,createSqlCtxDb as i,readSqlCdcChanges as t,runSqlAggregateMigrations as s,runSqlCdcMigration as l,runSqlGlobalTableMigrations as o,runSqlRankMigrations as g,runSqlSearchMigrations as c,trimSqlCdcChanges as d}from"@lunora/sql-store";import{createSqlCtxDb as G,decodeGlobalRow as R}from"@lunora/sql-store";import e from"./sqliteDialect-B43yA0ek.mjs";const D=a=>i({...a,dialect:e}),b=(a,r)=>o(a,r,e),q=(a,r)=>s(a,r,e),u=(a,r)=>g(a,r,e),M=(a,r)=>c(a,r,e),h=(a,r)=>n(a,r,e),m=a=>l(a,e),x=(a,r={})=>t(a,r,e),f=(a,r)=>d(a,r,e);export{h as backfillD1SearchIndexes,D as createD1CtxDb,G as createSqlCtxDb,R as decodeGlobalRow,x as readD1CdcChanges,q as runD1AggregateMigrations,m as runD1CdcMigration,b as runD1GlobalTableMigrations,u as runD1RankMigrations,M as runD1SearchMigrations,f as trimD1CdcChanges};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{toErrorBody as u}from"@lunora/errors";import{runD1GlobalTableMigrations as m}from"./backfillD1SearchIndexes-ERQf6szv.mjs";import{quoteIdentifier as f}from"./quoteIdentifier-CObIFRhb.mjs";import{decodeGlobalRow as E}from"@lunora/sql-store";const R=200,g=(o,t)=>{const r=e=>o.tables[e]?.shardMode?.kind==="global";return t&&t.length>0?t.filter(e=>r(e)):Object.keys(o.tables).filter(e=>r(e))},k=(o,t,r)=>{const e=o.tables[t];return e?E(e,r):{_creationTime:r._creationTime,_id:r.id}},O=async function*(o,t,r){const e=g(t,r.tables),a=r.batchSize??R;await m(o,t);for(const i of e){const n=f(i);let c,s=!0;for(;s;){const l=c===void 0?await o.all(`SELECT * FROM ${n} ORDER BY "id" LIMIT ?`,[a]):await o.all(`SELECT * FROM ${n} WHERE "id" > ? ORDER BY "id" LIMIT ?`,[c,a]);for(const b of l)yield{doc:k(t,i,b),table:i};const d=l.at(-1);d!==void 0&&(c=String(d.id)),s=l.length===a}}},w=(o,t,r)=>{const e=o.tables[t];if(!e)return`unknown table: ${t}`;for(const[a,i]of Object.entries(e.shape)){const n=r[a],c=i.kind==="optional";if(n===void 0&&c)continue;const s=i.parse;if(typeof s=="function")try{s(n)}catch(l){const d=l instanceof Error?l.message:String(l);return`field "${a}": ${d}`}}},y=async(o,t,r,e)=>{try{return t?(await t.all(`SELECT 1 AS hit FROM ${f(r)} WHERE "id" = ? LIMIT 1`,[e])).length>0:await o.get(e)!==null}catch{return!1}},p=async(o,t,r,e,a)=>{const{doc:i,table:n}=e;if(t.tables[n]?.shardMode?.kind!=="global")return{kind:"skip"};if(!i||typeof i!="object"||Array.isArray(i))return{error:{code:"BAD_ROW",line:a,message:"row is missing or malformed `doc`",table:n},kind:"error"};const c=w(t,n,i);if(c!==void 0)return{error:{code:"VALIDATION_ERROR",line:a,message:c,table:n},kind:"error"};const s=typeof i._id=="string"?i._id:void 0;if(s!==void 0&&await y(o,r.exec,n,s))return{kind:"conflict"};try{return await o.insert(n,i,{allowExplicitId:!0}),{inserted:n,kind:"inserted"}}catch(l){const{body:d}=u(l,{fallbackCode:"INSERT_FAILED"});return{error:{code:d.code,line:a,message:d.message,table:n},kind:"error"}}},M=async(o,t,r)=>{const e=[],a={};let i=0,n=(r.startLine??1)-1;for(const c of r.rows){n+=1;const s=await p(o,t,r,c,n);switch(s.kind){case"conflict":{i+=1;break}case"error":{e.push(s.error);break}case"inserted":{a[s.inserted]=(a[s.inserted]??0)+1;break}}}return{conflicts:i,errors:e,inserted:a}};export{O as exportGlobalRows,M as importGlobalRows,g as selectGlobalTables};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as _}from"@lunora/errors";import{runD1GlobalTableMigrations as T}from"./backfillD1SearchIndexes-ERQf6szv.mjs";import{quoteIdentifier as i}from"./quoteIdentifier-CObIFRhb.mjs";import{decodeGlobalRow as S}from"@lunora/sql-store";const E=(t,a)=>T(t,a),L=50,g=500,y=30,C=200,O=(t,a,o)=>Math.min(Math.max(t,a),o),A=/^sqlite_|^_cf_|^d1_|^__cdc|__agg_|__rank_|__fts_/u,U=t=>A.test(t),N=/password|secret|token|hash|salt|credential/iu,p=async t=>(await t.all("SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name",[])).map(a=>String(a.name)).filter(a=>!U(a)),$=async(t,a,o="",n=[])=>{const s=await t.all(`SELECT COUNT(*) AS c FROM ${a}${o}`,n);return Number(s[0]?.c??0)},v=(t,a,o)=>t.tables[a]!==void 0&&o==="_id"?"id":o,M=(t,a,o,n)=>{if(n===void 0||n.length===0)return;const s=[],l=[];for(const e of n){if(!o.includes(e.column))throw new _("UNKNOWN_COLUMN",`unknown column: ${e.column}`,{status:404});if(t.tables[a]===void 0&&N.test(e.column))throw new _("FORBIDDEN",`cannot filter on a redacted column: ${e.column}`,{status:403});const r=i(v(t,a,e.column));e.value===null||e.value===void 0?s.push(`${r} IS NULL`):(s.push(`${r} = ?`),l.push(e.value))}return{params:l,where:s.join(" AND ")}},G=(t,a,o)=>{const n=t.tables[a];if(n)return S(n,o);const s={};for(const[l,e]of Object.entries(o))s[l]=e!=null&&N.test(l)?"•••":e;return s},R=async(t,a,o)=>{const n=a.tables[o];return n?["_id","_creationTime",...Object.keys(n.shape)]:(await t.all(`PRAGMA table_info(${i(o)})`,[])).map(s=>String(s.name))},k=async(t,a,o)=>{if(a.tables[o])return;const n=await t.all(`PRAGMA foreign_key_list(${i(o)})`,[]);if(n.length===0)return;const s={};for(const l of n){const e=String(l.from),r=String(l.table);s[e]??=r}return s},B=async(t,a)=>{await E(t,a);const o=await p(t);return Promise.all(o.map(async n=>({name:n,rowCount:await $(t,i(n))})))},P=async(t,a,o)=>{const{table:n}=o;if(await E(t,a),!(await p(t)).includes(n))throw new _("UNKNOWN_TABLE",`unknown table: ${n}`,{status:404});const s=O(Math.trunc(o.limit??L),1,g),l=Math.max(0,Math.trunc(o.offset??0)),e=i(n),r=await R(t,a,n),u=M(a,n,r,o.filters),w=u===void 0?"":` WHERE ${u.where}`,c=u?.params??[],f=await $(t,e,w,c),m=(await t.all(`SELECT * FROM ${e}${w} LIMIT ? OFFSET ?`,[...c,s,l])).map(h=>G(a,n,h)),d=await k(t,a,n);return d===void 0?{columns:r,rows:m,total:f}:{columns:r,refs:d,rows:m,total:f}},K=async(t,a,o)=>{const{column:n,table:s}=o;if(await E(t,a),!(await p(t)).includes(s))throw new _("UNKNOWN_TABLE",`unknown table: ${s}`,{status:404});const l=await R(t,a,s);if(!l.includes(n))throw new _("UNKNOWN_COLUMN",`unknown column: ${n}`,{status:404});const e=i(s),r=M(a,s,l,o.filters),u=r===void 0?"":` WHERE ${r.where}`,w=r?.params??[];if(a.tables[s]===void 0&&N.test(n)){const b=await $(t,e,u,w);return{truncated:!1,values:b===0?[]:[{count:b,value:"•••"}]}}const c=O(Math.trunc(o.limit??y),1,C),f=i(v(a,s,n)),m=await t.all(`SELECT ${f} AS value, COUNT(*) AS count FROM ${e}${u} GROUP BY ${f} ORDER BY count DESC LIMIT ?`,[...w,c+1]),d=m.length>c,h=d?m.slice(0,c):m;return{truncated:d,values:h.map(b=>({count:Number(b.count),value:b.value}))}};export{K as facetGlobalColumn,B as listGlobalTables,P as readGlobalTablePage};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{sqliteEncode as i,sqliteDecode as n}from"@lunora/sql-store";import{sql as o}from"drizzle-orm";import{sqlAffinityForKind as r}from"../dialect.mjs";const
|
|
1
|
+
import{sqliteEncode as i,sqliteDecode as n}from"@lunora/sql-store";import{sql as o}from"drizzle-orm";import{sqlAffinityForKind as r}from"../dialect.mjs";const s=/unique constraint failed/iu,T={companionTypes:{autoincrementPrimaryKey:"INTEGER PRIMARY KEY AUTOINCREMENT",integer:"INTEGER",key:"TEXT",real:"REAL",text:"TEXT"},columnType:e=>r(e),decode:(e,t)=>n(e,t),encode:e=>i(e),frameworkColumns:()=>[{name:"id",type:"TEXT PRIMARY KEY"},{name:"_creationTime",type:"REAL NOT NULL"}],isUniqueViolation:e=>e instanceof Error&&s.test(e.message),name:"sqlite",supportsFts5:!0,supportsReturning:!0,tableExists:e=>o`SELECT name FROM sqlite_master WHERE type = 'table' AND name = ${e}`};export{T as default};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/d1",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.48",
|
|
4
4
|
"description": "D1 adapter for Lunora .global() tables, wrapping the Sessions API for read-your-writes",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -50,9 +50,9 @@
|
|
|
50
50
|
"access": "public"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@lunora/do": "1.0.0-alpha.
|
|
53
|
+
"@lunora/do": "1.0.0-alpha.52",
|
|
54
54
|
"@lunora/errors": "1.0.0-alpha.8",
|
|
55
|
-
"@lunora/sql-store": "1.0.0-alpha.
|
|
55
|
+
"@lunora/sql-store": "1.0.0-alpha.49",
|
|
56
56
|
"drizzle-orm": "^0.45.2"
|
|
57
57
|
},
|
|
58
58
|
"engines": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{createSqlCtxDb as t,readSqlCdcChanges as e,runSqlAggregateMigrations as i,runSqlCdcMigration as o,runSqlGlobalTableMigrations as s,runSqlRankMigrations as g,runSqlSearchMigrations as l,trimSqlCdcChanges as c}from"@lunora/sql-store";import{createSqlCtxDb as f,decodeGlobalRow as G}from"@lunora/sql-store";import n from"./sqliteDialect-JvN44Hjf.mjs";const D=a=>t({...a,dialect:n}),S=(a,r)=>s(a,r,n),q=(a,r)=>i(a,r,n),u=(a,r)=>g(a,r,n),M=(a,r)=>l(a,r,n),b=a=>o(a,n),m=(a,r={})=>e(a,r,n),h=(a,r)=>c(a,r,n);export{D as createD1CtxDb,f as createSqlCtxDb,G as decodeGlobalRow,m as readD1CdcChanges,q as runD1AggregateMigrations,b as runD1CdcMigration,S as runD1GlobalTableMigrations,u as runD1RankMigrations,M as runD1SearchMigrations,h as trimD1CdcChanges};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{toErrorBody as u}from"@lunora/errors";import{runD1GlobalTableMigrations as m}from"./createD1CtxDb-oii8T0ys.mjs";import{quoteIdentifier as f}from"./quoteIdentifier-CObIFRhb.mjs";import{decodeGlobalRow as E}from"@lunora/sql-store";const R=200,g=(o,t)=>{const r=e=>o.tables[e]?.shardMode?.kind==="global";return t&&t.length>0?t.filter(e=>r(e)):Object.keys(o.tables).filter(e=>r(e))},k=(o,t,r)=>{const e=o.tables[t];return e?E(e,r):{_creationTime:r._creationTime,_id:r.id}},O=async function*(o,t,r){const e=g(t,r.tables),a=r.batchSize??R;await m(o,t);for(const i of e){const n=f(i);let c,s=!0;for(;s;){const l=c===void 0?await o.all(`SELECT * FROM ${n} ORDER BY "id" LIMIT ?`,[a]):await o.all(`SELECT * FROM ${n} WHERE "id" > ? ORDER BY "id" LIMIT ?`,[c,a]);for(const b of l)yield{doc:k(t,i,b),table:i};const d=l.at(-1);d!==void 0&&(c=String(d.id)),s=l.length===a}}},w=(o,t,r)=>{const e=o.tables[t];if(!e)return`unknown table: ${t}`;for(const[a,i]of Object.entries(e.shape)){const n=r[a],c=i.kind==="optional";if(n===void 0&&c)continue;const s=i.parse;if(typeof s=="function")try{s(n)}catch(l){const d=l instanceof Error?l.message:String(l);return`field "${a}": ${d}`}}},y=async(o,t,r,e)=>{try{return t?(await t.all(`SELECT 1 AS hit FROM ${f(r)} WHERE "id" = ? LIMIT 1`,[e])).length>0:await o.get(e)!==null}catch{return!1}},p=async(o,t,r,e,a)=>{const{doc:i,table:n}=e;if(t.tables[n]?.shardMode?.kind!=="global")return{kind:"skip"};if(!i||typeof i!="object"||Array.isArray(i))return{error:{code:"BAD_ROW",line:a,message:"row is missing or malformed `doc`",table:n},kind:"error"};const c=w(t,n,i);if(c!==void 0)return{error:{code:"VALIDATION_ERROR",line:a,message:c,table:n},kind:"error"};const s=typeof i._id=="string"?i._id:void 0;if(s!==void 0&&await y(o,r.exec,n,s))return{kind:"conflict"};try{return await o.insert(n,i,{allowExplicitId:!0}),{inserted:n,kind:"inserted"}}catch(l){const{body:d}=u(l,{fallbackCode:"INSERT_FAILED"});return{error:{code:d.code,line:a,message:d.message,table:n},kind:"error"}}},M=async(o,t,r)=>{const e=[],a={};let i=0,n=(r.startLine??1)-1;for(const c of r.rows){n+=1;const s=await p(o,t,r,c,n);switch(s.kind){case"conflict":{i+=1;break}case"error":{e.push(s.error);break}case"inserted":{a[s.inserted]=(a[s.inserted]??0)+1;break}}}return{conflicts:i,errors:e,inserted:a}};export{O as exportGlobalRows,M as importGlobalRows,g as selectGlobalTables};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{LunoraError as _}from"@lunora/errors";import{runD1GlobalTableMigrations as T}from"./createD1CtxDb-oii8T0ys.mjs";import{quoteIdentifier as i}from"./quoteIdentifier-CObIFRhb.mjs";import{decodeGlobalRow as S}from"@lunora/sql-store";const E=(t,a)=>T(t,a),L=50,g=500,y=30,C=200,O=(t,a,o)=>Math.min(Math.max(t,a),o),A=/^sqlite_|^_cf_|^d1_|^__cdc|__agg_|__rank_|__fts_/u,U=t=>A.test(t),N=/password|secret|token|hash|salt|credential/iu,$=async t=>(await t.all("SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name",[])).map(a=>String(a.name)).filter(a=>!U(a)),p=async(t,a,o="",n=[])=>{const s=await t.all(`SELECT COUNT(*) AS c FROM ${a}${o}`,n);return Number(s[0]?.c??0)},v=(t,a,o)=>t.tables[a]!==void 0&&o==="_id"?"id":o,M=(t,a,o,n)=>{if(n===void 0||n.length===0)return;const s=[],l=[];for(const e of n){if(!o.includes(e.column))throw new _("UNKNOWN_COLUMN",`unknown column: ${e.column}`,{status:404});if(t.tables[a]===void 0&&N.test(e.column))throw new _("FORBIDDEN",`cannot filter on a redacted column: ${e.column}`,{status:403});const r=i(v(t,a,e.column));e.value===null||e.value===void 0?s.push(`${r} IS NULL`):(s.push(`${r} = ?`),l.push(e.value))}return{params:l,where:s.join(" AND ")}},G=(t,a,o)=>{const n=t.tables[a];if(n)return S(n,o);const s={};for(const[l,e]of Object.entries(o))s[l]=e!=null&&N.test(l)?"•••":e;return s},R=async(t,a,o)=>{const n=a.tables[o];return n?["_id","_creationTime",...Object.keys(n.shape)]:(await t.all(`PRAGMA table_info(${i(o)})`,[])).map(s=>String(s.name))},k=async(t,a,o)=>{if(a.tables[o])return;const n=await t.all(`PRAGMA foreign_key_list(${i(o)})`,[]);if(n.length===0)return;const s={};for(const l of n){const e=String(l.from),r=String(l.table);s[e]??=r}return s},B=async(t,a)=>{await E(t,a);const o=await $(t);return Promise.all(o.map(async n=>({name:n,rowCount:await p(t,i(n))})))},P=async(t,a,o)=>{const{table:n}=o;if(await E(t,a),!(await $(t)).includes(n))throw new _("UNKNOWN_TABLE",`unknown table: ${n}`,{status:404});const s=O(Math.trunc(o.limit??L),1,g),l=Math.max(0,Math.trunc(o.offset??0)),e=i(n),r=await R(t,a,n),u=M(a,n,r,o.filters),w=u===void 0?"":` WHERE ${u.where}`,c=u?.params??[],f=await p(t,e,w,c),m=(await t.all(`SELECT * FROM ${e}${w} LIMIT ? OFFSET ?`,[...c,s,l])).map(h=>G(a,n,h)),d=await k(t,a,n);return d===void 0?{columns:r,rows:m,total:f}:{columns:r,refs:d,rows:m,total:f}},K=async(t,a,o)=>{const{column:n,table:s}=o;if(await E(t,a),!(await $(t)).includes(s))throw new _("UNKNOWN_TABLE",`unknown table: ${s}`,{status:404});const l=await R(t,a,s);if(!l.includes(n))throw new _("UNKNOWN_COLUMN",`unknown column: ${n}`,{status:404});const e=i(s),r=M(a,s,l,o.filters),u=r===void 0?"":` WHERE ${r.where}`,w=r?.params??[];if(a.tables[s]===void 0&&N.test(n)){const b=await p(t,e,u,w);return{truncated:!1,values:b===0?[]:[{count:b,value:"•••"}]}}const c=O(Math.trunc(o.limit??y),1,C),f=i(v(a,s,n)),m=await t.all(`SELECT ${f} AS value, COUNT(*) AS count FROM ${e}${u} GROUP BY ${f} ORDER BY count DESC LIMIT ?`,[...w,c+1]),d=m.length>c,h=d?m.slice(0,c):m;return{truncated:d,values:h.map(b=>({count:Number(b.count),value:b.value}))}};export{K as facetGlobalColumn,B as listGlobalTables,P as readGlobalTablePage};
|