@hono-crud/drizzle 0.1.17 → 0.1.18
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/CHANGELOG.md +14 -0
- package/dist/index.d.ts +33 -14
- package/dist/index.js +2 -2
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @hono-crud/drizzle
|
|
2
2
|
|
|
3
|
+
## 0.1.18
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 3cb6910: Fix a cross-tenant data leak in the version endpoints. `versionHistory`,
|
|
8
|
+
`versionRead`, `versionCompare`, and `versionRollback` did not apply the model's
|
|
9
|
+
`multiTenant` owner-scope, so any authenticated user who knew a record id could
|
|
10
|
+
read (or roll back) another tenant's version history — while the base CRUD reads
|
|
11
|
+
correctly 404'd. All four endpoints now gate on a tenant-scoped `recordExists`
|
|
12
|
+
(the parent record must exist AND belong to the caller's tenant), matching base
|
|
13
|
+
reads; owning the record implies owning its versions since record ids are
|
|
14
|
+
unique. New `CrudEndpoint#getTenantScope()` helper; the Drizzle and Memory
|
|
15
|
+
adapters scope their existence check by the tenant field.
|
|
16
|
+
|
|
3
17
|
## 0.1.17
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -651,7 +651,7 @@ declare abstract class DrizzleBulkPatchEndpoint<E extends Env = Env, M extends M
|
|
|
651
651
|
}
|
|
652
652
|
/**
|
|
653
653
|
* Drizzle Version History endpoint.
|
|
654
|
-
* Lists all versions for a record.
|
|
654
|
+
* Lists all versions for a record (owner-scoped parent-record check).
|
|
655
655
|
*/
|
|
656
656
|
declare abstract class DrizzleVersionHistoryEndpoint<E extends Env = Env, M extends MetaInput = MetaInput, DB extends DrizzleDatabaseConstraint = DrizzleDatabaseConstraint> extends VersionHistoryEndpoint<E, M> {
|
|
657
657
|
/** Drizzle database instance. Can be undefined if using context injection. */
|
|
@@ -660,30 +660,45 @@ declare abstract class DrizzleVersionHistoryEndpoint<E extends Env = Env, M exte
|
|
|
660
660
|
protected getDb(): DB;
|
|
661
661
|
protected getTable(): DrizzleTable;
|
|
662
662
|
protected getColumn(field: string): DrizzleColumn;
|
|
663
|
-
protected recordExists(lookupValue: string
|
|
663
|
+
protected recordExists(lookupValue: string, tenantScope?: {
|
|
664
|
+
field: string;
|
|
665
|
+
value: string;
|
|
666
|
+
}): Promise<boolean>;
|
|
664
667
|
}
|
|
665
668
|
/**
|
|
666
669
|
* Drizzle Version Read endpoint.
|
|
667
|
-
* Gets a specific version of a record.
|
|
668
|
-
*
|
|
669
|
-
* Unlike the db-touching endpoints, this is a pure pass-through to the core
|
|
670
|
-
* base class and performs no Drizzle queries, so it intentionally takes only
|
|
671
|
-
* `<E, M>` — there is no third `DB` generic to parametrize.
|
|
670
|
+
* Gets a specific version of a record. Owner-scopes the parent-record existence
|
|
671
|
+
* check so another tenant's version is 404.
|
|
672
672
|
*/
|
|
673
|
-
declare abstract class DrizzleVersionReadEndpoint<E extends Env = Env, M extends MetaInput = MetaInput> extends VersionReadEndpoint<E, M> {
|
|
673
|
+
declare abstract class DrizzleVersionReadEndpoint<E extends Env = Env, M extends MetaInput = MetaInput, DB extends DrizzleDatabaseConstraint = DrizzleDatabaseConstraint> extends VersionReadEndpoint<E, M> {
|
|
674
|
+
/** Drizzle database instance. Can be undefined if using context injection. */
|
|
675
|
+
db?: DB;
|
|
676
|
+
protected getDb(): DB;
|
|
677
|
+
protected getTable(): DrizzleTable;
|
|
678
|
+
protected getColumn(field: string): DrizzleColumn;
|
|
679
|
+
protected recordExists(lookupValue: string, tenantScope?: {
|
|
680
|
+
field: string;
|
|
681
|
+
value: string;
|
|
682
|
+
}): Promise<boolean>;
|
|
674
683
|
}
|
|
675
684
|
/**
|
|
676
685
|
* Drizzle Version Compare endpoint.
|
|
677
|
-
* Compares two versions of a record.
|
|
678
|
-
*
|
|
679
|
-
* Like {@link DrizzleVersionReadEndpoint}, this is a pure pass-through with no
|
|
680
|
-
* Drizzle queries, so it intentionally takes only `<E, M>` (no `DB` generic).
|
|
686
|
+
* Compares two versions of a record (owner-scoped parent-record check).
|
|
681
687
|
*/
|
|
682
|
-
declare abstract class DrizzleVersionCompareEndpoint<E extends Env = Env, M extends MetaInput = MetaInput> extends VersionCompareEndpoint<E, M> {
|
|
688
|
+
declare abstract class DrizzleVersionCompareEndpoint<E extends Env = Env, M extends MetaInput = MetaInput, DB extends DrizzleDatabaseConstraint = DrizzleDatabaseConstraint> extends VersionCompareEndpoint<E, M> {
|
|
689
|
+
/** Drizzle database instance. Can be undefined if using context injection. */
|
|
690
|
+
db?: DB;
|
|
691
|
+
protected getDb(): DB;
|
|
692
|
+
protected getTable(): DrizzleTable;
|
|
693
|
+
protected getColumn(field: string): DrizzleColumn;
|
|
694
|
+
protected recordExists(lookupValue: string, tenantScope?: {
|
|
695
|
+
field: string;
|
|
696
|
+
value: string;
|
|
697
|
+
}): Promise<boolean>;
|
|
683
698
|
}
|
|
684
699
|
/**
|
|
685
700
|
* Drizzle Version Rollback endpoint.
|
|
686
|
-
* Rolls back a record to a previous version.
|
|
701
|
+
* Rolls back a record to a previous version (owner-scoped before mutating).
|
|
687
702
|
*/
|
|
688
703
|
declare abstract class DrizzleVersionRollbackEndpoint<E extends Env = Env, M extends MetaInput = MetaInput, DB extends DrizzleDatabaseConstraint = DrizzleDatabaseConstraint> extends VersionRollbackEndpoint<E, M> {
|
|
689
704
|
/** Drizzle database instance. Can be undefined if using context injection. */
|
|
@@ -692,6 +707,10 @@ declare abstract class DrizzleVersionRollbackEndpoint<E extends Env = Env, M ext
|
|
|
692
707
|
protected getDb(): DB;
|
|
693
708
|
protected getTable(): DrizzleTable;
|
|
694
709
|
protected getColumn(field: string): DrizzleColumn;
|
|
710
|
+
protected recordExists(lookupValue: string, tenantScope?: {
|
|
711
|
+
field: string;
|
|
712
|
+
value: string;
|
|
713
|
+
}): Promise<boolean>;
|
|
695
714
|
rollback(lookupValue: string, versionData: Record<string, unknown>, newVersion: number): Promise<ModelObject<M['model']>>;
|
|
696
715
|
}
|
|
697
716
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {getTableColumns,between,isNull,isNotNull,notInArray,inArray,lte,lt,gte,gt,ne as ne$1,eq,sql,and,desc,asc,or}from'drizzle-orm';import {resolveRelationValueAsync,loadRelationsForItem,batchLoadRelations,assertNever,CreateEndpoint,getLogger,ReadEndpoint,UpdateEndpoint,DeleteEndpoint,ListEndpoint,buildCursorPage,RestoreEndpoint,BatchCreateEndpoint,BatchUpdateEndpoint,BatchDeleteEndpoint,BatchRestoreEndpoint,UpsertEndpoint,BatchUpsertEndpoint,BulkPatchEndpoint,VersionHistoryEndpoint,VersionReadEndpoint,VersionCompareEndpoint,VersionRollbackEndpoint,AggregateEndpoint,isFilterOperator,computeAggregations,SearchEndpoint,searchInMemory,ExportEndpoint,ImportEndpoint,CloneEndpoint,CONTEXT_KEYS,ConfigurationException,decodeCursor}from'hono-crud/internal';import {sqliteTable,text,integer}from'drizzle-orm/sqlite-core';import {z}from'zod';function W(o){return o}function g(...o){return and(...o)}function ee(...o){return or(...o)}var
|
|
1
|
+
import {getTableColumns,between,isNull,isNotNull,notInArray,inArray,lte,lt,gte,gt,ne as ne$1,eq,sql,and,desc,asc,or}from'drizzle-orm';import {resolveRelationValueAsync,loadRelationsForItem,batchLoadRelations,assertNever,CreateEndpoint,getLogger,ReadEndpoint,UpdateEndpoint,DeleteEndpoint,ListEndpoint,buildCursorPage,RestoreEndpoint,BatchCreateEndpoint,BatchUpdateEndpoint,BatchDeleteEndpoint,BatchRestoreEndpoint,UpsertEndpoint,BatchUpsertEndpoint,BulkPatchEndpoint,VersionHistoryEndpoint,VersionReadEndpoint,VersionCompareEndpoint,VersionRollbackEndpoint,AggregateEndpoint,isFilterOperator,computeAggregations,SearchEndpoint,searchInMemory,ExportEndpoint,ImportEndpoint,CloneEndpoint,CONTEXT_KEYS,ConfigurationException,decodeCursor}from'hono-crud/internal';import {sqliteTable,text,integer}from'drizzle-orm/sqlite-core';import {z}from'zod';function W(o){return o}function g(...o){return and(...o)}function ee(...o){return or(...o)}var Ye=["sqlite","pg","mysql"];function b(o){if(!o.model.table)throw new Error(`Model ${o.model.tableName} does not have a table reference`);return o.model.table}function p(o,e){let n=getTableColumns(o),t=n[e];if(!t)throw new Error(`Column '${e}' not found in table. Available columns: ${Object.keys(n).join(", ")}`);return t}function ye(o){return {resolveRelation:e=>e.table??null,fetchRelated:(e,n,t,r)=>{let i=[inArray(p(e,n),t)];return r?.tenantField!=null&&r.tenantValue!=null&&i.push(eq(p(e,r.tenantField),r.tenantValue)),r?.excludeDeletedField!=null&&i.push(isNull(p(e,r.excludeDeletedField))),o.select().from(e).where(i.length===1?i[0]:and(...i))}}}async function Ge(o,e,n,t){let r=t.table;if(!r)return e;let i=ye(o),s=await resolveRelationValueAsync(e,t,r,i.fetchRelated);return {...e,[n]:s}}async function Ce(o,e,n,t){return loadRelationsForItem(e,n,ye(o),t)}async function S(o,e,n,t){return batchLoadRelations(e,n,ye(o),t)}function H(o,e,n="sqlite"){let t=p(o,e.field);switch(e.operator){case "eq":return eq(t,e.value);case "ne":return ne$1(t,e.value);case "gt":return gt(t,e.value);case "gte":return gte(t,e.value);case "lt":return lt(t,e.value);case "lte":return lte(t,e.value);case "in":return inArray(t,e.value);case "nin":return notInArray(t,e.value);case "like":return j(t,String(e.value).replace(/%/g,""),n,{caseSensitive:true});case "ilike":return j(t,String(e.value).replace(/%/g,""),n);case "null":return e.value?isNull(t):isNotNull(t);case "between":{let[r,i]=e.value;return between(t,r,i)}default:return assertNever(e.operator)}}function k(o){return Number(o[0]?.count)||0}async function J(o){let{db:e,table:n,filters:t,dialect:r,searchFields:i=[],softDeleteConfig:s,defaultPerPage:a=20,extraConditions:l=[],cursorField:c}=o,u=[];if(s?.enabled){let M=p(n,s.field);t.options.onlyDeleted?u.push(isNotNull(M)):t.options.withDeleted||u.push(isNull(M));}for(let M of t.filters){let v=H(n,M,r);v&&u.push(v);}if(t.options.search&&i.length>0){let M=t.options.search,v=i.map(_e=>j(p(n,_e),M,r));u.push(ee(...v));}u.push(...l);let d=u.length>0?g(...u):void 0,z=await e.select({count:sql`count(*)`}).from(n).where(d),f=k(z),D=c!==void 0&&(t.options.cursor!==void 0||t.options.limit!==void 0),y=d,w=false;if(D&&t.options.cursor){let M=decodeCursor(t.options.cursor);M!==null&&(y=g(d,gt(p(n,c),M)),w=true);}let C=e.select().from(n).where(y);if(t.options.order_by){let M=p(n,t.options.order_by),v=t.options.order_by_direction==="desc"?desc:asc;C=C.orderBy(v(M));}if(D){let M=t.options.limit||t.options.per_page||a;return {records:await C.limit(M+1),totalCount:f,page:0,perPage:M,totalPages:0,cursor:{limit:M,applied:w}}}let R=t.options.page||1,x=t.options.per_page||a,G=await C.limit(x).offset((R-1)*x),Q=Math.ceil(f/x);return {records:G,totalCount:f,page:R,perPage:x,totalPages:Q}}function te(o,e){return {result:o,result_info:{page:e.page,per_page:e.perPage,total_count:e.totalCount,total_pages:e.totalPages,has_next_page:e.page<e.totalPages,has_prev_page:e.page>1}}}async function ne(o,e,n,t,r){let i=[];for(let a of r){let l=t[a];l!==void 0&&i.push(eq(n(a),l));}return i.length===0?null:(await o.select().from(e).where(g(...i)).limit(1))[0]||null}function j(o,e,n,t){if(t?.caseSensitive)switch(n){case "pg":return sql`POSITION(${e} IN ${o}) > 0`;case "mysql":return sql`LOCATE(${e}, ${o}) > 0`;default:return sql`INSTR(${o}, ${e}) > 0`}switch(n){case "pg":return sql`POSITION(LOWER(${e}) IN LOWER(${o})) > 0`;case "mysql":return sql`LOCATE(LOWER(${e}), LOWER(${o})) > 0`;default:return sql`INSTR(LOWER(${o}), LOWER(${e})) > 0`}}function m(o){let e=o;if(e._tx)return e._tx;if(e.db)return e.db;let n=e.context?.get?.(CONTEXT_KEYS.db);if(n)return n;throw new ConfigurationException(`Database not configured. Either:
|
|
2
2
|
1. Set db property: db = myDb;
|
|
3
3
|
2. Use middleware: c.set(CONTEXT_KEYS.db, myDb);
|
|
4
|
-
3. Use factory: createDrizzleCrud(db, meta)`)}var P=class extends CreateEndpoint{db;useTransaction=false;getDb(){return b(this)}getTable(){return m(this._meta)}getRelatedTable(e){return e.table}async create(e,n){let t=n??this.getDb(),r=this.getTable(),i=this.applyManagedInsertFields(e,"drizzle");return (await t.insert(r).values(i).returning())[0]}async createNested(e,n,t,r,i){let s=i??this.getDb(),a=this.getRelatedTable(t);if(!a)return getLogger().warn(`Related table not found for ${n}. Add 'table' to the relation config.`),[];let l=Array.isArray(r)?r:[r],c=[];for(let u of l){if(typeof u!="object"||u===null)continue;let d={...u,id:crypto.randomUUID(),[t.foreignKey]:e},z=await s.insert(a).values(d).returning();z[0]&&c.push(z[0]);}return c}async handle(){return this.useTransaction?this.getDb().transaction(async e=>{this._tx=e;try{return await super.handle()}finally{this._tx=void 0;}}):super.handle()}},I=class extends ReadEndpoint{db;getDb(){return b(this)}getTable(){return m(this._meta)}getColumn(e){return p(this.getTable(),e)}async read(e,n,t){let r=this.getTable(),i=this.getColumn(this.lookupField),s=this.getSoftDeleteConfig(),a=[eq(i,e)];if(n)for(let[u,d]of Object.entries(n))a.push(eq(this.getColumn(u),d));s.enabled&&a.push(isNull(this.getColumn(s.field)));let l=await this.getDb().select().from(r).where(g(...a)).limit(1);return l[0]?await ye(this.getDb(),l[0],this._meta,t):null}},_=class extends UpdateEndpoint{db;useTransaction=false;getDb(){return b(this)}getTable(){return m(this._meta)}getColumn(e){return p(this.getTable(),e)}getRelatedTable(e){return e.table}async findExisting(e,n,t){let r=t??this.getDb(),i=this.getTable(),s=this.getColumn(this.lookupField),a=this.getSoftDeleteConfig(),l=[eq(s,e)];if(n)for(let[u,d]of Object.entries(n))l.push(eq(this.getColumn(u),d));return a.enabled&&l.push(isNull(this.getColumn(a.field))),(await r.select().from(i).where(g(...l)).limit(1))[0]||null}async update(e,n,t,r){let i=r??this.getDb(),s=this.getTable(),a=this.getColumn(this.lookupField),l=this.getSoftDeleteConfig(),c=[eq(a,e)];if(t)for(let[d,z]of Object.entries(t))c.push(eq(this.getColumn(d),z));return l.enabled&&c.push(isNull(this.getColumn(l.field))),(await i.update(s).set(this.applyManagedUpdateFields(n)).where(g(...c)).returning())[0]||null}async processNestedWrites(e,n,t,r,i){let s=i??this.getDb(),a=this.getRelatedTable(t);if(!a)return getLogger().warn(`Related table not found for ${n}. Add 'table' to the relation config.`),{created:[],updated:[],deleted:[],connected:[],disconnected:[]};let l={created:[],updated:[],deleted:[],connected:[],disconnected:[]},c=p(a,t.foreignKey),u=p(a,"id");if(r.create){let d=Array.isArray(r.create)?r.create:[r.create];for(let z of d){if(typeof z!="object"||z===null)continue;let f={...z,id:crypto.randomUUID(),[t.foreignKey]:e},D=await s.insert(a).values(f).returning();D[0]&&l.created.push(D[0]);}}if(r.update)for(let d of r.update){if(!d.id||!(await s.select().from(a).where(g(eq(u,d.id),eq(c,e))).limit(1))[0])continue;let{id:f,...D}=d,y=await s.update(a).set(D).where(eq(u,f)).returning();y[0]&&l.updated.push(y[0]);}if(r.delete)for(let d of r.delete)(await s.delete(a).where(g(eq(u,d),eq(c,e))).returning())[0]&&l.deleted.push(d);if(r.connect)for(let d of r.connect)(await s.update(a).set({[t.foreignKey]:e}).where(eq(u,d)).returning())[0]&&l.connected.push(d);if(r.disconnect)for(let d of r.disconnect)(await s.update(a).set({[t.foreignKey]:null}).where(g(eq(u,d),eq(c,e))).returning())[0]&&l.disconnected.push(d);return l}async handle(){return this.useTransaction?this.getDb().transaction(async e=>{this._tx=e;try{return await super.handle()}finally{this._tx=void 0;}}):super.handle()}},A=class extends DeleteEndpoint{db;useTransaction=false;getDb(){return b(this)}getTable(){return m(this._meta)}getColumn(e){return p(this.getTable(),e)}getRelatedTable(e){return e.table}async findForDelete(e,n,t){let r=t??this.getDb(),i=this.getTable(),s=this.getColumn(this.lookupField),a=this.getSoftDeleteConfig(),l=[eq(s,e)];if(n)for(let[u,d]of Object.entries(n))l.push(eq(this.getColumn(u),d));return a.enabled&&l.push(isNull(this.getColumn(a.field))),(await r.select().from(i).where(g(...l)).limit(1))[0]||null}async delete(e,n,t){let r=t??this.getDb(),i=this.getTable(),s=this.getColumn(this.lookupField),a=this.getSoftDeleteConfig(),l=[eq(s,e)];if(n)for(let[c,u]of Object.entries(n))l.push(eq(this.getColumn(c),u));return a.enabled&&l.push(isNull(this.getColumn(a.field))),a.enabled?(await r.update(i).set({[a.field]:new Date}).where(g(...l)).returning())[0]||null:(await r.delete(i).where(g(...l)).returning())[0]||null}async countRelated(e,n,t,r){let i=r??this.getDb(),s=this.getRelatedTable(t);if(!s)return 0;let a=p(s,t.foreignKey),l=await i.select({count:sql`count(*)`}).from(s).where(eq(a,e));return k(l)}async deleteRelated(e,n,t,r){let i=r??this.getDb(),s=this.getRelatedTable(t);if(!s)return 0;let a=p(s,t.foreignKey);return (await i.delete(s).where(eq(a,e)).returning()).length}async nullifyRelated(e,n,t,r){let i=r??this.getDb(),s=this.getRelatedTable(t);if(!s)return 0;let a=p(s,t.foreignKey);return (await i.update(s).set({[t.foreignKey]:null}).where(eq(a,e)).returning()).length}async handle(){return this.useTransaction?this.getDb().transaction(async e=>{this._tx=e;try{return await super.handle()}finally{this._tx=void 0;}}):super.handle()}},q=class extends ListEndpoint{db;dialect="sqlite";supportsCursorPagination=true;getDb(){return b(this)}getTable(){return m(this._meta)}getColumn(e){return p(this.getTable(),e)}async list(e){let n=await J({db:this.getDb(),table:this.getTable(),filters:e,dialect:this.dialect,searchFields:this.searchFields,softDeleteConfig:this.getSoftDeleteConfig(),defaultPerPage:this.defaultPerPage,cursorField:this.isCursorPaginationActive()?this.cursorField||"id":void 0}),t={relations:e.options.include||[],scope:this.getRelationScope(e.options.withDeleted)};if(n.cursor){let{items:i,result_info:s}=buildCursorPage({rows:n.records,limit:n.cursor.limit,totalCount:n.totalCount,cursorField:this.cursorField||"id",cursorApplied:n.cursor.applied});return {result:await S(this.getDb(),i,this._meta,t),result_info:s}}let r=await S(this.getDb(),n.records,this._meta,t);return te(r,n)}},F=class extends RestoreEndpoint{db;useTransaction=false;getDb(){return b(this)}getTable(){return m(this._meta)}getColumn(e){return p(this.getTable(),e)}async restore(e,n,t){let r=t??this.getDb(),i=this.getTable(),s=this.getColumn(this.lookupField),a=this.getSoftDeleteConfig(),l=[eq(s,e)];if(n)for(let[u,d]of Object.entries(n))l.push(eq(this.getColumn(u),d));return l.push(isNotNull(this.getColumn(a.field))),(await r.update(i).set({[a.field]:null}).where(g(...l)).returning())[0]||null}async handle(){return this.useTransaction?this.getDb().transaction(async e=>{this._tx=e;try{return await super.handle()}finally{this._tx=void 0;}}):super.handle()}};var U=class extends BatchCreateEndpoint{db;getDb(){return b(this)}getTable(){return m(this._meta)}async batchCreate(e){let n=this.getTable(),t=e.map(i=>this.applyManagedInsertFields(i,"drizzle"));return await this.getDb().insert(n).values(t).returning()}},Z=class extends BatchUpdateEndpoint{db;getDb(){return b(this)}getTable(){return m(this._meta)}getColumn(e){return p(this.getTable(),e)}async batchUpdate(e){let n=this.getTable(),t=this.getColumn(this.lookupField),r=this.getSoftDeleteConfig(),i=[],s=[],a=this.getTenantScopeFilter();for(let l of e){let c=[eq(t,l.id)];r.enabled&&c.push(isNull(this.getColumn(r.field))),a&&c.push(eq(this.getColumn(a.field),a.value));let u=await this.getDb().update(n).set(this.applyManagedUpdateFields(l.data)).where(g(...c)).returning();u[0]?i.push(u[0]):s.push(l.id);}return {updated:i,notFound:s}}},L=class extends BatchDeleteEndpoint{db;getDb(){return b(this)}getTable(){return m(this._meta)}getColumn(e){return p(this.getTable(),e)}async batchDelete(e){let n=this.getTable(),t=this.getColumn(this.lookupField),r=this.getSoftDeleteConfig(),i=[inArray(t,e)];r.enabled&&i.push(isNull(this.getColumn(r.field)));let s=this.getTenantScopeFilter();s&&i.push(eq(this.getColumn(s.field),s.value));let a;r.enabled?a=await this.getDb().update(n).set({[r.field]:new Date}).where(g(...i)).returning():a=await this.getDb().delete(n).where(g(...i)).returning();let l=a,c=new Set(l.map(d=>String(d[this.lookupField]))),u=e.filter(d=>!c.has(d));return {deleted:l,notFound:u}}},N=class extends BatchRestoreEndpoint{db;getDb(){return b(this)}getTable(){return m(this._meta)}getColumn(e){return p(this.getTable(),e)}async batchRestore(e){let n=this.getTable(),t=this.getColumn(this.lookupField),r=this.getSoftDeleteConfig(),i=[inArray(t,e),isNotNull(this.getColumn(r.field))],s=this.getTenantScopeFilter();s&&i.push(eq(this.getColumn(s.field),s.value));let l=await this.getDb().update(n).set({[r.field]:null}).where(g(...i)).returning(),c=new Set(l.map(d=>String(d[this.lookupField]))),u=e.filter(d=>!c.has(d));return {restored:l,notFound:u}}};function St(o){return o.split(/\s+/).filter(e=>e.length>0)}var V=class extends UpsertEndpoint{db;dialect="sqlite";getDb(){return b(this)}getTable(){return m(this._meta)}getColumn(e){return p(this.getTable(),e)}async findExisting(e){return ne(this.getDb(),this.getTable(),n=>this.getColumn(n),e,this.getUpsertKeys())}async create(e){let n=this.getTable(),t=this.applyManagedInsertFields(e,"drizzle");return (await this.getDb().insert(n).values(t).returning())[0]}async update(e,n){let t=this.getTable(),r=this._meta.model.primaryKeys[0],i=e[r];return (await this.getDb().update(t).set(this.applyManagedUpdateFields(n)).where(eq(this.getColumn(r),i)).returning())[0]}async nativeUpsert(e,n){let t=this.getTable(),r=this.getUpsertKeys(),i=this._meta.model.primaryKeys[0],s=this.getSoftDeleteConfig(),a=this.getTimestampsConfig(),l=this.applyManagedInsertFields(e,"drizzle"),c={};for(let[y,w]of Object.entries(e))!r.includes(y)&&y!==i&&(this.createOnlyFields?.includes(y)||(c[y]=w));a.enabled&&(c[a.updatedAt]=Date.now());let u=r.map(y=>this.getColumn(y)),d;s.enabled&&(d=isNull(this.getColumn(s.field)));let z=Object.keys(c).length>0?c:{[i]:sql`${this.getColumn(i)}`},f=this.getDb().insert(t).values(l);return this.dialect==="mysql"?{data:(await f.onDuplicateKeyUpdate({set:z}).returning())[0],created:false}:{data:(await f.onConflictDoUpdate({target:u,set:z,where:d}).returning())[0],created:false}}},K=class extends BatchUpsertEndpoint{db;dialect="sqlite";getDb(){return b(this)}getTable(){return m(this._meta)}getColumn(e){return p(this.getTable(),e)}async findExisting(e){return ne(this.getDb(),this.getTable(),n=>this.getColumn(n),e,this.getUpsertKeys())}async create(e){let n=this.getTable(),t=this.applyManagedInsertFields(e,"drizzle");return (await this.getDb().insert(n).values(t).returning())[0]}async update(e,n){let t=this.getTable(),r=this._meta.model.primaryKeys[0],i=e[r];return (await this.getDb().update(t).set(this.applyManagedUpdateFields(n)).where(eq(this.getColumn(r),i)).returning())[0]}async nativeBatchUpsert(e,n){if(e.length===0)return {items:[],createdCount:0,updatedCount:0,totalCount:0};let t=this.getTable(),r=this.getUpsertKeys(),i=this._meta.model.primaryKeys[0],s=this.getTimestampsConfig(),a=e.map(D=>this.applyManagedInsertFields(D,"drizzle")),l={},c=e[0];for(let D of Object.keys(c))!r.includes(D)&&D!==i&&(this.createOnlyFields?.includes(D)||(l[D]=sql`excluded.${sql.identifier(D)}`));s.enabled&&(l[s.updatedAt]=Date.now());let u=r.map(D=>this.getColumn(D)),d=Object.keys(l).length>0?l:{[i]:sql`${this.getColumn(i)}`},z=this.getDb().insert(t).values(a),f=await(this.dialect==="mysql"?z.onDuplicateKeyUpdate({set:d}):z.onConflictDoUpdate({target:u,set:d})).returning();return {items:f.map((D,y)=>({data:D,created:false,index:y})),createdCount:0,updatedCount:f.length,totalCount:f.length}}},oe=class extends BulkPatchEndpoint{db;dialect="sqlite";getDb(){return b(this)}getTable(){return m(this._meta)}getColumn(e){return p(this.getTable(),e)}buildConditions(e){let n=this.getTable(),t=[];for(let i of e.filters){let s=H(n,i,this.dialect);s&&t.push(s);}let r=this.getSoftDeleteConfig();return r.enabled&&t.push(isNull(this.getColumn(r.field))),t}async countMatching(e){let n=this.buildConditions(e),t=await this.getDb().select({count:sql`count(*)`}).from(this.getTable()).where(g(...n));return k(t)}async applyPatch(e,n){let t=this.buildConditions(n),r=await this.getDb().update(this.getTable()).set(this.applyManagedUpdateFields(e)).where(g(...t)).returning();return {updated:r.length,records:r}}},ie=class extends VersionHistoryEndpoint{db;getDb(){return b(this)}getTable(){return m(this._meta)}getColumn(e){return p(this.getTable(),e)}async recordExists(e){let n=this.getTable(),t=await this.getDb().select({count:sql`count(*)`}).from(n).where(eq(this.getColumn("id"),e));return k(t)>0}},se=class extends VersionReadEndpoint{},ae=class extends VersionCompareEndpoint{},le=class extends VersionRollbackEndpoint{db;getDb(){return b(this)}getTable(){return m(this._meta)}getColumn(e){return p(this.getTable(),e)}async rollback(e,n,t){let r=this.getTable(),i=this.getVersioningConfig().field;return (await this.getDb().update(r).set({...n,[i]:t}).where(eq(this.getColumn("id"),e)).returning())[0]}},de=class extends AggregateEndpoint{db;dialect="sqlite";getDb(){return b(this)}getTable(){return m(this._meta)}getColumn(e){return p(this.getTable(),e)}async aggregate(e){let n=this.getTable(),t=[],r=this.getSoftDeleteConfig();if(r.enabled){let{query:a}=await this.getValidatedData();a?.withDeleted===true||a?.withDeleted==="true"||t.push(isNull(this.getColumn(r.field)));}if(e.filters)for(let[a,l]of Object.entries(e.filters))if(typeof l=="object"&&l!==null)for(let[c,u]of Object.entries(l)){if(!isFilterOperator(c)){t.push(sql`1 = 0`);continue}let d=H(n,{field:a,operator:c,value:u},this.dialect);d&&t.push(d);}else t.push(eq(this.getColumn(a),l));let i=t.length>0?g(...t):void 0,s=await this.getDb().select().from(n).where(i);return computeAggregations(s,e)}},$=class extends SearchEndpoint{db;dialect="sqlite";getDb(){return b(this)}useNativeSearch=false;vectorColumn;vectorConfig="english";getTable(){return m(this._meta)}getColumn(e){return p(this.getTable(),e)}async search(e,n){let t=this.getTable(),r=[],i=this.getSearchableFields(),s=e.fields||Object.keys(i);if(this.useNativeSearch&&this.vectorColumn){let w=this.getColumn(this.vectorColumn),C=e.mode==="phrase"?sql`phraseto_tsquery(${this.vectorConfig}, ${e.query})`:e.mode==="all"?sql`plainto_tsquery(${this.vectorConfig}, ${e.query})`:sql`to_tsquery(${this.vectorConfig}, ${e.query.split(/\s+/).join(" | ")})`;r.push(sql`${w} @@ ${C}`);}else {let w=(C,R)=>{try{let T=this.getColumn(C);return j(sql`CAST(${T} AS TEXT)`,R,this.dialect)}catch{return}};if(e.mode==="all"){let C=St(e.query);if(C.length>0){let R=[];for(let T of C){let G=s.map(Q=>w(Q,T)).filter(Q=>Q!==void 0);G.length>0&&R.push(ee(...G));}R.length>0&&r.push(g(...R));}}else {let C=s.map(R=>w(R,e.query)).filter(R=>R!==void 0);C.length>0&&r.push(ee(...C));}}let a=await J({db:this.getDb(),table:t,filters:n,dialect:this.dialect,softDeleteConfig:this.getSoftDeleteConfig(),defaultPerPage:this.defaultPerPage,extraConditions:r}),l=a.records,c=a.totalCount,u=e.mode==="all"?{...e,mode:"any"}:e,d=searchInMemory(l,u,i),z={relations:n.options.include||[],scope:this.getRelationScope(n.options.withDeleted)},f=d.map(w=>w.item),D=await S(this.getDb(),f,this._meta,z);return {items:d.map((w,C)=>({...w,item:D[C]})),totalCount:c}}},ce=class extends ExportEndpoint{db;dialect="sqlite";getDb(){return b(this)}getTable(){return m(this._meta)}getColumn(e){return p(this.getTable(),e)}async list(e){let n=await J({db:this.getDb(),table:this.getTable(),filters:e,dialect:this.dialect,searchFields:this.searchFields,softDeleteConfig:this.getSoftDeleteConfig(),defaultPerPage:this.defaultPerPage}),t={relations:e.options.include||[],scope:this.getRelationScope(e.options.withDeleted)},r=await S(this.getDb(),n.records,this._meta,t);return te(r,n)}},ue=class extends ImportEndpoint{db;getDb(){return b(this)}getTable(){return m(this._meta)}getColumn(e){return p(this.getTable(),e)}async findExisting(e){return ne(this.getDb(),this.getTable(),n=>this.getColumn(n),e,this.getUpsertKeys())}async create(e){let n=this.getTable(),t=this.applyManagedInsertFields(e,"drizzle");return (await this.getDb().insert(n).values(t).returning())[0]}async update(e,n){let t=this.getTable(),r=this._meta.model.primaryKeys[0],i=e[r];return (await this.getDb().update(t).set(this.applyManagedUpdateFields(n)).where(eq(this.getColumn(r),i)).returning())[0]}},pe=class extends CloneEndpoint{db;getDb(){return b(this)}getTable(){return m(this._meta)}getColumn(e){return p(this.getTable(),e)}generateId(){return crypto.randomUUID()}async findSource(e,n){let t=this.getTable(),r=this.getColumn(this.lookupField),i=this.getSoftDeleteConfig(),s=[eq(r,e)];if(n)for(let[l,c]of Object.entries(n))s.push(eq(this.getColumn(l),c));i.enabled&&s.push(isNull(this.getColumn(i.field)));let a=await this.getDb().select().from(t).where(g(...s)).limit(1);return a[0]?a[0]:null}async createClone(e){let n=this.getTable(),t=this.applyManagedInsertFields(e,"drizzle",()=>this.generateId());return (await this.getDb().insert(n).values(t).returning())[0]}};function Sn(o,e,n){let t=n?.dialect??"sqlite";return {Create:class extends P{_meta=e;db=o},Read:class extends I{_meta=e;db=o},Update:class extends _{_meta=e;db=o},Delete:class extends A{_meta=e;db=o},List:class extends q{_meta=e;db=o;dialect=t},Restore:class extends F{_meta=e;db=o},Upsert:class extends V{_meta=e;db=o;dialect=t},Search:class extends ${_meta=e;db=o;dialect=t},BatchCreate:class extends U{_meta=e;db=o},BatchUpdate:class extends Z{_meta=e;db=o},BatchDelete:class extends L{_meta=e;db=o},BatchRestore:class extends N{_meta=e;db=o},BatchUpsert:class extends K{_meta=e;db=o;dialect=t}}}var Be=class{db;table;constructor(e){this.db=e.db,this.table=e.table;}col(e){return p(this.table,e)}recordScope(e,n){return and(eq(this.col("resourceTable"),e),eq(this.col("recordId"),String(n)))}toEntry(e){return {id:e.id,recordId:e.recordId,version:e.version,data:JSON.parse(e.data),createdAt:new Date(e.createdAt),...e.changedBy!=null?{changedBy:e.changedBy}:{},...e.changeReason!=null?{changeReason:e.changeReason}:{},...e.changes!=null?{changes:JSON.parse(e.changes)}:{}}}async store(e,n){let t=n.createdAt instanceof Date?n.createdAt:new Date(n.createdAt);await this.db.insert(this.table).values({id:n.id,resourceTable:e,recordId:String(n.recordId),version:n.version,data:JSON.stringify(n.data),createdAt:t.getTime(),changedBy:n.changedBy??null,changeReason:n.changeReason??null,changes:n.changes?JSON.stringify(n.changes):null});}async getByRecordId(e,n,t){let r=this.db.select().from(this.table).where(this.recordScope(e,n)).orderBy(desc(this.col("version")));return (t?.limit!=null||t?.offset!=null)&&(r=r.limit(t?.limit??Number.MAX_SAFE_INTEGER)),t?.offset!=null&&(r=r.offset(t.offset)),(await r).map(s=>this.toEntry(s))}async getVersion(e,n,t){let r=await this.db.select().from(this.table).where(and(this.recordScope(e,n),eq(this.col("version"),t))).limit(1);return r.length>0?this.toEntry(r[0]):null}async getLatestVersion(e,n){let t=await this.db.select().from(this.table).where(this.recordScope(e,n)).orderBy(desc(this.col("version"))).limit(1);return t.length>0?t[0].version:0}async pruneVersions(e,n,t){if(t<=0)return this.deleteAllVersions(e,n);let r=await this.getByRecordId(e,n);if(r.length<=t)return 0;let i=r[t-1].version;return (await this.db.delete(this.table).where(and(this.recordScope(e,n),lt(this.col("version"),i))).returning()).length}async deleteAllVersions(e,n){return (await this.db.delete(this.table).where(this.recordScope(e,n)).returning()).length}};function Wn(o="version_history"){return sqliteTable(o,{id:text("id").primaryKey(),resourceTable:text("resource_table").notNull(),recordId:text("record_id").notNull(),version:integer("version").notNull(),data:text("data").notNull(),createdAt:integer("created_at").notNull(),changedBy:text("changed_by"),changeReason:text("change_reason"),changes:text("changes")})}var be=null,je=false,me=null;async function he(){if(je){if(me)throw me;return be}je=true;try{return be=await import('drizzle-zod'),be}catch{throw me=new Error("drizzle-zod is not installed. Please install it: npm install drizzle-zod"),me}}async function jt(o,e){return (await he()).createSelectSchema(o,e)}async function Pt(o,e){return (await he()).createInsertSchema(o,e)}async function It(o,e){let n=await he();return n.createUpdateSchema?n.createUpdateSchema(o,e):n.createInsertSchema(o,e).partial()}async function _t(o,e){let n=await he(),t=e?.coerceDates!==false,r=t?Ut(o):new Set,i=n.createSelectSchema(o,e?.selectRefine),s=n.createInsertSchema(o,e?.insertRefine),a;return n.createUpdateSchema?a=n.createUpdateSchema(o,e?.updateRefine):a=n.createInsertSchema(o,e?.updateRefine).partial(),t&&r.size>0&&(s=Pe(s,r),a=Pe(a,r)),{select:i,insert:s,update:a}}function At(){return be!==null}var qt=z.preprocess(o=>{if(o instanceof Date)return o;if(typeof o=="string"){let e=new Date(o);if(!isNaN(e.getTime()))return e}return o},z.date()),Ft=z.preprocess(o=>{if(o==null)return null;if(o instanceof Date)return o;if(typeof o=="string"){let e=new Date(o);if(!isNaN(e.getTime()))return e}return o},z.date().nullable());function Ut(o){let e=new Set,n=o;for(let[t,r]of Object.entries(n)){if(t==="_"||t==="$inferInsert"||t==="$inferSelect")continue;let i=r;if(!i||typeof i!="object")continue;let s=String(i.dataType??"").toLowerCase(),a=String(i.columnType??"").toLowerCase(),l=i.config,c=String(l?.dataType??"").toLowerCase();(s.includes("timestamp")||s.includes("date")||s.includes("datetime")||a.includes("pgtimestamp")||a.includes("pgdate")||a.includes("mysqltimestamp")||a.includes("mysqldate")||a.includes("sqlitetimestamp")||c.includes("timestamp")||c.includes("date"))&&e.add(t);}return e}function Pe(o,e){if(e.size===0)return o;let n=o.shape,t={};for(let[r,i]of Object.entries(n))if(e.has(r)){let s=i.isOptional?.()??false,a=i.isNullable?.()??false,l=qt;(a||s)&&(l=Ft),s&&(l=l.optional()),t[r]=l;}else t[r]=i;return z.object(t)}var tr={CreateEndpoint:P,ListEndpoint:q,ReadEndpoint:I,UpdateEndpoint:_,DeleteEndpoint:A,RestoreEndpoint:F,BatchCreateEndpoint:U,BatchUpdateEndpoint:Z,BatchDeleteEndpoint:L,BatchRestoreEndpoint:N,BatchUpsertEndpoint:K,SearchEndpoint:$,AggregateEndpoint:de,ExportEndpoint:ce,ImportEndpoint:ue,UpsertEndpoint:V,CloneEndpoint:pe,BulkPatchEndpoint:oe,VersionHistoryEndpoint:ie,VersionReadEndpoint:se,VersionCompareEndpoint:ae,VersionRollbackEndpoint:le};export{Xe as DRIZZLE_DIALECTS,tr as DrizzleAdapters,de as DrizzleAggregateEndpoint,U as DrizzleBatchCreateEndpoint,L as DrizzleBatchDeleteEndpoint,N as DrizzleBatchRestoreEndpoint,Z as DrizzleBatchUpdateEndpoint,K as DrizzleBatchUpsertEndpoint,oe as DrizzleBulkPatchEndpoint,pe as DrizzleCloneEndpoint,P as DrizzleCreateEndpoint,A as DrizzleDeleteEndpoint,ce as DrizzleExportEndpoint,ue as DrizzleImportEndpoint,q as DrizzleListEndpoint,I as DrizzleReadEndpoint,F as DrizzleRestoreEndpoint,$ as DrizzleSearchEndpoint,_ as DrizzleUpdateEndpoint,V as DrizzleUpsertEndpoint,ae as DrizzleVersionCompareEndpoint,ie as DrizzleVersionHistoryEndpoint,se as DrizzleVersionReadEndpoint,le as DrizzleVersionRollbackEndpoint,Be as DrizzleVersioningStorage,S as batchLoadDrizzleRelations,H as buildWhereCondition,W as cast,Sn as createDrizzleCrud,_t as createDrizzleSchemas,Pt as createInsertSchema,jt as createSelectSchema,It as createUpdateSchema,p as getColumn,m as getTable,At as isDrizzleZodAvailable,Ye as loadDrizzleRelation,ye as loadDrizzleRelations,k as readCount,Wn as sqliteVersionHistoryTable,j as substringMatch};
|
|
4
|
+
3. Use factory: createDrizzleCrud(db, meta)`)}var P=class extends CreateEndpoint{db;useTransaction=false;getDb(){return m(this)}getTable(){return b(this._meta)}getRelatedTable(e){return e.table}async create(e,n){let t=n??this.getDb(),r=this.getTable(),i=this.applyManagedInsertFields(e,"drizzle");return (await t.insert(r).values(i).returning())[0]}async createNested(e,n,t,r,i){let s=i??this.getDb(),a=this.getRelatedTable(t);if(!a)return getLogger().warn(`Related table not found for ${n}. Add 'table' to the relation config.`),[];let l=Array.isArray(r)?r:[r],c=[];for(let u of l){if(typeof u!="object"||u===null)continue;let d={...u,id:crypto.randomUUID(),[t.foreignKey]:e},z=await s.insert(a).values(d).returning();z[0]&&c.push(z[0]);}return c}async handle(){return this.useTransaction?this.getDb().transaction(async e=>{this._tx=e;try{return await super.handle()}finally{this._tx=void 0;}}):super.handle()}},I=class extends ReadEndpoint{db;getDb(){return m(this)}getTable(){return b(this._meta)}getColumn(e){return p(this.getTable(),e)}async read(e,n,t){let r=this.getTable(),i=this.getColumn(this.lookupField),s=this.getSoftDeleteConfig(),a=[eq(i,e)];if(n)for(let[u,d]of Object.entries(n))a.push(eq(this.getColumn(u),d));s.enabled&&a.push(isNull(this.getColumn(s.field)));let l=await this.getDb().select().from(r).where(g(...a)).limit(1);return l[0]?await Ce(this.getDb(),l[0],this._meta,t):null}},_=class extends UpdateEndpoint{db;useTransaction=false;getDb(){return m(this)}getTable(){return b(this._meta)}getColumn(e){return p(this.getTable(),e)}getRelatedTable(e){return e.table}async findExisting(e,n,t){let r=t??this.getDb(),i=this.getTable(),s=this.getColumn(this.lookupField),a=this.getSoftDeleteConfig(),l=[eq(s,e)];if(n)for(let[u,d]of Object.entries(n))l.push(eq(this.getColumn(u),d));return a.enabled&&l.push(isNull(this.getColumn(a.field))),(await r.select().from(i).where(g(...l)).limit(1))[0]||null}async update(e,n,t,r){let i=r??this.getDb(),s=this.getTable(),a=this.getColumn(this.lookupField),l=this.getSoftDeleteConfig(),c=[eq(a,e)];if(t)for(let[d,z]of Object.entries(t))c.push(eq(this.getColumn(d),z));return l.enabled&&c.push(isNull(this.getColumn(l.field))),(await i.update(s).set(this.applyManagedUpdateFields(n)).where(g(...c)).returning())[0]||null}async processNestedWrites(e,n,t,r,i){let s=i??this.getDb(),a=this.getRelatedTable(t);if(!a)return getLogger().warn(`Related table not found for ${n}. Add 'table' to the relation config.`),{created:[],updated:[],deleted:[],connected:[],disconnected:[]};let l={created:[],updated:[],deleted:[],connected:[],disconnected:[]},c=p(a,t.foreignKey),u=p(a,"id");if(r.create){let d=Array.isArray(r.create)?r.create:[r.create];for(let z of d){if(typeof z!="object"||z===null)continue;let f={...z,id:crypto.randomUUID(),[t.foreignKey]:e},D=await s.insert(a).values(f).returning();D[0]&&l.created.push(D[0]);}}if(r.update)for(let d of r.update){if(!d.id||!(await s.select().from(a).where(g(eq(u,d.id),eq(c,e))).limit(1))[0])continue;let{id:f,...D}=d,y=await s.update(a).set(D).where(eq(u,f)).returning();y[0]&&l.updated.push(y[0]);}if(r.delete)for(let d of r.delete)(await s.delete(a).where(g(eq(u,d),eq(c,e))).returning())[0]&&l.deleted.push(d);if(r.connect)for(let d of r.connect)(await s.update(a).set({[t.foreignKey]:e}).where(eq(u,d)).returning())[0]&&l.connected.push(d);if(r.disconnect)for(let d of r.disconnect)(await s.update(a).set({[t.foreignKey]:null}).where(g(eq(u,d),eq(c,e))).returning())[0]&&l.disconnected.push(d);return l}async handle(){return this.useTransaction?this.getDb().transaction(async e=>{this._tx=e;try{return await super.handle()}finally{this._tx=void 0;}}):super.handle()}},A=class extends DeleteEndpoint{db;useTransaction=false;getDb(){return m(this)}getTable(){return b(this._meta)}getColumn(e){return p(this.getTable(),e)}getRelatedTable(e){return e.table}async findForDelete(e,n,t){let r=t??this.getDb(),i=this.getTable(),s=this.getColumn(this.lookupField),a=this.getSoftDeleteConfig(),l=[eq(s,e)];if(n)for(let[u,d]of Object.entries(n))l.push(eq(this.getColumn(u),d));return a.enabled&&l.push(isNull(this.getColumn(a.field))),(await r.select().from(i).where(g(...l)).limit(1))[0]||null}async delete(e,n,t){let r=t??this.getDb(),i=this.getTable(),s=this.getColumn(this.lookupField),a=this.getSoftDeleteConfig(),l=[eq(s,e)];if(n)for(let[c,u]of Object.entries(n))l.push(eq(this.getColumn(c),u));return a.enabled&&l.push(isNull(this.getColumn(a.field))),a.enabled?(await r.update(i).set({[a.field]:new Date}).where(g(...l)).returning())[0]||null:(await r.delete(i).where(g(...l)).returning())[0]||null}async countRelated(e,n,t,r){let i=r??this.getDb(),s=this.getRelatedTable(t);if(!s)return 0;let a=p(s,t.foreignKey),l=await i.select({count:sql`count(*)`}).from(s).where(eq(a,e));return k(l)}async deleteRelated(e,n,t,r){let i=r??this.getDb(),s=this.getRelatedTable(t);if(!s)return 0;let a=p(s,t.foreignKey);return (await i.delete(s).where(eq(a,e)).returning()).length}async nullifyRelated(e,n,t,r){let i=r??this.getDb(),s=this.getRelatedTable(t);if(!s)return 0;let a=p(s,t.foreignKey);return (await i.update(s).set({[t.foreignKey]:null}).where(eq(a,e)).returning()).length}async handle(){return this.useTransaction?this.getDb().transaction(async e=>{this._tx=e;try{return await super.handle()}finally{this._tx=void 0;}}):super.handle()}},q=class extends ListEndpoint{db;dialect="sqlite";supportsCursorPagination=true;getDb(){return m(this)}getTable(){return b(this._meta)}getColumn(e){return p(this.getTable(),e)}async list(e){let n=await J({db:this.getDb(),table:this.getTable(),filters:e,dialect:this.dialect,searchFields:this.searchFields,softDeleteConfig:this.getSoftDeleteConfig(),defaultPerPage:this.defaultPerPage,cursorField:this.isCursorPaginationActive()?this.cursorField||"id":void 0}),t={relations:e.options.include||[],scope:this.getRelationScope(e.options.withDeleted)};if(n.cursor){let{items:i,result_info:s}=buildCursorPage({rows:n.records,limit:n.cursor.limit,totalCount:n.totalCount,cursorField:this.cursorField||"id",cursorApplied:n.cursor.applied});return {result:await S(this.getDb(),i,this._meta,t),result_info:s}}let r=await S(this.getDb(),n.records,this._meta,t);return te(r,n)}},F=class extends RestoreEndpoint{db;useTransaction=false;getDb(){return m(this)}getTable(){return b(this._meta)}getColumn(e){return p(this.getTable(),e)}async restore(e,n,t){let r=t??this.getDb(),i=this.getTable(),s=this.getColumn(this.lookupField),a=this.getSoftDeleteConfig(),l=[eq(s,e)];if(n)for(let[u,d]of Object.entries(n))l.push(eq(this.getColumn(u),d));return l.push(isNotNull(this.getColumn(a.field))),(await r.update(i).set({[a.field]:null}).where(g(...l)).returning())[0]||null}async handle(){return this.useTransaction?this.getDb().transaction(async e=>{this._tx=e;try{return await super.handle()}finally{this._tx=void 0;}}):super.handle()}};var U=class extends BatchCreateEndpoint{db;getDb(){return m(this)}getTable(){return b(this._meta)}async batchCreate(e){let n=this.getTable(),t=e.map(i=>this.applyManagedInsertFields(i,"drizzle"));return await this.getDb().insert(n).values(t).returning()}},Z=class extends BatchUpdateEndpoint{db;getDb(){return m(this)}getTable(){return b(this._meta)}getColumn(e){return p(this.getTable(),e)}async batchUpdate(e){let n=this.getTable(),t=this.getColumn(this.lookupField),r=this.getSoftDeleteConfig(),i=[],s=[],a=this.getTenantScopeFilter();for(let l of e){let c=[eq(t,l.id)];r.enabled&&c.push(isNull(this.getColumn(r.field))),a&&c.push(eq(this.getColumn(a.field),a.value));let u=await this.getDb().update(n).set(this.applyManagedUpdateFields(l.data)).where(g(...c)).returning();u[0]?i.push(u[0]):s.push(l.id);}return {updated:i,notFound:s}}},L=class extends BatchDeleteEndpoint{db;getDb(){return m(this)}getTable(){return b(this._meta)}getColumn(e){return p(this.getTable(),e)}async batchDelete(e){let n=this.getTable(),t=this.getColumn(this.lookupField),r=this.getSoftDeleteConfig(),i=[inArray(t,e)];r.enabled&&i.push(isNull(this.getColumn(r.field)));let s=this.getTenantScopeFilter();s&&i.push(eq(this.getColumn(s.field),s.value));let a;r.enabled?a=await this.getDb().update(n).set({[r.field]:new Date}).where(g(...i)).returning():a=await this.getDb().delete(n).where(g(...i)).returning();let l=a,c=new Set(l.map(d=>String(d[this.lookupField]))),u=e.filter(d=>!c.has(d));return {deleted:l,notFound:u}}},N=class extends BatchRestoreEndpoint{db;getDb(){return m(this)}getTable(){return b(this._meta)}getColumn(e){return p(this.getTable(),e)}async batchRestore(e){let n=this.getTable(),t=this.getColumn(this.lookupField),r=this.getSoftDeleteConfig(),i=[inArray(t,e),isNotNull(this.getColumn(r.field))],s=this.getTenantScopeFilter();s&&i.push(eq(this.getColumn(s.field),s.value));let l=await this.getDb().update(n).set({[r.field]:null}).where(g(...i)).returning(),c=new Set(l.map(d=>String(d[this.lookupField]))),u=e.filter(d=>!c.has(d));return {restored:l,notFound:u}}};function kt(o){return o.split(/\s+/).filter(e=>e.length>0)}var V=class extends UpsertEndpoint{db;dialect="sqlite";getDb(){return m(this)}getTable(){return b(this._meta)}getColumn(e){return p(this.getTable(),e)}async findExisting(e){return ne(this.getDb(),this.getTable(),n=>this.getColumn(n),e,this.getUpsertKeys())}async create(e){let n=this.getTable(),t=this.applyManagedInsertFields(e,"drizzle");return (await this.getDb().insert(n).values(t).returning())[0]}async update(e,n){let t=this.getTable(),r=this._meta.model.primaryKeys[0],i=e[r];return (await this.getDb().update(t).set(this.applyManagedUpdateFields(n)).where(eq(this.getColumn(r),i)).returning())[0]}async nativeUpsert(e,n){let t=this.getTable(),r=this.getUpsertKeys(),i=this._meta.model.primaryKeys[0],s=this.getSoftDeleteConfig(),a=this.getTimestampsConfig(),l=this.applyManagedInsertFields(e,"drizzle"),c={};for(let[y,w]of Object.entries(e))!r.includes(y)&&y!==i&&(this.createOnlyFields?.includes(y)||(c[y]=w));a.enabled&&(c[a.updatedAt]=Date.now());let u=r.map(y=>this.getColumn(y)),d;s.enabled&&(d=isNull(this.getColumn(s.field)));let z=Object.keys(c).length>0?c:{[i]:sql`${this.getColumn(i)}`},f=this.getDb().insert(t).values(l);return this.dialect==="mysql"?{data:(await f.onDuplicateKeyUpdate({set:z}).returning())[0],created:false}:{data:(await f.onConflictDoUpdate({target:u,set:z,where:d}).returning())[0],created:false}}},K=class extends BatchUpsertEndpoint{db;dialect="sqlite";getDb(){return m(this)}getTable(){return b(this._meta)}getColumn(e){return p(this.getTable(),e)}async findExisting(e){return ne(this.getDb(),this.getTable(),n=>this.getColumn(n),e,this.getUpsertKeys())}async create(e){let n=this.getTable(),t=this.applyManagedInsertFields(e,"drizzle");return (await this.getDb().insert(n).values(t).returning())[0]}async update(e,n){let t=this.getTable(),r=this._meta.model.primaryKeys[0],i=e[r];return (await this.getDb().update(t).set(this.applyManagedUpdateFields(n)).where(eq(this.getColumn(r),i)).returning())[0]}async nativeBatchUpsert(e,n){if(e.length===0)return {items:[],createdCount:0,updatedCount:0,totalCount:0};let t=this.getTable(),r=this.getUpsertKeys(),i=this._meta.model.primaryKeys[0],s=this.getTimestampsConfig(),a=e.map(D=>this.applyManagedInsertFields(D,"drizzle")),l={},c=e[0];for(let D of Object.keys(c))!r.includes(D)&&D!==i&&(this.createOnlyFields?.includes(D)||(l[D]=sql`excluded.${sql.identifier(D)}`));s.enabled&&(l[s.updatedAt]=Date.now());let u=r.map(D=>this.getColumn(D)),d=Object.keys(l).length>0?l:{[i]:sql`${this.getColumn(i)}`},z=this.getDb().insert(t).values(a),f=await(this.dialect==="mysql"?z.onDuplicateKeyUpdate({set:d}):z.onConflictDoUpdate({target:u,set:d})).returning();return {items:f.map((D,y)=>({data:D,created:false,index:y})),createdCount:0,updatedCount:f.length,totalCount:f.length}}},oe=class extends BulkPatchEndpoint{db;dialect="sqlite";getDb(){return m(this)}getTable(){return b(this._meta)}getColumn(e){return p(this.getTable(),e)}buildConditions(e){let n=this.getTable(),t=[];for(let i of e.filters){let s=H(n,i,this.dialect);s&&t.push(s);}let r=this.getSoftDeleteConfig();return r.enabled&&t.push(isNull(this.getColumn(r.field))),t}async countMatching(e){let n=this.buildConditions(e),t=await this.getDb().select({count:sql`count(*)`}).from(this.getTable()).where(g(...n));return k(t)}async applyPatch(e,n){let t=this.buildConditions(n),r=await this.getDb().update(this.getTable()).set(this.applyManagedUpdateFields(e)).where(g(...t)).returning();return {updated:r.length,records:r}}};async function be(o,e,n,t,r){let i=r?g(eq(n,t),eq(p(e,r.field),r.value)):eq(n,t),s=await o.select({count:sql`count(*)`}).from(e).where(i);return k(s)>0}var ie=class extends VersionHistoryEndpoint{db;getDb(){return m(this)}getTable(){return b(this._meta)}getColumn(e){return p(this.getTable(),e)}async recordExists(e,n){return be(this.getDb(),this.getTable(),this.getColumn("id"),e,n)}},se=class extends VersionReadEndpoint{db;getDb(){return m(this)}getTable(){return b(this._meta)}getColumn(e){return p(this.getTable(),e)}async recordExists(e,n){return be(this.getDb(),this.getTable(),this.getColumn("id"),e,n)}},ae=class extends VersionCompareEndpoint{db;getDb(){return m(this)}getTable(){return b(this._meta)}getColumn(e){return p(this.getTable(),e)}async recordExists(e,n){return be(this.getDb(),this.getTable(),this.getColumn("id"),e,n)}},le=class extends VersionRollbackEndpoint{db;getDb(){return m(this)}getTable(){return b(this._meta)}getColumn(e){return p(this.getTable(),e)}async recordExists(e,n){return be(this.getDb(),this.getTable(),this.getColumn("id"),e,n)}async rollback(e,n,t){let r=this.getTable(),i=this.getVersioningConfig().field;return (await this.getDb().update(r).set({...n,[i]:t}).where(eq(this.getColumn("id"),e)).returning())[0]}},de=class extends AggregateEndpoint{db;dialect="sqlite";getDb(){return m(this)}getTable(){return b(this._meta)}getColumn(e){return p(this.getTable(),e)}async aggregate(e){let n=this.getTable(),t=[],r=this.getSoftDeleteConfig();if(r.enabled){let{query:a}=await this.getValidatedData();a?.withDeleted===true||a?.withDeleted==="true"||t.push(isNull(this.getColumn(r.field)));}if(e.filters)for(let[a,l]of Object.entries(e.filters))if(typeof l=="object"&&l!==null)for(let[c,u]of Object.entries(l)){if(!isFilterOperator(c)){t.push(sql`1 = 0`);continue}let d=H(n,{field:a,operator:c,value:u},this.dialect);d&&t.push(d);}else t.push(eq(this.getColumn(a),l));let i=t.length>0?g(...t):void 0,s=await this.getDb().select().from(n).where(i);return computeAggregations(s,e)}},$=class extends SearchEndpoint{db;dialect="sqlite";getDb(){return m(this)}useNativeSearch=false;vectorColumn;vectorConfig="english";getTable(){return b(this._meta)}getColumn(e){return p(this.getTable(),e)}async search(e,n){let t=this.getTable(),r=[],i=this.getSearchableFields(),s=e.fields||Object.keys(i);if(this.useNativeSearch&&this.vectorColumn){let w=this.getColumn(this.vectorColumn),C=e.mode==="phrase"?sql`phraseto_tsquery(${this.vectorConfig}, ${e.query})`:e.mode==="all"?sql`plainto_tsquery(${this.vectorConfig}, ${e.query})`:sql`to_tsquery(${this.vectorConfig}, ${e.query.split(/\s+/).join(" | ")})`;r.push(sql`${w} @@ ${C}`);}else {let w=(C,R)=>{try{let x=this.getColumn(C);return j(sql`CAST(${x} AS TEXT)`,R,this.dialect)}catch{return}};if(e.mode==="all"){let C=kt(e.query);if(C.length>0){let R=[];for(let x of C){let G=s.map(Q=>w(Q,x)).filter(Q=>Q!==void 0);G.length>0&&R.push(ee(...G));}R.length>0&&r.push(g(...R));}}else {let C=s.map(R=>w(R,e.query)).filter(R=>R!==void 0);C.length>0&&r.push(ee(...C));}}let a=await J({db:this.getDb(),table:t,filters:n,dialect:this.dialect,softDeleteConfig:this.getSoftDeleteConfig(),defaultPerPage:this.defaultPerPage,extraConditions:r}),l=a.records,c=a.totalCount,u=e.mode==="all"?{...e,mode:"any"}:e,d=searchInMemory(l,u,i),z={relations:n.options.include||[],scope:this.getRelationScope(n.options.withDeleted)},f=d.map(w=>w.item),D=await S(this.getDb(),f,this._meta,z);return {items:d.map((w,C)=>({...w,item:D[C]})),totalCount:c}}},ce=class extends ExportEndpoint{db;dialect="sqlite";getDb(){return m(this)}getTable(){return b(this._meta)}getColumn(e){return p(this.getTable(),e)}async list(e){let n=await J({db:this.getDb(),table:this.getTable(),filters:e,dialect:this.dialect,searchFields:this.searchFields,softDeleteConfig:this.getSoftDeleteConfig(),defaultPerPage:this.defaultPerPage}),t={relations:e.options.include||[],scope:this.getRelationScope(e.options.withDeleted)},r=await S(this.getDb(),n.records,this._meta,t);return te(r,n)}},ue=class extends ImportEndpoint{db;getDb(){return m(this)}getTable(){return b(this._meta)}getColumn(e){return p(this.getTable(),e)}async findExisting(e){return ne(this.getDb(),this.getTable(),n=>this.getColumn(n),e,this.getUpsertKeys())}async create(e){let n=this.getTable(),t=this.applyManagedInsertFields(e,"drizzle");return (await this.getDb().insert(n).values(t).returning())[0]}async update(e,n){let t=this.getTable(),r=this._meta.model.primaryKeys[0],i=e[r];return (await this.getDb().update(t).set(this.applyManagedUpdateFields(n)).where(eq(this.getColumn(r),i)).returning())[0]}},pe=class extends CloneEndpoint{db;getDb(){return m(this)}getTable(){return b(this._meta)}getColumn(e){return p(this.getTable(),e)}generateId(){return crypto.randomUUID()}async findSource(e,n){let t=this.getTable(),r=this.getColumn(this.lookupField),i=this.getSoftDeleteConfig(),s=[eq(r,e)];if(n)for(let[l,c]of Object.entries(n))s.push(eq(this.getColumn(l),c));i.enabled&&s.push(isNull(this.getColumn(i.field)));let a=await this.getDb().select().from(t).where(g(...s)).limit(1);return a[0]?a[0]:null}async createClone(e){let n=this.getTable(),t=this.applyManagedInsertFields(e,"drizzle",()=>this.generateId());return (await this.getDb().insert(n).values(t).returning())[0]}};function kn(o,e,n){let t=n?.dialect??"sqlite";return {Create:class extends P{_meta=e;db=o},Read:class extends I{_meta=e;db=o},Update:class extends _{_meta=e;db=o},Delete:class extends A{_meta=e;db=o},List:class extends q{_meta=e;db=o;dialect=t},Restore:class extends F{_meta=e;db=o},Upsert:class extends V{_meta=e;db=o;dialect=t},Search:class extends ${_meta=e;db=o;dialect=t},BatchCreate:class extends U{_meta=e;db=o},BatchUpdate:class extends Z{_meta=e;db=o},BatchDelete:class extends L{_meta=e;db=o},BatchRestore:class extends N{_meta=e;db=o},BatchUpsert:class extends K{_meta=e;db=o;dialect=t}}}var je=class{db;table;constructor(e){this.db=e.db,this.table=e.table;}col(e){return p(this.table,e)}recordScope(e,n){return and(eq(this.col("resourceTable"),e),eq(this.col("recordId"),String(n)))}toEntry(e){return {id:e.id,recordId:e.recordId,version:e.version,data:JSON.parse(e.data),createdAt:new Date(e.createdAt),...e.changedBy!=null?{changedBy:e.changedBy}:{},...e.changeReason!=null?{changeReason:e.changeReason}:{},...e.changes!=null?{changes:JSON.parse(e.changes)}:{}}}async store(e,n){let t=n.createdAt instanceof Date?n.createdAt:new Date(n.createdAt);await this.db.insert(this.table).values({id:n.id,resourceTable:e,recordId:String(n.recordId),version:n.version,data:JSON.stringify(n.data),createdAt:t.getTime(),changedBy:n.changedBy??null,changeReason:n.changeReason??null,changes:n.changes?JSON.stringify(n.changes):null});}async getByRecordId(e,n,t){let r=this.db.select().from(this.table).where(this.recordScope(e,n)).orderBy(desc(this.col("version")));return (t?.limit!=null||t?.offset!=null)&&(r=r.limit(t?.limit??Number.MAX_SAFE_INTEGER)),t?.offset!=null&&(r=r.offset(t.offset)),(await r).map(s=>this.toEntry(s))}async getVersion(e,n,t){let r=await this.db.select().from(this.table).where(and(this.recordScope(e,n),eq(this.col("version"),t))).limit(1);return r.length>0?this.toEntry(r[0]):null}async getLatestVersion(e,n){let t=await this.db.select().from(this.table).where(this.recordScope(e,n)).orderBy(desc(this.col("version"))).limit(1);return t.length>0?t[0].version:0}async pruneVersions(e,n,t){if(t<=0)return this.deleteAllVersions(e,n);let r=await this.getByRecordId(e,n);if(r.length<=t)return 0;let i=r[t-1].version;return (await this.db.delete(this.table).where(and(this.recordScope(e,n),lt(this.col("version"),i))).returning()).length}async deleteAllVersions(e,n){return (await this.db.delete(this.table).where(this.recordScope(e,n)).returning()).length}};function Hn(o="version_history"){return sqliteTable(o,{id:text("id").primaryKey(),resourceTable:text("resource_table").notNull(),recordId:text("record_id").notNull(),version:integer("version").notNull(),data:text("data").notNull(),createdAt:integer("created_at").notNull(),changedBy:text("changed_by"),changeReason:text("change_reason"),changes:text("changes")})}var he=null,Pe=false,me=null;async function ze(){if(Pe){if(me)throw me;return he}Pe=true;try{return he=await import('drizzle-zod'),he}catch{throw me=new Error("drizzle-zod is not installed. Please install it: npm install drizzle-zod"),me}}async function Pt(o,e){return (await ze()).createSelectSchema(o,e)}async function It(o,e){return (await ze()).createInsertSchema(o,e)}async function _t(o,e){let n=await ze();return n.createUpdateSchema?n.createUpdateSchema(o,e):n.createInsertSchema(o,e).partial()}async function At(o,e){let n=await ze(),t=e?.coerceDates!==false,r=t?Zt(o):new Set,i=n.createSelectSchema(o,e?.selectRefine),s=n.createInsertSchema(o,e?.insertRefine),a;return n.createUpdateSchema?a=n.createUpdateSchema(o,e?.updateRefine):a=n.createInsertSchema(o,e?.updateRefine).partial(),t&&r.size>0&&(s=Ie(s,r),a=Ie(a,r)),{select:i,insert:s,update:a}}function qt(){return he!==null}var Ft=z.preprocess(o=>{if(o instanceof Date)return o;if(typeof o=="string"){let e=new Date(o);if(!isNaN(e.getTime()))return e}return o},z.date()),Ut=z.preprocess(o=>{if(o==null)return null;if(o instanceof Date)return o;if(typeof o=="string"){let e=new Date(o);if(!isNaN(e.getTime()))return e}return o},z.date().nullable());function Zt(o){let e=new Set,n=o;for(let[t,r]of Object.entries(n)){if(t==="_"||t==="$inferInsert"||t==="$inferSelect")continue;let i=r;if(!i||typeof i!="object")continue;let s=String(i.dataType??"").toLowerCase(),a=String(i.columnType??"").toLowerCase(),l=i.config,c=String(l?.dataType??"").toLowerCase();(s.includes("timestamp")||s.includes("date")||s.includes("datetime")||a.includes("pgtimestamp")||a.includes("pgdate")||a.includes("mysqltimestamp")||a.includes("mysqldate")||a.includes("sqlitetimestamp")||c.includes("timestamp")||c.includes("date"))&&e.add(t);}return e}function Ie(o,e){if(e.size===0)return o;let n=o.shape,t={};for(let[r,i]of Object.entries(n))if(e.has(r)){let s=i.isOptional?.()??false,a=i.isNullable?.()??false,l=Ft;(a||s)&&(l=Ut),s&&(l=l.optional()),t[r]=l;}else t[r]=i;return z.object(t)}var nr={CreateEndpoint:P,ListEndpoint:q,ReadEndpoint:I,UpdateEndpoint:_,DeleteEndpoint:A,RestoreEndpoint:F,BatchCreateEndpoint:U,BatchUpdateEndpoint:Z,BatchDeleteEndpoint:L,BatchRestoreEndpoint:N,BatchUpsertEndpoint:K,SearchEndpoint:$,AggregateEndpoint:de,ExportEndpoint:ce,ImportEndpoint:ue,UpsertEndpoint:V,CloneEndpoint:pe,BulkPatchEndpoint:oe,VersionHistoryEndpoint:ie,VersionReadEndpoint:se,VersionCompareEndpoint:ae,VersionRollbackEndpoint:le};export{Ye as DRIZZLE_DIALECTS,nr as DrizzleAdapters,de as DrizzleAggregateEndpoint,U as DrizzleBatchCreateEndpoint,L as DrizzleBatchDeleteEndpoint,N as DrizzleBatchRestoreEndpoint,Z as DrizzleBatchUpdateEndpoint,K as DrizzleBatchUpsertEndpoint,oe as DrizzleBulkPatchEndpoint,pe as DrizzleCloneEndpoint,P as DrizzleCreateEndpoint,A as DrizzleDeleteEndpoint,ce as DrizzleExportEndpoint,ue as DrizzleImportEndpoint,q as DrizzleListEndpoint,I as DrizzleReadEndpoint,F as DrizzleRestoreEndpoint,$ as DrizzleSearchEndpoint,_ as DrizzleUpdateEndpoint,V as DrizzleUpsertEndpoint,ae as DrizzleVersionCompareEndpoint,ie as DrizzleVersionHistoryEndpoint,se as DrizzleVersionReadEndpoint,le as DrizzleVersionRollbackEndpoint,je as DrizzleVersioningStorage,S as batchLoadDrizzleRelations,H as buildWhereCondition,W as cast,kn as createDrizzleCrud,At as createDrizzleSchemas,It as createInsertSchema,Pt as createSelectSchema,_t as createUpdateSchema,p as getColumn,b as getTable,qt as isDrizzleZodAvailable,Ge as loadDrizzleRelation,Ce as loadDrizzleRelations,k as readCount,Hn as sqliteVersionHistoryTable,j as substringMatch};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hono-crud/drizzle",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.18",
|
|
4
4
|
"description": "Drizzle ORM CRUD adapter for hono-crud",
|
|
5
5
|
"author": "Kauan Guesser <contato@kauan.net>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"drizzle-zod": ">=0.8.0",
|
|
48
48
|
"hono": ">=4.11.7 <5",
|
|
49
49
|
"zod": ">=4.0.0",
|
|
50
|
-
"hono-crud": "^0.13.
|
|
50
|
+
"hono-crud": "^0.13.24"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"drizzle-orm": "^0.45.1",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"tsup": "^8.4.0",
|
|
57
57
|
"typescript": "^5.8.3",
|
|
58
58
|
"zod": "^4.3.5",
|
|
59
|
-
"hono-crud": "0.13.
|
|
59
|
+
"hono-crud": "0.13.24"
|
|
60
60
|
},
|
|
61
61
|
"peerDependenciesMeta": {
|
|
62
62
|
"drizzle-zod": {
|