@hono-crud/drizzle 0.1.16 → 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 CHANGED
@@ -1,5 +1,25 @@
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
+
17
+ ## 0.1.17
18
+
19
+ ### Patch Changes
20
+
21
+ - e0eac64: Add `DrizzleVersioningStorage` — a durable, Drizzle-backed `VersioningStorage` (Cloudflare D1, libsql, postgres-js, …) so record version history survives across isolates/requests. Previously the only shipped `VersioningStorage` was in-memory, so version history on Workers was per-isolate and ephemeral. Ships a `sqliteVersionHistoryTable()` helper for D1/SQLite; one shared table backs many models (rows discriminated by the model's tableName). Core re-exports `VersionHistoryEntry` from `hono-crud/versioning` so storage implementers can import it alongside `VersioningStorage`.
22
+
3
23
  ## 0.1.16
4
24
 
5
25
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import { MetaInput, IncludeOptions, FilterCondition, RelationConfig, CreateEndpoint, ModelObject, ReadEndpoint, UpdateEndpoint, NestedUpdateInput, NestedWriteResult, DeleteEndpoint, ListEndpoint, ListFilters, PaginatedResult, RestoreEndpoint, BatchCreateEndpoint, BatchDeleteEndpoint, BatchRestoreEndpoint, BatchUpdateEndpoint, BatchUpdateItem, AggregateEndpoint, AggregateOptions, AggregateResult, BatchUpsertEndpoint, BulkPatchEndpoint, CloneEndpoint, UpsertEndpoint, SearchEndpoint, SearchOptions, SearchResult, ExportEndpoint, ImportEndpoint, VersionCompareEndpoint, VersionHistoryEndpoint, VersionReadEndpoint, VersionRollbackEndpoint, AdapterBundle } from 'hono-crud/internal';
2
2
  import { Env } from 'hono';
3
+ import * as drizzle_orm_sqlite_core from 'drizzle-orm/sqlite-core';
4
+ import { VersioningStorage, VersionHistoryEntry } from 'hono-crud/versioning';
3
5
  import { z } from 'zod';
4
6
 
5
7
  /**
@@ -649,7 +651,7 @@ declare abstract class DrizzleBulkPatchEndpoint<E extends Env = Env, M extends M
649
651
  }
650
652
  /**
651
653
  * Drizzle Version History endpoint.
652
- * Lists all versions for a record.
654
+ * Lists all versions for a record (owner-scoped parent-record check).
653
655
  */
654
656
  declare abstract class DrizzleVersionHistoryEndpoint<E extends Env = Env, M extends MetaInput = MetaInput, DB extends DrizzleDatabaseConstraint = DrizzleDatabaseConstraint> extends VersionHistoryEndpoint<E, M> {
655
657
  /** Drizzle database instance. Can be undefined if using context injection. */
@@ -658,30 +660,45 @@ declare abstract class DrizzleVersionHistoryEndpoint<E extends Env = Env, M exte
658
660
  protected getDb(): DB;
659
661
  protected getTable(): DrizzleTable;
660
662
  protected getColumn(field: string): DrizzleColumn;
661
- protected recordExists(lookupValue: string): Promise<boolean>;
663
+ protected recordExists(lookupValue: string, tenantScope?: {
664
+ field: string;
665
+ value: string;
666
+ }): Promise<boolean>;
662
667
  }
663
668
  /**
664
669
  * Drizzle Version Read endpoint.
665
- * Gets a specific version of a record.
666
- *
667
- * Unlike the db-touching endpoints, this is a pure pass-through to the core
668
- * base class and performs no Drizzle queries, so it intentionally takes only
669
- * `<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.
670
672
  */
671
- 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>;
672
683
  }
673
684
  /**
674
685
  * Drizzle Version Compare endpoint.
675
- * Compares two versions of a record.
676
- *
677
- * Like {@link DrizzleVersionReadEndpoint}, this is a pure pass-through with no
678
- * Drizzle queries, so it intentionally takes only `<E, M>` (no `DB` generic).
686
+ * Compares two versions of a record (owner-scoped parent-record check).
679
687
  */
680
- 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>;
681
698
  }
682
699
  /**
683
700
  * Drizzle Version Rollback endpoint.
684
- * Rolls back a record to a previous version.
701
+ * Rolls back a record to a previous version (owner-scoped before mutating).
685
702
  */
686
703
  declare abstract class DrizzleVersionRollbackEndpoint<E extends Env = Env, M extends MetaInput = MetaInput, DB extends DrizzleDatabaseConstraint = DrizzleDatabaseConstraint> extends VersionRollbackEndpoint<E, M> {
687
704
  /** Drizzle database instance. Can be undefined if using context injection. */
@@ -690,6 +707,10 @@ declare abstract class DrizzleVersionRollbackEndpoint<E extends Env = Env, M ext
690
707
  protected getDb(): DB;
691
708
  protected getTable(): DrizzleTable;
692
709
  protected getColumn(field: string): DrizzleColumn;
710
+ protected recordExists(lookupValue: string, tenantScope?: {
711
+ field: string;
712
+ value: string;
713
+ }): Promise<boolean>;
693
714
  rollback(lookupValue: string, versionData: Record<string, unknown>, newVersion: number): Promise<ModelObject<M['model']>>;
694
715
  }
695
716
  /**
@@ -923,6 +944,241 @@ interface CreateDrizzleCrudOptions {
923
944
  */
924
945
  declare function createDrizzleCrud<M extends MetaInput, E extends Env = Env>(db: DrizzleDatabaseConstraint, meta: M, options?: CreateDrizzleCrudOptions): DrizzleCrudClasses<M, E>;
925
946
 
947
+ interface DrizzleVersioningStorageOptions {
948
+ /** Any Drizzle database handle (D1/libsql/postgres-js/…). */
949
+ db: DrizzleDatabaseConstraint;
950
+ /**
951
+ * The history table. Must have the property names of {@link VersionHistoryRow}
952
+ * (`id`, `resourceTable`, `recordId`, `version`, `data`, `createdAt`,
953
+ * `changedBy`, `changeReason`, `changes`). Use {@link sqliteVersionHistoryTable}
954
+ * for D1/SQLite, or define your own for another dialect.
955
+ */
956
+ table: DrizzleTable;
957
+ }
958
+ /**
959
+ * Durable {@link VersioningStorage} backed by Drizzle — the persistent
960
+ * counterpart to the in-memory `MemoryVersioningStorage`, suitable for
961
+ * Cloudflare D1 and any other Drizzle-supported database. Version snapshots
962
+ * survive across isolates/requests (unlike the memory store, which is
963
+ * per-isolate).
964
+ *
965
+ * @remarks
966
+ * The record snapshot (`entry.data`) is persisted with `JSON.stringify` and
967
+ * rehydrated with `JSON.parse`, so non-JSON values inside it are stored in
968
+ * their JSON form — e.g. a nested `Date` comes back as an ISO string, not a
969
+ * `Date` (unlike `MemoryVersioningStorage`, which keeps the object by
970
+ * reference). The entry's own `createdAt` is exempt: stored as epoch
971
+ * milliseconds and rehydrated to a `Date`.
972
+ *
973
+ * @example
974
+ * ```ts
975
+ * import { DrizzleVersioningStorage, sqliteVersionHistoryTable } from '@hono-crud/drizzle';
976
+ * import { setVersioningStorage } from 'hono-crud/versioning';
977
+ *
978
+ * const versionHistory = sqliteVersionHistoryTable();
979
+ * const db = drizzle(env.DB);
980
+ * setVersioningStorage(new DrizzleVersioningStorage({ db, table: versionHistory }));
981
+ * ```
982
+ */
983
+ declare class DrizzleVersioningStorage implements VersioningStorage {
984
+ private readonly db;
985
+ private readonly table;
986
+ constructor(options: DrizzleVersioningStorageOptions);
987
+ private col;
988
+ private recordScope;
989
+ private toEntry;
990
+ store(tableName: string, entry: VersionHistoryEntry): Promise<void>;
991
+ getByRecordId(tableName: string, recordId: string | number, options?: {
992
+ limit?: number;
993
+ offset?: number;
994
+ }): Promise<VersionHistoryEntry[]>;
995
+ getVersion(tableName: string, recordId: string | number, version: number): Promise<VersionHistoryEntry | null>;
996
+ getLatestVersion(tableName: string, recordId: string | number): Promise<number>;
997
+ pruneVersions(tableName: string, recordId: string | number, keepCount: number): Promise<number>;
998
+ deleteAllVersions(tableName: string, recordId: string | number): Promise<number>;
999
+ }
1000
+ /**
1001
+ * Build a SQLite/D1 history table with the columns
1002
+ * {@link DrizzleVersioningStorage} expects. `recordId`/`resourceTable`/`version`
1003
+ * are indexed for the per-record lookups the storage performs.
1004
+ *
1005
+ * @param name - Table name. Default `version_history`.
1006
+ */
1007
+ declare function sqliteVersionHistoryTable(name?: string): drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
1008
+ name: string;
1009
+ schema: undefined;
1010
+ columns: {
1011
+ id: drizzle_orm_sqlite_core.SQLiteColumn<{
1012
+ name: "id";
1013
+ tableName: string;
1014
+ dataType: "string";
1015
+ columnType: "SQLiteText";
1016
+ data: string;
1017
+ driverParam: string;
1018
+ notNull: true;
1019
+ hasDefault: false;
1020
+ isPrimaryKey: true;
1021
+ isAutoincrement: false;
1022
+ hasRuntimeDefault: false;
1023
+ enumValues: [string, ...string[]];
1024
+ baseColumn: never;
1025
+ identity: undefined;
1026
+ generated: undefined;
1027
+ }, {}, {
1028
+ length: number | undefined;
1029
+ }>;
1030
+ resourceTable: drizzle_orm_sqlite_core.SQLiteColumn<{
1031
+ name: "resource_table";
1032
+ tableName: string;
1033
+ dataType: "string";
1034
+ columnType: "SQLiteText";
1035
+ data: string;
1036
+ driverParam: string;
1037
+ notNull: true;
1038
+ hasDefault: false;
1039
+ isPrimaryKey: false;
1040
+ isAutoincrement: false;
1041
+ hasRuntimeDefault: false;
1042
+ enumValues: [string, ...string[]];
1043
+ baseColumn: never;
1044
+ identity: undefined;
1045
+ generated: undefined;
1046
+ }, {}, {
1047
+ length: number | undefined;
1048
+ }>;
1049
+ recordId: drizzle_orm_sqlite_core.SQLiteColumn<{
1050
+ name: "record_id";
1051
+ tableName: string;
1052
+ dataType: "string";
1053
+ columnType: "SQLiteText";
1054
+ data: string;
1055
+ driverParam: string;
1056
+ notNull: true;
1057
+ hasDefault: false;
1058
+ isPrimaryKey: false;
1059
+ isAutoincrement: false;
1060
+ hasRuntimeDefault: false;
1061
+ enumValues: [string, ...string[]];
1062
+ baseColumn: never;
1063
+ identity: undefined;
1064
+ generated: undefined;
1065
+ }, {}, {
1066
+ length: number | undefined;
1067
+ }>;
1068
+ version: drizzle_orm_sqlite_core.SQLiteColumn<{
1069
+ name: "version";
1070
+ tableName: string;
1071
+ dataType: "number";
1072
+ columnType: "SQLiteInteger";
1073
+ data: number;
1074
+ driverParam: number;
1075
+ notNull: true;
1076
+ hasDefault: false;
1077
+ isPrimaryKey: false;
1078
+ isAutoincrement: false;
1079
+ hasRuntimeDefault: false;
1080
+ enumValues: undefined;
1081
+ baseColumn: never;
1082
+ identity: undefined;
1083
+ generated: undefined;
1084
+ }, {}, {}>;
1085
+ data: drizzle_orm_sqlite_core.SQLiteColumn<{
1086
+ name: "data";
1087
+ tableName: string;
1088
+ dataType: "string";
1089
+ columnType: "SQLiteText";
1090
+ data: string;
1091
+ driverParam: string;
1092
+ notNull: true;
1093
+ hasDefault: false;
1094
+ isPrimaryKey: false;
1095
+ isAutoincrement: false;
1096
+ hasRuntimeDefault: false;
1097
+ enumValues: [string, ...string[]];
1098
+ baseColumn: never;
1099
+ identity: undefined;
1100
+ generated: undefined;
1101
+ }, {}, {
1102
+ length: number | undefined;
1103
+ }>;
1104
+ createdAt: drizzle_orm_sqlite_core.SQLiteColumn<{
1105
+ name: "created_at";
1106
+ tableName: string;
1107
+ dataType: "number";
1108
+ columnType: "SQLiteInteger";
1109
+ data: number;
1110
+ driverParam: number;
1111
+ notNull: true;
1112
+ hasDefault: false;
1113
+ isPrimaryKey: false;
1114
+ isAutoincrement: false;
1115
+ hasRuntimeDefault: false;
1116
+ enumValues: undefined;
1117
+ baseColumn: never;
1118
+ identity: undefined;
1119
+ generated: undefined;
1120
+ }, {}, {}>;
1121
+ changedBy: drizzle_orm_sqlite_core.SQLiteColumn<{
1122
+ name: "changed_by";
1123
+ tableName: string;
1124
+ dataType: "string";
1125
+ columnType: "SQLiteText";
1126
+ data: string;
1127
+ driverParam: string;
1128
+ notNull: false;
1129
+ hasDefault: false;
1130
+ isPrimaryKey: false;
1131
+ isAutoincrement: false;
1132
+ hasRuntimeDefault: false;
1133
+ enumValues: [string, ...string[]];
1134
+ baseColumn: never;
1135
+ identity: undefined;
1136
+ generated: undefined;
1137
+ }, {}, {
1138
+ length: number | undefined;
1139
+ }>;
1140
+ changeReason: drizzle_orm_sqlite_core.SQLiteColumn<{
1141
+ name: "change_reason";
1142
+ tableName: string;
1143
+ dataType: "string";
1144
+ columnType: "SQLiteText";
1145
+ data: string;
1146
+ driverParam: string;
1147
+ notNull: false;
1148
+ hasDefault: false;
1149
+ isPrimaryKey: false;
1150
+ isAutoincrement: false;
1151
+ hasRuntimeDefault: false;
1152
+ enumValues: [string, ...string[]];
1153
+ baseColumn: never;
1154
+ identity: undefined;
1155
+ generated: undefined;
1156
+ }, {}, {
1157
+ length: number | undefined;
1158
+ }>;
1159
+ changes: drizzle_orm_sqlite_core.SQLiteColumn<{
1160
+ name: "changes";
1161
+ tableName: string;
1162
+ dataType: "string";
1163
+ columnType: "SQLiteText";
1164
+ data: string;
1165
+ driverParam: string;
1166
+ notNull: false;
1167
+ hasDefault: false;
1168
+ isPrimaryKey: false;
1169
+ isAutoincrement: false;
1170
+ hasRuntimeDefault: false;
1171
+ enumValues: [string, ...string[]];
1172
+ baseColumn: never;
1173
+ identity: undefined;
1174
+ generated: undefined;
1175
+ }, {}, {
1176
+ length: number | undefined;
1177
+ }>;
1178
+ };
1179
+ dialect: "sqlite";
1180
+ }>;
1181
+
926
1182
  /**
927
1183
  * Drizzle-Zod schema utilities.
928
1184
  *
@@ -1090,4 +1346,4 @@ declare function isDrizzleZodAvailable(): boolean;
1090
1346
  */
1091
1347
  declare const DrizzleAdapters: AdapterBundle;
1092
1348
 
1093
- export { type CountRow, type CreateDrizzleCrudOptions, DRIZZLE_DIALECTS, type Database, DrizzleAdapters, DrizzleAggregateEndpoint, DrizzleBatchCreateEndpoint, DrizzleBatchDeleteEndpoint, DrizzleBatchRestoreEndpoint, DrizzleBatchUpdateEndpoint, DrizzleBatchUpsertEndpoint, DrizzleBulkPatchEndpoint, DrizzleCloneEndpoint, type DrizzleColumn, DrizzleCreateEndpoint, type DrizzleCrudClasses, type DrizzleDatabaseConstraint, DrizzleDeleteEndpoint, type DrizzleDialect, type DrizzleEnv, DrizzleExportEndpoint, DrizzleImportEndpoint, DrizzleListEndpoint, DrizzleReadEndpoint, DrizzleRestoreEndpoint, type DrizzleSchemas, DrizzleSearchEndpoint, type DrizzleSql, type DrizzleTable, DrizzleUpdateEndpoint, DrizzleUpsertEndpoint, DrizzleVersionCompareEndpoint, DrizzleVersionHistoryEndpoint, DrizzleVersionReadEndpoint, DrizzleVersionRollbackEndpoint, type QueryBuilder, batchLoadDrizzleRelations, buildWhereCondition, cast, createDrizzleCrud, createDrizzleSchemas, createInsertSchema, createSelectSchema, createUpdateSchema, getColumn, getTable, isDrizzleZodAvailable, loadDrizzleRelation, loadDrizzleRelations, readCount, substringMatch };
1349
+ export { type CountRow, type CreateDrizzleCrudOptions, DRIZZLE_DIALECTS, type Database, DrizzleAdapters, DrizzleAggregateEndpoint, DrizzleBatchCreateEndpoint, DrizzleBatchDeleteEndpoint, DrizzleBatchRestoreEndpoint, DrizzleBatchUpdateEndpoint, DrizzleBatchUpsertEndpoint, DrizzleBulkPatchEndpoint, DrizzleCloneEndpoint, type DrizzleColumn, DrizzleCreateEndpoint, type DrizzleCrudClasses, type DrizzleDatabaseConstraint, DrizzleDeleteEndpoint, type DrizzleDialect, type DrizzleEnv, DrizzleExportEndpoint, DrizzleImportEndpoint, DrizzleListEndpoint, DrizzleReadEndpoint, DrizzleRestoreEndpoint, type DrizzleSchemas, DrizzleSearchEndpoint, type DrizzleSql, type DrizzleTable, DrizzleUpdateEndpoint, DrizzleUpsertEndpoint, DrizzleVersionCompareEndpoint, DrizzleVersionHistoryEndpoint, DrizzleVersionReadEndpoint, DrizzleVersionRollbackEndpoint, DrizzleVersioningStorage, type DrizzleVersioningStorageOptions, type QueryBuilder, batchLoadDrizzleRelations, buildWhereCondition, cast, createDrizzleCrud, createDrizzleSchemas, createInsertSchema, createSelectSchema, createUpdateSchema, getColumn, getTable, isDrizzleZodAvailable, loadDrizzleRelation, loadDrizzleRelations, readCount, sqliteVersionHistoryTable, substringMatch };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import {getTableColumns,between,isNull,isNotNull,notInArray,inArray,lte,lt,gte,gt,ne,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 {z as z$1}from'zod';function G(o){return o}function g(...o){return and(...o)}function J(...o){return or(...o)}var Ke=["sqlite","pg","mysql"];function z(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 he(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 Qe(o,e,n,t){let r=t.table;if(!r)return e;let i=he(o),s=await resolveRelationValueAsync(e,t,r,i.fetchRelated);return {...e,[n]:s}}async function fe(o,e,n,t){return loadRelationsForItem(e,n,he(o),t)}async function v(o,e,n,t){return batchLoadRelations(e,n,he(o),t)}function W(o,e,n="sqlite"){let t=p(o,e.field);switch(e.operator){case "eq":return eq(t,e.value);case "ne":return ne(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 B(t,String(e.value).replace(/%/g,""),n,{caseSensitive:true});case "ilike":return B(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 S(o){return Number(o[0]?.count)||0}async function V(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 y=p(n,s.field);t.options.onlyDeleted?u.push(isNotNull(y)):t.options.withDeleted||u.push(isNull(y));}for(let y of t.filters){let k=W(n,y,r);k&&u.push(k);}if(t.options.search&&i.length>0){let y=t.options.search,k=i.map(Oe=>B(p(n,Oe),y,r));u.push(J(...k));}u.push(...l);let d=u.length>0?g(...u):void 0,D=await e.select({count:sql`count(*)`}).from(n).where(d),f=S(D),h=c!==void 0&&(t.options.cursor!==void 0||t.options.limit!==void 0),C=d,w=false;if(h&&t.options.cursor){let y=decodeCursor(t.options.cursor);y!==null&&(C=g(d,gt(p(n,c),y)),w=true);}let M=e.select().from(n).where(C);if(t.options.order_by){let y=p(n,t.options.order_by),k=t.options.order_by_direction==="desc"?desc:asc;M=M.orderBy(k(y));}if(h){let y=t.options.limit||t.options.per_page||a;return {records:await M.limit(y+1),totalCount:f,page:0,perPage:y,totalPages:0,cursor:{limit:y,applied:w}}}let R=t.options.page||1,T=t.options.per_page||a,Y=await M.limit(T).offset((R-1)*T),Q=Math.ceil(f/T);return {records:Y,totalCount:f,page:R,perPage:T,totalPages:Q}}function ee(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 te(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 B(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:
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 j=class extends CreateEndpoint{db;useTransaction=false;getDb(){return m(this)}getTable(){return z(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},D=await s.insert(a).values(d).returning();D[0]&&c.push(D[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()}},P=class extends ReadEndpoint{db;getDb(){return m(this)}getTable(){return z(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 fe(this.getDb(),l[0],this._meta,t):null}},I=class extends UpdateEndpoint{db;useTransaction=false;getDb(){return m(this)}getTable(){return z(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,D]of Object.entries(t))c.push(eq(this.getColumn(d),D));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 D of d){if(typeof D!="object"||D===null)continue;let f={...D,id:crypto.randomUUID(),[t.foreignKey]:e},h=await s.insert(a).values(f).returning();h[0]&&l.created.push(h[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,...h}=d,C=await s.update(a).set(h).where(eq(u,f)).returning();C[0]&&l.updated.push(C[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()}},_=class extends DeleteEndpoint{db;useTransaction=false;getDb(){return m(this)}getTable(){return z(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 S(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()}},A=class extends ListEndpoint{db;dialect="sqlite";supportsCursorPagination=true;getDb(){return m(this)}getTable(){return z(this._meta)}getColumn(e){return p(this.getTable(),e)}async list(e){let n=await V({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 v(this.getDb(),i,this._meta,t),result_info:s}}let r=await v(this.getDb(),n.records,this._meta,t);return ee(r,n)}},F=class extends RestoreEndpoint{db;useTransaction=false;getDb(){return m(this)}getTable(){return z(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 q=class extends BatchCreateEndpoint{db;getDb(){return m(this)}getTable(){return z(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()}},U=class extends BatchUpdateEndpoint{db;getDb(){return m(this)}getTable(){return z(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}}},Z=class extends BatchDeleteEndpoint{db;getDb(){return m(this)}getTable(){return z(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}}},L=class extends BatchRestoreEndpoint{db;getDb(){return m(this)}getTable(){return z(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 Rt(o){return o.split(/\s+/).filter(e=>e.length>0)}var N=class extends UpsertEndpoint{db;dialect="sqlite";getDb(){return m(this)}getTable(){return z(this._meta)}getColumn(e){return p(this.getTable(),e)}async findExisting(e){return te(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[C,w]of Object.entries(e))!r.includes(C)&&C!==i&&(this.createOnlyFields?.includes(C)||(c[C]=w));a.enabled&&(c[a.updatedAt]=Date.now());let u=r.map(C=>this.getColumn(C)),d;s.enabled&&(d=isNull(this.getColumn(s.field)));let D=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:D}).returning())[0],created:false}:{data:(await f.onConflictDoUpdate({target:u,set:D,where:d}).returning())[0],created:false}}},$=class extends BatchUpsertEndpoint{db;dialect="sqlite";getDb(){return m(this)}getTable(){return z(this._meta)}getColumn(e){return p(this.getTable(),e)}async findExisting(e){return te(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(h=>this.applyManagedInsertFields(h,"drizzle")),l={},c=e[0];for(let h of Object.keys(c))!r.includes(h)&&h!==i&&(this.createOnlyFields?.includes(h)||(l[h]=sql`excluded.${sql.identifier(h)}`));s.enabled&&(l[s.updatedAt]=Date.now());let u=r.map(h=>this.getColumn(h)),d=Object.keys(l).length>0?l:{[i]:sql`${this.getColumn(i)}`},D=this.getDb().insert(t).values(a),f=await(this.dialect==="mysql"?D.onDuplicateKeyUpdate({set:d}):D.onConflictDoUpdate({target:u,set:d})).returning();return {items:f.map((h,C)=>({data:h,created:false,index:C})),createdCount:0,updatedCount:f.length,totalCount:f.length}}},re=class extends BulkPatchEndpoint{db;dialect="sqlite";getDb(){return m(this)}getTable(){return z(this._meta)}getColumn(e){return p(this.getTable(),e)}buildConditions(e){let n=this.getTable(),t=[];for(let i of e.filters){let s=W(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 S(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}}},oe=class extends VersionHistoryEndpoint{db;getDb(){return m(this)}getTable(){return z(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 S(t)>0}},ie=class extends VersionReadEndpoint{},se=class extends VersionCompareEndpoint{},ae=class extends VersionRollbackEndpoint{db;getDb(){return m(this)}getTable(){return z(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]}},le=class extends AggregateEndpoint{db;dialect="sqlite";getDb(){return m(this)}getTable(){return z(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=W(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)}},K=class extends SearchEndpoint{db;dialect="sqlite";getDb(){return m(this)}useNativeSearch=false;vectorColumn;vectorConfig="english";getTable(){return z(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),M=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} @@ ${M}`);}else {let w=(M,R)=>{try{let T=this.getColumn(M);return B(sql`CAST(${T} AS TEXT)`,R,this.dialect)}catch{return}};if(e.mode==="all"){let M=Rt(e.query);if(M.length>0){let R=[];for(let T of M){let Y=s.map(Q=>w(Q,T)).filter(Q=>Q!==void 0);Y.length>0&&R.push(J(...Y));}R.length>0&&r.push(g(...R));}}else {let M=s.map(R=>w(R,e.query)).filter(R=>R!==void 0);M.length>0&&r.push(J(...M));}}let a=await V({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),D={relations:n.options.include||[],scope:this.getRelationScope(n.options.withDeleted)},f=d.map(w=>w.item),h=await v(this.getDb(),f,this._meta,D);return {items:d.map((w,M)=>({...w,item:h[M]})),totalCount:c}}},de=class extends ExportEndpoint{db;dialect="sqlite";getDb(){return m(this)}getTable(){return z(this._meta)}getColumn(e){return p(this.getTable(),e)}async list(e){let n=await V({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 v(this.getDb(),n.records,this._meta,t);return ee(r,n)}},ce=class extends ImportEndpoint{db;getDb(){return m(this)}getTable(){return z(this._meta)}getColumn(e){return p(this.getTable(),e)}async findExisting(e){return te(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]}},ue=class extends CloneEndpoint{db;getDb(){return m(this)}getTable(){return z(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 yn(o,e,n){let t=n?.dialect??"sqlite";return {Create:class extends j{_meta=e;db=o},Read:class extends P{_meta=e;db=o},Update:class extends I{_meta=e;db=o},Delete:class extends _{_meta=e;db=o},List:class extends A{_meta=e;db=o;dialect=t},Restore:class extends F{_meta=e;db=o},Upsert:class extends N{_meta=e;db=o;dialect=t},Search:class extends K{_meta=e;db=o;dialect=t},BatchCreate:class extends q{_meta=e;db=o},BatchUpdate:class extends U{_meta=e;db=o},BatchDelete:class extends Z{_meta=e;db=o},BatchRestore:class extends L{_meta=e;db=o},BatchUpsert:class extends ${_meta=e;db=o;dialect=t}}}var ze=null,xe=false,ge=null;async function me(){if(xe){if(ge)throw ge;return ze}xe=true;try{return ze=await import('drizzle-zod'),ze}catch{throw ge=new Error("drizzle-zod is not installed. Please install it: npm install drizzle-zod"),ge}}async function Et(o,e){return (await me()).createSelectSchema(o,e)}async function Tt(o,e){return (await me()).createInsertSchema(o,e)}async function xt(o,e){let n=await me();return n.createUpdateSchema?n.createUpdateSchema(o,e):n.createInsertSchema(o,e).partial()}async function kt(o,e){let n=await me(),t=e?.coerceDates!==false,r=t?Bt(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=ke(s,r),a=ke(a,r)),{select:i,insert:s,update:a}}function Ot(){return ze!==null}var vt=z$1.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$1.date()),St=z$1.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$1.date().nullable());function Bt(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 ke(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=vt;(a||s)&&(l=St),s&&(l=l.optional()),t[r]=l;}else t[r]=i;return z$1.object(t)}var Ln={CreateEndpoint:j,ListEndpoint:A,ReadEndpoint:P,UpdateEndpoint:I,DeleteEndpoint:_,RestoreEndpoint:F,BatchCreateEndpoint:q,BatchUpdateEndpoint:U,BatchDeleteEndpoint:Z,BatchRestoreEndpoint:L,BatchUpsertEndpoint:$,SearchEndpoint:K,AggregateEndpoint:le,ExportEndpoint:de,ImportEndpoint:ce,UpsertEndpoint:N,CloneEndpoint:ue,BulkPatchEndpoint:re,VersionHistoryEndpoint:oe,VersionReadEndpoint:ie,VersionCompareEndpoint:se,VersionRollbackEndpoint:ae};export{Ke as DRIZZLE_DIALECTS,Ln as DrizzleAdapters,le as DrizzleAggregateEndpoint,q as DrizzleBatchCreateEndpoint,Z as DrizzleBatchDeleteEndpoint,L as DrizzleBatchRestoreEndpoint,U as DrizzleBatchUpdateEndpoint,$ as DrizzleBatchUpsertEndpoint,re as DrizzleBulkPatchEndpoint,ue as DrizzleCloneEndpoint,j as DrizzleCreateEndpoint,_ as DrizzleDeleteEndpoint,de as DrizzleExportEndpoint,ce as DrizzleImportEndpoint,A as DrizzleListEndpoint,P as DrizzleReadEndpoint,F as DrizzleRestoreEndpoint,K as DrizzleSearchEndpoint,I as DrizzleUpdateEndpoint,N as DrizzleUpsertEndpoint,se as DrizzleVersionCompareEndpoint,oe as DrizzleVersionHistoryEndpoint,ie as DrizzleVersionReadEndpoint,ae as DrizzleVersionRollbackEndpoint,v as batchLoadDrizzleRelations,W as buildWhereCondition,G as cast,yn as createDrizzleCrud,kt as createDrizzleSchemas,Tt as createInsertSchema,Et as createSelectSchema,xt as createUpdateSchema,p as getColumn,z as getTable,Ot as isDrizzleZodAvailable,Qe as loadDrizzleRelation,fe as loadDrizzleRelations,S as readCount,B 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.16",
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.19"
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.19"
59
+ "hono-crud": "0.13.24"
60
60
  },
61
61
  "peerDependenciesMeta": {
62
62
  "drizzle-zod": {