@aurios/mizzle 1.1.3 → 1.1.5

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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @aurios/mizzle@1.1.3 build /home/runner/work/mizzle/mizzle/packages/mizzle
2
+ > @aurios/mizzle@1.1.5 build /home/runner/work/mizzle/mizzle/packages/mizzle
3
3
  > tsup
4
4
 
5
5
  CLI Building entry: {"index":"src/index.ts","columns":"src/columns/index.ts","table":"src/core/table.ts","snapshot":"src/core/snapshot.ts","diff":"src/core/diff.ts","introspection":"src/core/introspection.ts","db":"src/db.ts"}
@@ -10,22 +10,22 @@
10
10
  CLI Cleaning output folder
11
11
  ESM Build start
12
12
  ESM dist/index.js 2.32 KB
13
+ ESM dist/columns.js 299.00 B
13
14
  ESM dist/table.js 144.00 B
14
15
  ESM dist/snapshot.js 193.00 B
15
- ESM dist/chunk-TOYV2M4M.js 866.00 B
16
16
  ESM dist/diff.js 147.00 B
17
+ ESM dist/chunk-TOYV2M4M.js 866.00 B
17
18
  ESM dist/chunk-AQVECMXP.js 2.38 KB
18
19
  ESM dist/introspection.js 1.47 KB
19
20
  ESM dist/db.js 166.00 B
20
- ESM dist/chunk-NPPZW6VT.js 9.59 KB
21
+ ESM dist/chunk-WTOBEKFQ.js 9.74 KB
21
22
  ESM dist/transaction-RE7LXTGV.js 193.00 B
22
23
  ESM dist/chunk-UM3YF5EC.js 15.21 KB
23
24
  ESM dist/chunk-GPYZK4WY.js 1.12 KB
24
25
  ESM dist/chunk-DU7UPWBW.js 5.17 KB
25
- ESM dist/columns.js 299.00 B
26
- ESM ⚡️ Build success in 50ms
26
+ ESM ⚡️ Build success in 76ms
27
27
  DTS Build start
28
- DTS ⚡️ Build success in 5003ms
28
+ DTS ⚡️ Build success in 6614ms
29
29
  DTS dist/index.d.ts 3.84 KB
30
30
  DTS dist/diff.d.ts 485.00 B
31
31
  DTS dist/introspection.d.ts 258.00 B
@@ -33,5 +33,5 @@
33
33
  DTS dist/db.d.ts 169.00 B
34
34
  DTS dist/columns.d.ts 250.00 B
35
35
  DTS dist/table.d.ts 403.00 B
36
- DTS dist/db-zHIHBm1E.d.ts 31.72 KB
36
+ DTS dist/db-ZX6HGN1x.d.ts 31.83 KB
37
37
  DTS dist/operators-BVreW0ky.d.ts 29.24 KB
package/README.md CHANGED
@@ -1,8 +1,24 @@
1
- # @aurios/mizzle
1
+ # 🌧️ mizzle
2
2
 
3
+ ![NPM Last Update](https://img.shields.io/npm/last-update/%40aurios%2Fmizzle?style=flat&color=0EA5E9)
4
+ ![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/realfakenerd/mizzle/release.yml?style=flat&color=0EA5E9)
5
+ ![GitHub License](https://img.shields.io/github/license/realfakenerd/mizzle?style=flat&color=0EA5E9)
6
+
7
+ ![NPM Downloads](https://img.shields.io/npm/dw/%40aurios%2Fmizzle?style=flat&color=0EA5E9)
3
8
  A Drizzle-like ORM for DynamoDB. Mizzle provides a type-safe, fluent API for interacting with DynamoDB, supporting relational queries, batch operations, and transactions.
4
9
 
5
- ## Installation
10
+ ## Key Features
11
+
12
+ - **Type-Safe Schema Definition**: Define your tables and entities with strict TypeScript types.
13
+ - **Fluent Query Builder**: precise API for `insert`, `select`, `update`, and `delete` operations.
14
+ - **Relational Queries**: Query related entities with `db.query`.
15
+ - **Batch Operations**: `batchGet` and `batchWrite` support.
16
+ - **Transactions**: Atomic operations using `db.transaction`.
17
+ - **Automatic Type Inference**: `InferSelectModel` and `InferInsertModel` utilities.
18
+
19
+ > Skip this with the [way less boring docs](https://mizzle-docs.vercel.app)
20
+
21
+ ## 🚀 Installation
6
22
 
7
23
  ```bash
8
24
  npm install @aurios/mizzle
@@ -10,48 +26,141 @@ npm install @aurios/mizzle
10
26
  bun add @aurios/mizzle
11
27
  ```
12
28
 
13
- ## Usage
29
+ ## Get Started
30
+
31
+ ### Defining the Table
32
+
33
+ In DynamoDB, you first need a physical table. Mizzle separates the definition of the physical table structure (PK, SK, Indexes) from the logical entities that live within it and with this making your database well organized and easier to reason about.
34
+
35
+ ```ts
36
+ import { dynamoTable, string } from "@aurios/mizzle";
37
+
38
+ // This matches your actual DynamoDB table configuration
39
+ export const myTable = dynamoTable("JediOrder", {
40
+ pk: string("pk"), // The partition key attribute name
41
+ sk: string("sk"), // The sort key attribute name (optional)
42
+ });
43
+ ```
44
+
45
+ ### Defining the Entity
46
+
47
+ An Entity represents your data model (e.g., an user, an item on an user). You map the Entity to a Physical Table and define how its keys are generated, so every entity looks kinda like an separated table.
48
+
49
+ ```ts
50
+ import { dynamoEntity, string, uuid, number, enum, date, prefixKey, staticKey } from "@aurios/mizzle";
51
+
52
+ export const jedi = dynamoEntity(
53
+ myTable,
54
+ "Jedi",
55
+ {
56
+ id: uuid(), // Automatically generates a v7 UUID
57
+ name: string(),
58
+ homeworld: string()
59
+ },
60
+ (cols) => ({
61
+ // PK will look like "JEDI#<uuid>"
62
+ pk: prefixKey("JEDI#", cols.id),
63
+ // SK will be a static string "PROFILE"
64
+ sk: staticKey("PROFILE"),
65
+ }),
66
+ );
67
+
68
+ export const jediRank = dynamoEntity(
69
+ myTable,
70
+ 'JediRank',
71
+ {
72
+ jediId: uuid(),
73
+ position: string().default('initiate'),
74
+ joinedCouncilDate: string(),
75
+ },
76
+ (cols) => ({
77
+ // Same as the jedi so they can be related
78
+ pk: prefixKey('JEDI#', cols.jediId),
79
+ // RANK#initiate
80
+ sk: prefixKey('RANK#', cols.position),
81
+ })
82
+ )
83
+ ```
84
+
85
+ > The UUID V7 was chosen for better sorting, since the values are time-sortable with 1 millisecond precision.
86
+
87
+ ### Define the Relations
88
+
89
+ Relationships in Mizzle are established using the defineRelations function. This step creates a logical map of how your entities interact, enabling you to perform powerful relational queries—such as fetching a Jedi along with their entire rank history—in a single operation.
90
+
91
+ ```ts
92
+ import { defineRelations } from "@aurios/mizzle";
93
+ import * as schema from "./schema";
94
+
95
+ export const relations = defineRelations(schema, (r) => ({
96
+ jedi: {
97
+ // A Jedi could've a lot of ranks throughout his year
98
+ ranks: r.many.jediRank({
99
+ fields: [r.jedi.id],
100
+ references: [r.jediRank.jediId],
101
+ }),
102
+ },
103
+ jediRank: {
104
+ // Every registry points to one Jedi only
105
+ member: r.one.jedi({
106
+ fields: [r.jediRank.jediId],
107
+ references: [r.jedi.id],
108
+ }),
109
+ },
110
+ }));
111
+ ```
14
112
 
15
113
  ### Initialization
16
114
 
115
+ Initialize the mizzle client by passing it an instance of the standard AWS DynamoDBClient and the relations we just defined.
116
+
17
117
  ```ts
18
118
  import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
19
119
  import { mizzle } from "@aurios/mizzle";
120
+ import { relations } from "./relations";
20
121
 
21
- const client = new DynamoDBClient({});
22
- const db = mizzle(client);
122
+ const client = new DynamoDBClient({ region: "us-east-1" });
123
+ export const db = mizzle({ client, relations });
23
124
  ```
24
125
 
25
- ### Key Features
126
+ ### Query
26
127
 
27
- - **Type-Safe Schema Definition**: Define your tables and entities with strict TypeScript types.
28
- - **Fluent Query Builder**: precise API for `insert`, `select`, `update`, and `delete` operations.
29
- - **Relational Queries**: Query related entities with `db.query`.
30
- - **Batch Operations**: `batchGet` and `batchWrite` support.
31
- - **Transactions**: Atomic operations using `db.transaction`.
32
- - **Automatic Type Inference**: `InferSelectModel` and `InferInsertModel` utilities.
128
+ Now you can use the fluent API to interact with your data in the best way possible.
33
129
 
34
- ### Example
130
+ #### Insert Data
35
131
 
36
- ```ts
37
- // Define your schema (simplified)
38
- import { dynamoTable, dynamoEntity, string } from "@aurios/mizzle";
132
+ ```typescript
133
+ // api/jedi/new.ts
134
+ import { jedi } from "$lib/schema.ts";
39
135
 
40
- const myTable = dynamoTable("my-app-table", {
41
- pk: string("pk"),
42
- sk: string("sk"),
43
- });
136
+ const newJedi = await db
137
+ .insert(jedi)
138
+ .values({
139
+ name: "Luke Skywalker",
140
+ homeworld: "Tatooine",
141
+ })
142
+ .returning();
44
143
 
45
- const users = dynamoEntity(myTable, "users", {
46
- id: string("id"),
47
- name: string("name"),
48
- email: string("email"),
49
- });
144
+ console.log(newJedi.id); // The auto-generated UUID
145
+ ```
50
146
 
51
- // Query
52
- const result = await db.select().from(users).where(eq(users.id, "123"));
147
+ #### Select Data
148
+
149
+ Mizzle intelligently routes your request to `GetItem`, `Query`, or `Scan` based on the filters you provide.
150
+
151
+ ```typescript
152
+ // /api/jedi/get.ts
153
+ import { jedi } from "$lib/schema.ts";
154
+ import { eq } from "@aurios/mizzle";
155
+
156
+ // This will use GetItem because both PK and SK are fully resolved
157
+ const user = await db.select().from(jedi).where(eq(jedi.id, "some-uuid")).execute();
53
158
  ```
54
159
 
55
- ## License
160
+ ## Mizzling
161
+
162
+ This will work if you already has a DynamoDB table with data in it. If you want to create a new table with the schema you defined, you can use the [`mizzling`](https://www.npmjs.com/package/@aurios/mizzling) CLI.
163
+
164
+ ## 📄 License
56
165
 
57
- MIT
166
+ This project is licensed under the MIT License.
@@ -1 +1 @@
1
- import{D as Q,E as U,I as L,J as w,K as H,L as $,N as J,P as X,Q as Z,S as ee,e as P,p as q,q as G,r as z}from"./chunk-UM3YF5EC.js";import{b as D}from"./chunk-GPYZK4WY.js";import{d as E,e as d,f as k,i as v}from"./chunk-DU7UPWBW.js";import{DynamoDBClient as ne}from"@aws-sdk/client-dynamodb";import{DynamoDBDocumentClient as le}from"@aws-sdk/lib-dynamodb";import{GetCommand as ie,QueryCommand as se,ScanCommand as oe}from"@aws-sdk/lib-dynamodb";var O=class{constructor(t,e){this.client=t;this.fields=e}from(t){return new I(t,this.client,this.fields)}},I=class extends w{constructor(e,i,n){super(e,i);this.fields=n}static[d.ENTITY_KIND]="SelectBase";_whereClause;_limitVal;_pageSizeVal;_consistentReadVal;_sortForward=!0;_forcedIndexName;where(e){return this._whereClause=e,this}limit(e){return this._limitVal=e,this}pageSize(e){return this._pageSizeVal=e,this}consistentRead(e=!0){return this._consistentReadVal=e,this}sort(e){return this._sortForward=e,this}index(e){return this._forcedIndexName=e,this}iterator(){return async function*(){let e,i=0;do{let n=await this.fetchPage(e);for(let s of n.items)if(yield s,i++,this._limitVal!==void 0&&i>=this._limitVal)return;e=n.lastEvaluatedKey}while(e)}.bind(this)()}async fetchPage(e){let i=this.resolveKeys(this._whereClause,void 0,this._forcedIndexName);return i.hasPartitionKey&&i.hasSortKey&&!i.indexName&&!e?{items:await this.executeGet(i.keys)}:i.hasPartitionKey||i.indexName?await this.executeQuery(i,e):await this.executeScan(e)}async execute(){let{items:e}=await this.fetchPage();return e}async executeGet(e){let i=new ie({TableName:this.tableName,Key:e,ConsistentRead:this._consistentReadVal}),n=await this.client.send(i);return n.Item?[this.mapToLogical(n.Item)]:[]}async executeQuery(e,i){let{expressionAttributeNames:n,expressionAttributeValues:s,addName:r,addValue:o}=this.createExpressionContext(),a=[],c=new Set;for(let[p,_]of Object.entries(e.keys))a.push(`${r(p)} = ${o(_)}`),c.add(p);let m=a.join(" AND "),u=this._whereClause?z(this._whereClause,r,o,c):void 0,f=new se({TableName:this.tableName,IndexName:e.indexName,KeyConditionExpression:m,FilterExpression:u||void 0,ExpressionAttributeNames:Object.keys(n).length>0?n:void 0,ExpressionAttributeValues:Object.keys(s).length>0?s:void 0,Limit:this._pageSizeVal??this._limitVal,ScanIndexForward:this._sortForward,ConsistentRead:e.indexName?void 0:this._consistentReadVal,ExclusiveStartKey:i}),T=await this.client.send(f);return{items:(T.Items||[]).map(p=>this.mapToLogical(p)),lastEvaluatedKey:T.LastEvaluatedKey}}async executeScan(e){let{expressionAttributeNames:i,expressionAttributeValues:n,addName:s,addValue:r}=this.createExpressionContext(),o=this._whereClause?z(this._whereClause,s,r):void 0,a=new oe({TableName:this.tableName,FilterExpression:o,ExpressionAttributeNames:Object.keys(i).length>0?i:void 0,ExpressionAttributeValues:Object.keys(n).length>0?n:void 0,Limit:this._pageSizeVal??this._limitVal,ConsistentRead:this._consistentReadVal,ExclusiveStartKey:e}),c=await this.client.send(a);return{items:(c.Items||[]).map(m=>this.mapToLogical(m)),lastEvaluatedKey:c.LastEvaluatedKey}}};var N=class{constructor(t){this.schema=t}parse(t,e,i={}){let n=this.schema.entities[e];if(!n)throw new Error(`Root entity ${e} not found in schema`);let s=[],r=[];for(let o of t)this.isEntity(o,n.entity)?s.push({...o}):r.push(o);for(let o of s)for(let[a,c]of Object.entries(i)){if(!c)continue;let m=n.relations[a];if(!m)continue;let u=m.config.to,f=r.filter(T=>this.isEntity(T,u));f.length>0&&(m.type==="many"?o[a]=f:m.type==="one"&&(o[a]=f[0]||null))}return s}isEntity(t,e){let i=e[d.ENTITY_STRATEGY],n=e[d.PHYSICAL_TABLE];if(!n||!n[E.PARTITION_KEY])return!1;let s=n[E.PARTITION_KEY].name,r=n[E.SORT_KEY]?.name,o=this.matchStrategy(t[s],i.pk),a=r?this.matchStrategy(t[r],i.sk):!0;return o&&a}matchStrategy(t,e){if(!e)return!0;if(t==null)return!1;let i=String(t);if(e.type==="static")return i===e.segments[0];if(e.type==="prefix"||e.type==="composite"){let n=e.segments[0];return typeof n=="string"&&i.startsWith(n)}return!1}};var b=class l{constructor(t,e,i,n){this.client=t;this.table=e;this.schema=i;this.entityName=n}async findFirst(t={}){return(await this.findMany({...t,limit:1}))[0]}async findMany(t={}){let e=new I(this.table,this.client,void 0);t.orderBy&&e.sort(t.orderBy==="asc");let i;if(t.where){let r=this.table._?.columns||this.table;typeof t.where=="function"?i=t.where(r,G):i=t.where}let n,s=L(this.table,i);if(this.schema&&this.entityName&&(t.with||t.include)&&s.hasPartitionKey&&!s.indexName){let r=this.table[d.PHYSICAL_TABLE];if(!r)throw new Error("Physical table not found for entity");let o=r[E.PARTITION_KEY].name,a=s.keys[o];e.where(P({name:o},a));let m=(await e).map(f=>v(this.table,f));n=new N(this.schema).parse(m,this.entityName,t.with||t.include),t.limit&&(n=n.slice(0,t.limit))}else t.limit&&e.limit(t.limit),i&&e.where(i),n=await e;if(this.schema&&this.entityName&&(t.with||t.include)){let r=t.with||t.include;await Promise.all(n.map(async o=>{for(let[a,c]of Object.entries(r)){let m=this.schema.entities[this.entityName];if(!m)continue;let u=m.relations[a];if(!u)continue;let f=o[a]!==void 0,T=typeof c=="object"&&(c.with||c.include);if(f&&!T)continue;let p=u.config.to,_=Object.entries(this.schema.entities).find(([R,y])=>y.entity===p)?.[0],V=v(this.table,o);if(u.config.fields&&u.config.references){let R={};u.config.fields.forEach((y,g)=>{let h=u.config.references[g];if(!h)return;let F=Object.entries(p[d.COLUMNS]).find(([K,C])=>C===h||C.name===h.name)?.[0];if(F){let K=Object.entries(this.table[d.COLUMNS]).find(([de,W])=>W===y||W.name===y.name)?.[0],C=K?o[K]??o[y.name]:o[y.name];C!==void 0&&(R[F]=C)}}),V=R}let j=L(p,void 0,V);if(j.hasPartitionKey){let R=new l(this.client,p,this.schema,_),y=[];for(let[g,h]of Object.entries(j.keys))y.push(P({name:g},h));if(y.length>0){let g=y.length===1?y[0]:q(...y),h=typeof c=="object"?c:{};u.type==="one"?o[a]=await R.findFirst({...h,where:g}):o[a]=await R.findMany({...h,where:g})}}}}))}return n}};import{BatchGetCommand as re}from"@aws-sdk/lib-dynamodb";var M=class{constructor(t){this.client=t}items(t,e){return new A(t,this.client,e)}},A=class extends w{constructor(e,i,n){super(e,i);this.keysData=n}static[d.ENTITY_KIND]="BatchGetBase";async execute(){let e=[],i=[],n=this.keysData.map(o=>this.resolveKeys(void 0,o).keys),s=0,r=5;for(;n.length>0&&s<r;){s++;let o=new re({RequestItems:{[this.tableName]:{Keys:n}}}),a=await this.client.send(o);a.Responses?.[this.tableName]&&e.push(...a.Responses[this.tableName]);let c=a.UnprocessedKeys?.[this.tableName]?.Keys;c&&c.length>0?n=c:n=[]}return n.length>0&&i.push(...n),{succeeded:e,failed:i}}};import{BatchWriteCommand as ae}from"@aws-sdk/lib-dynamodb";var B=class{constructor(t){this.client=t}operations(t,e){return new Y(t,this.client,e)}},Y=class extends w{constructor(e,i,n){super(e,i);this.ops=n}static[d.ENTITY_KIND]="BatchWriteBase";async execute(){let e=0,i=[],s=[...this.ops.map(a=>{if(a.type==="put"){let c=a.item;if(H(c)>400*1024)throw new $("Item in batch exceeds the 400KB limit.");return{PutRequest:{Item:c}}}else return{DeleteRequest:{Key:a.keys}}})],r=0,o=5;for(;s.length>0&&r<o;){r++;let a=new ae({RequestItems:{[this.tableName]:s}}),m=(await this.client.send(a)).UnprocessedItems?.[this.tableName]||[];e+=s.length-m.length,m.length>0?s=m:s=[]}return s.length>0&&(i=s),{succeededCount:e,failed:i}}};var x=class{constructor(t,e){this.type=t;this.config=e}};function st(l,t){if(l instanceof D){let i=t({one:(n,s)=>new x("one",{to:n,...s}),many:(n,s)=>new x("many",{to:n,...s})});return{entity:l,config:i,[k.RELATION_CONFIG]:!0}}else{let e=l,i=t,n={one:{},many:{}};for(let[r,o]of Object.entries(e))n.one[r]=a=>new x("one",{to:o,...a}),n.many[r]=a=>new x("many",{to:o,...a}),n[r]=o;let s=i(n);return{schema:e,definitions:s,[k.RELATION_CONFIG]:!0}}}function te(l){let t={entities:{}};for(let[e,i]of Object.entries(l))i instanceof D&&(t.entities[e]={entity:i,relations:{}});for(let[,e]of Object.entries(l))if(e&&typeof e=="object"&&e[k.RELATION_CONFIG]){let i=e;if(i.entity){let n=e,s=Object.entries(t.entities).find(([r,o])=>o.entity===n.entity);if(s){let[,r]=s;r.relations={...r.relations,...n.config}}}else if(i.definitions){let n=e;for(let[s,r]of Object.entries(n.definitions)){let o=n.schema[s],a=Object.entries(t.entities).find(([c,m])=>m.entity===o);if(a&&r){let[,c]=a;c.relations={...c.relations,...r}}}}}return t}var S=class{docClient;schema;retryConfig;query;constructor(t,e,i){this.retryConfig={maxAttempts:i?.maxAttempts??3,baseDelay:i?.baseDelay??100},this.docClient=new U(le.from(t),new Q(this.retryConfig)),e&&(this.schema=te(e)),this.query=new Proxy({},{get:(n,s)=>{if(typeof s!="string")return;if(!this.schema)throw new Error("No relations defined. Initialize mizzle with a relations object to use db.query.");let r=this.schema.entities[s];if(!r)throw new Error(`Entity ${s} not found in relations schema.`);return new b(this.docClient,r.entity,this.schema,s)}})}insert(t){return new J(t,this.docClient)}select(t){return new O(this.docClient,t)}batchGet(t,e){return new M(this.docClient).items(t,e)}batchWrite(t,e){return new B(this.docClient).operations(t,e)}_query(t){return new b(this.docClient,t)}update(t){return new X(t,this.docClient)}delete(t,e){return new Z(t,this.docClient,e)}async transaction(t,e){let i=new ee(this.docClient),n=await e(i);if(n.length===0)return;if(n.length>100)throw new Error("DynamoDB transactions are limited to 100 items.");let{TransactionExecutor:s}=await import("./transaction-RE7LXTGV.js");await new s(this.docClient).execute(t,n)}};function gt(l){return l instanceof ne?new S(l):"client"in l&&l.client instanceof ne?new S(l.client,l.relations,l.retry):"client"in l&&l.client?new S(l.client,l.relations,l.retry):new S(l)}export{O as a,I as b,M as c,A as d,B as e,Y as f,b as g,x as h,st as i,te as j,S as k,gt as l};
1
+ import{D as Q,E as U,I as L,J as w,K as H,L as $,N as J,P as X,Q as Z,S as ee,e as P,p as q,q as G,r as z}from"./chunk-UM3YF5EC.js";import{b as D}from"./chunk-GPYZK4WY.js";import{d as E,e as d,f as C,i as v}from"./chunk-DU7UPWBW.js";import{DynamoDBClient as ne}from"@aws-sdk/client-dynamodb";import{DynamoDBDocumentClient as le}from"@aws-sdk/lib-dynamodb";import{GetCommand as ie,QueryCommand as se,ScanCommand as oe}from"@aws-sdk/lib-dynamodb";var O=class{constructor(t,e){this.client=t;this.fields=e}from(t){return new b(t,this.client,this.fields)}},b=class extends w{constructor(e,i,n){super(e,i);this.fields=n}static[d.ENTITY_KIND]="SelectBase";_whereClause;_limitVal;_pageSizeVal;_consistentReadVal;_sortForward=!0;_forcedIndexName;where(e){return this._whereClause=e,this}limit(e){return this._limitVal=e,this}pageSize(e){return this._pageSizeVal=e,this}consistentRead(e=!0){return this._consistentReadVal=e,this}sort(e){return this._sortForward=e,this}index(e){return this._forcedIndexName=e,this}iterator(){return async function*(){let e,i=0;do{let n=await this.fetchPage(e);for(let s of n.items)if(yield s,i++,this._limitVal!==void 0&&i>=this._limitVal)return;e=n.lastEvaluatedKey}while(e)}.bind(this)()}async fetchPage(e){let i=this.resolveKeys(this._whereClause,void 0,this._forcedIndexName);return i.hasPartitionKey&&i.hasSortKey&&!i.indexName&&!e?{items:await this.executeGet(i.keys)}:i.hasPartitionKey||i.indexName?await this.executeQuery(i,e):await this.executeScan(e)}async execute(){let{items:e}=await this.fetchPage();return e}async executeGet(e){let i=new ie({TableName:this.tableName,Key:e,ConsistentRead:this._consistentReadVal}),n=await this.client.send(i);return n.Item?[this.mapToLogical(n.Item)]:[]}async executeQuery(e,i){let{expressionAttributeNames:n,expressionAttributeValues:s,addName:r,addValue:o}=this.createExpressionContext(),l=[],c=new Set;for(let[p,_]of Object.entries(e.keys))l.push(`${r(p)} = ${o(_)}`),c.add(p);let m=l.join(" AND "),u=this._whereClause?z(this._whereClause,r,o,c):void 0,f=new se({TableName:this.tableName,IndexName:e.indexName,KeyConditionExpression:m,FilterExpression:u||void 0,ExpressionAttributeNames:Object.keys(n).length>0?n:void 0,ExpressionAttributeValues:Object.keys(s).length>0?s:void 0,Limit:this._pageSizeVal??this._limitVal,ScanIndexForward:this._sortForward,ConsistentRead:e.indexName?void 0:this._consistentReadVal,ExclusiveStartKey:i}),T=await this.client.send(f);return{items:(T.Items||[]).map(p=>this.mapToLogical(p)),lastEvaluatedKey:T.LastEvaluatedKey}}async executeScan(e){let{expressionAttributeNames:i,expressionAttributeValues:n,addName:s,addValue:r}=this.createExpressionContext(),o=this._whereClause?z(this._whereClause,s,r):void 0,l=new oe({TableName:this.tableName,FilterExpression:o,ExpressionAttributeNames:Object.keys(i).length>0?i:void 0,ExpressionAttributeValues:Object.keys(n).length>0?n:void 0,Limit:this._pageSizeVal??this._limitVal,ConsistentRead:this._consistentReadVal,ExclusiveStartKey:e}),c=await this.client.send(l);return{items:(c.Items||[]).map(m=>this.mapToLogical(m)),lastEvaluatedKey:c.LastEvaluatedKey}}};var M=class{constructor(t){this.schema=t}parse(t,e,i={}){let n=this.schema.entities[e];if(!n)throw new Error(`Root entity ${e} not found in schema`);let s=[],r=[];for(let o of t)this.isEntity(o,n.entity)?s.push({...o}):r.push(o);for(let o of s)for(let[l,c]of Object.entries(i)){if(!c)continue;let m=n.relations[l];if(!m)continue;let u=m.config.to,f=r.filter(T=>this.isEntity(T,u));f.length>0&&(m.type==="many"?o[l]=f:m.type==="one"&&(o[l]=f[0]||null))}return s}isEntity(t,e){let i=e[d.ENTITY_STRATEGY],n=e[d.PHYSICAL_TABLE];if(!n||!n[E.PARTITION_KEY])return!1;let s=n[E.PARTITION_KEY].name,r=n[E.SORT_KEY]?.name,o=this.matchStrategy(t[s],i.pk),l=r?this.matchStrategy(t[r],i.sk):!0;return o&&l}matchStrategy(t,e){if(!e)return!0;if(t==null)return!1;let i=String(t);if(e.type==="static")return i===e.segments[0];if(e.type==="prefix"||e.type==="composite"){let n=e.segments[0];return typeof n=="string"&&i.startsWith(n)}return!1}};var k=class a{constructor(t,e,i,n){this.client=t;this.table=e;this.schema=i;this.entityName=n}async findFirst(t={}){return(await this.findMany({...t,limit:1}))[0]}async findMany(t={}){let e=new b(this.table,this.client,void 0);t.orderBy&&e.sort(t.orderBy==="asc");let i;if(t.where){let r=this.table._?.columns||this.table;typeof t.where=="function"?i=t.where(r,G):i=t.where}let n,s=L(this.table,i);if(this.schema&&this.entityName&&(t.with||t.include)&&s.hasPartitionKey&&!s.indexName){let r=this.table[d.PHYSICAL_TABLE];if(!r)throw new Error("Physical table not found for entity");let o=r[E.PARTITION_KEY].name,l=s.keys[o];e.where(P({name:o},l));let m=(await e).map(f=>v(this.table,f));n=new M(this.schema).parse(m,this.entityName,t.with||t.include),t.limit&&(n=n.slice(0,t.limit))}else t.limit&&e.limit(t.limit),i&&e.where(i),n=await e;if(this.schema&&this.entityName&&(t.with||t.include)){let r=t.with||t.include;await Promise.all(n.map(async o=>{for(let[l,c]of Object.entries(r)){let m=this.schema.entities[this.entityName];if(!m)continue;let u=m.relations[l];if(!u)continue;let f=o[l]!==void 0,T=typeof c=="object"&&(c.with||c.include);if(f&&!T)continue;let p=u.config.to,_=Object.entries(this.schema.entities).find(([R,y])=>y.entity===p)?.[0],V=v(this.table,o);if(u.config.fields&&u.config.references){let R={};u.config.fields.forEach((y,g)=>{let h=u.config.references[g];if(!h)return;let F=Object.entries(p[d.COLUMNS]).find(([K,I])=>I===h||I.name===h.name)?.[0];if(F){let K=Object.entries(this.table[d.COLUMNS]).find(([de,W])=>W===y||W.name===y.name)?.[0],I=K?o[K]??o[y.name]:o[y.name];I!==void 0&&(R[F]=I)}}),V=R}let j=L(p,void 0,V);if(j.hasPartitionKey){let R=new a(this.client,p,this.schema,_),y=[];for(let[g,h]of Object.entries(j.keys))y.push(P({name:g},h));if(y.length>0){let g=y.length===1?y[0]:q(...y),h=typeof c=="object"?c:{};u.type==="one"?o[l]=await R.findFirst({...h,where:g}):o[l]=await R.findMany({...h,where:g})}}}}))}return n}};import{BatchGetCommand as re}from"@aws-sdk/lib-dynamodb";var N=class{constructor(t){this.client=t}items(t,e){return new A(t,this.client,e)}},A=class extends w{constructor(e,i,n){super(e,i);this.keysData=n}static[d.ENTITY_KIND]="BatchGetBase";async execute(){let e=[],i=[],n=this.keysData.map(o=>this.resolveKeys(void 0,o).keys),s=0,r=5;for(;n.length>0&&s<r;){s++;let o=new re({RequestItems:{[this.tableName]:{Keys:n}}}),l=await this.client.send(o);l.Responses?.[this.tableName]&&e.push(...l.Responses[this.tableName]);let c=l.UnprocessedKeys?.[this.tableName]?.Keys;c&&c.length>0?n=c:n=[]}return n.length>0&&i.push(...n),{succeeded:e,failed:i}}};import{BatchWriteCommand as ae}from"@aws-sdk/lib-dynamodb";var B=class{constructor(t){this.client=t}operations(t,e){return new Y(t,this.client,e)}},Y=class extends w{constructor(e,i,n){super(e,i);this.ops=n}static[d.ENTITY_KIND]="BatchWriteBase";async execute(){let e=0,i=[],s=[...this.ops.map(l=>{if(l.type==="put"){let c=l.item;if(H(c)>400*1024)throw new $("Item in batch exceeds the 400KB limit.");return{PutRequest:{Item:c}}}else return{DeleteRequest:{Key:l.keys}}})],r=0,o=5;for(;s.length>0&&r<o;){r++;let l=new ae({RequestItems:{[this.tableName]:s}}),m=(await this.client.send(l)).UnprocessedItems?.[this.tableName]||[];e+=s.length-m.length,m.length>0?s=m:s=[]}return s.length>0&&(i=s),{succeededCount:e,failed:i}}};var x=class{constructor(t,e){this.type=t;this.config=e}};function st(a,t){if(a instanceof D){let i=t({one:(n,s)=>new x("one",{to:n,...s}),many:(n,s)=>new x("many",{to:n,...s})});return{entity:a,config:i,[C.RELATION_CONFIG]:!0}}else{let e=a,i=t,n={one:{},many:{}};for(let[r,o]of Object.entries(e))n.one[r]=l=>new x("one",{to:o,...l}),n.many[r]=l=>new x("many",{to:o,...l}),n[r]=o;let s=i(n);return{schema:e,definitions:s,[C.RELATION_CONFIG]:!0}}}function te(a){let t={entities:{}};if(a&&a[C.RELATION_CONFIG]&&a.definitions){let e=a;for(let[i,n]of Object.entries(e.schema))t.entities[i]={entity:n,relations:e.definitions[i]||{}};return t}for(let[e,i]of Object.entries(a))i instanceof D&&(t.entities[e]={entity:i,relations:{}});for(let[,e]of Object.entries(a))if(e&&typeof e=="object"&&e[C.RELATION_CONFIG]){let i=e;if(i.entity){let n=e,s=Object.entries(t.entities).find(([r,o])=>o.entity===n.entity);if(s){let[,r]=s;r.relations={...r.relations,...n.config}}}else if(i.definitions){let n=e;for(let[s,r]of Object.entries(n.definitions)){let o=n.schema[s],l=Object.entries(t.entities).find(([c,m])=>m.entity===o);if(l&&r){let[,c]=l;c.relations={...c.relations,...r}}}}}return t}var S=class{docClient;schema;retryConfig;query;constructor(t,e,i){this.retryConfig={maxAttempts:i?.maxAttempts??3,baseDelay:i?.baseDelay??100},this.docClient=new U(le.from(t),new Q(this.retryConfig)),e&&(this.schema=te(e)),this.query=new Proxy({},{get:(n,s)=>{if(typeof s!="string")return;if(!this.schema)throw new Error("No relations defined. Initialize mizzle with a relations object to use db.query.");let r=this.schema.entities[s];if(!r)throw new Error(`Entity ${s} not found in relations schema.`);return new k(this.docClient,r.entity,this.schema,s)}})}insert(t){return new J(t,this.docClient)}select(t){return new O(this.docClient,t)}batchGet(t,e){return new N(this.docClient).items(t,e)}batchWrite(t,e){return new B(this.docClient).operations(t,e)}_query(t){return new k(this.docClient,t)}update(t){return new X(t,this.docClient)}delete(t,e){return new Z(t,this.docClient,e)}async transaction(t,e){let i=new ee(this.docClient),n=await e(i);if(n.length===0)return;if(n.length>100)throw new Error("DynamoDB transactions are limited to 100 items.");let{TransactionExecutor:s}=await import("./transaction-RE7LXTGV.js");await new s(this.docClient).execute(t,n)}};function gt(a){return a instanceof ne?new S(a):"client"in a&&a.client instanceof ne?new S(a.client,a.relations,a.retry):"client"in a&&a.client?new S(a.client,a.relations,a.retry):new S(a)}export{O as a,b,N as c,A as d,B as e,Y as f,k as g,x as h,st as i,te as j,S as k,gt as l};
@@ -654,7 +654,9 @@ declare class RelationnalQueryBuilder<T extends Entity> {
654
654
  findMany<TOptions extends RelationalQueryOptions<T>>(options?: TOptions): Promise<InferRelationalModel<T, TOptions>[]>;
655
655
  }
656
656
 
657
- type QuerySchema<TSchema extends Record<string, any>> = {
657
+ type QuerySchema<TSchema extends Record<string, any>> = TSchema extends MultiRelationsDefinition<infer T> ? {
658
+ [K in keyof T]: RelationnalQueryBuilder<T[K]>;
659
+ } : {
658
660
  [K in keyof TSchema as TSchema[K] extends Entity ? K : never]: RelationnalQueryBuilder<TSchema[K] extends Entity ? TSchema[K] : never>;
659
661
  };
660
662
  /**
package/dist/db.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  import './operators-BVreW0ky.js';
2
- export { i as DynamoDB, M as MizzleConfig, Q as QuerySchema, X as mizzle } from './db-zHIHBm1E.js';
2
+ export { i as DynamoDB, M as MizzleConfig, Q as QuerySchema, X as mizzle } from './db-ZX6HGN1x.js';
3
3
  import '@aws-sdk/client-dynamodb';
package/dist/db.js CHANGED
@@ -1 +1 @@
1
- import{k as a,l as b}from"./chunk-NPPZW6VT.js";import"./chunk-UM3YF5EC.js";import"./chunk-GPYZK4WY.js";import"./chunk-DU7UPWBW.js";export{a as DynamoDB,b as mizzle};
1
+ import{k as a,l as b}from"./chunk-WTOBEKFQ.js";import"./chunk-UM3YF5EC.js";import"./chunk-GPYZK4WY.js";import"./chunk-DU7UPWBW.js";export{a as DynamoDB,b as mizzle};
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { E as Expression } from './operators-BVreW0ky.js';
2
2
  export { A as AnyTable, a as Assume, b as AtomicValues, B as BinaryExpression, C as ColumnType, c as ColumnsBuilder, d as Condition, e as ENTITY_SYMBOLS, f as Entity, g as EntityConfig, h as EntityWithColumns, F as FunctionExpression, I as INFER_MODE, i as IndexBuilder, j as IndexColumnConfig, k as InferInsertModel, l as InferModelFromColumns, m as InferSelectModel, n as InferSelectedModel, K as KeyStrategy, o as KeyStrategyType, L as LogicalExpression, M as MapColumnName, N as NULLS, O as ORDER, p as Operators, P as PhysicalTable, q as PhysicalTableConfig, R as RELATION_SYMBOLS, S as Simplify, r as StrategyCallback, s as StrategyResolution, T as TABLE_SYMBOLS, t as TableDefinition, U as Update, u as UpdateTableConfig, v as and, w as attributeExists, x as beginsWith, y as between, z as binary, D as binarySet, G as boolean, H as compositeKey, J as contains, Q as date, V as dynamoEntity, W as dynamoTable, X as eq, Y as getColumnBuilders, Z as getEntityColumns, _ as gsi, $ as gt, a0 as gte, a1 as inList, a2 as json, a3 as list, a4 as lsi, a5 as lt, a6 as lte, a7 as map, a8 as mapToLogical, a9 as number, aa as numberSet, ab as operators, ac as or, ad as prefixKey, ae as resolveStrategies, af as resolveTableName, ag as staticKey, ah as string, ai as stringSet, aj as uuid } from './operators-BVreW0ky.js';
3
- export { A as ActionType, a as AddAction, B as BatchGetBase, b as BatchGetBuilder, c as BatchGetResult, d as BatchWriteBase, e as BatchWriteBuilder, f as BatchWriteOperation, g as BatchWriteResult, C as ConditionCheckBuilder, D as DeleteAction, h as DeleteBuilder, i as DynamoDB, E as EntityMetadata, I as IncludeOptions, j as InferRelationalModel, k as InsertBase, l as InsertBuilder, m as InternalRelationalSchema, M as MizzleConfig, n as MultiRelationsCallback, o as MultiRelationsDefinition, Q as QuerySchema, R as Relation, p as RelationConfig, q as RelationType, r as RelationalQueryOptions, s as RelationnalQueryBuilder, t as RelationsCallback, u as RelationsDefinition, v as RelationsHelpers, w as RemoveAction, x as RetryConfig, y as RetryHandler, S as SelectBase, z as SelectBuilder, F as SelectedFields, G as SetAction, T as TransactionExecutor, H as TransactionProxy, U as UpdateAction, J as UpdateBuilder, K as add, L as addToSet, N as append, O as defineRelations, P as deleteFromSet, V as extractMetadata, W as ifNotExists, X as mizzle, Y as remove } from './db-zHIHBm1E.js';
3
+ export { A as ActionType, a as AddAction, B as BatchGetBase, b as BatchGetBuilder, c as BatchGetResult, d as BatchWriteBase, e as BatchWriteBuilder, f as BatchWriteOperation, g as BatchWriteResult, C as ConditionCheckBuilder, D as DeleteAction, h as DeleteBuilder, i as DynamoDB, E as EntityMetadata, I as IncludeOptions, j as InferRelationalModel, k as InsertBase, l as InsertBuilder, m as InternalRelationalSchema, M as MizzleConfig, n as MultiRelationsCallback, o as MultiRelationsDefinition, Q as QuerySchema, R as Relation, p as RelationConfig, q as RelationType, r as RelationalQueryOptions, s as RelationnalQueryBuilder, t as RelationsCallback, u as RelationsDefinition, v as RelationsHelpers, w as RemoveAction, x as RetryConfig, y as RetryHandler, S as SelectBase, z as SelectBuilder, F as SelectedFields, G as SetAction, T as TransactionExecutor, H as TransactionProxy, U as UpdateAction, J as UpdateBuilder, K as add, L as addToSet, N as append, O as defineRelations, P as deleteFromSet, V as extractMetadata, W as ifNotExists, X as mizzle, Y as remove } from './db-ZX6HGN1x.js';
4
4
  export { SchemaChange, compareSchema } from './diff.js';
5
5
  import '@aws-sdk/client-dynamodb';
6
6
  import './snapshot.js';
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{a as Dr}from"./chunk-TOYV2M4M.js";import"./chunk-AQVECMXP.js";import{a as lr,b as kr,c as Ir,d as dr,e as hr,f as jr,g as qr,h as vr,i as zr,j as Ar,k as Er,l as Fr}from"./chunk-NPPZW6VT.js";import{A as O,B as P,C as Q,D as fr,F as xr,G as mr,H as nr,I as ir,L as sr,M as gr,N as cr,O as ur,P as Cr,Q as ar,R as br,S as wr,T as yr,a as u,b as l,c as k,d as C,e as a,f as b,g as w,h as y,i as I,j as d,k as h,l as j,m as q,n as v,o as z,p as A,q as D,r as E,s as F,t as G,u as H,v as J,w as K,x as L,y as M,z as N}from"./chunk-UM3YF5EC.js";import{a as or,b as tr,c as er,d as pr}from"./chunk-GPYZK4WY.js";import{a as p,b as f,c as x,d as m,e as n,f as i,g as s,h as g,i as c,k as R,l as S,m as T,n as U,o as V,p as W,q as X,r as Y,s as Z,t as _,u as $,v as B,w as rr}from"./chunk-DU7UPWBW.js";var o=class{constructor(t,e){this.type=t;this.config=e}};function Gr(r,t){return new o("gsi",{pk:r,sk:t})}function Hr(r){return new o("lsi",{sk:r})}export{H as AddAction,dr as BatchGetBase,Ir as BatchGetBuilder,jr as BatchWriteBase,hr as BatchWriteBuilder,l as BinaryExpression,br as ConditionCheckBuilder,K as DeleteAction,ar as DeleteBuilder,Er as DynamoDB,n as ENTITY_SYMBOLS,tr as Entity,u as Expression,C as FunctionExpression,p as INFER_MODE,o as IndexBuilder,ur as InsertBase,cr as InsertBuilder,sr as ItemSizeExceededError,k as LogicalExpression,x as NULLS,f as ORDER,or as PhysicalTable,i as RELATION_SYMBOLS,vr as Relation,qr as RelationnalQueryBuilder,J as RemoveAction,fr as RetryHandler,kr as SelectBase,lr as SelectBuilder,G as SetAction,m as TABLE_SYMBOLS,yr as TransactionExecutor,gr as TransactionFailedError,wr as TransactionProxy,F as UpdateAction,Cr as UpdateBuilder,L as add,P as addToSet,A as and,M as append,v as attributeExists,j as beginsWith,d as between,R as binary,S as binarySet,T as boolean,E as buildExpression,Dr as compareSchema,nr as compositeKey,q as contains,U as date,zr as defineRelations,Q as deleteFromSet,er as dynamoEntity,pr as dynamoTable,a as eq,Ar as extractMetadata,rr as getColumnBuilders,s as getEntityColumns,Gr as gsi,b as gt,w as gte,N as ifNotExists,h as inList,B as json,V as list,Hr as lsi,y as lt,I as lte,W as map,c as mapToLogical,Fr as mizzle,X as number,Y as numberSet,D as operators,z as or,mr as prefixKey,O as remove,ir as resolveStrategies,g as resolveTableName,xr as staticKey,Z as string,_ as stringSet,$ as uuid};
1
+ import{a as Dr}from"./chunk-TOYV2M4M.js";import"./chunk-AQVECMXP.js";import{a as lr,b as kr,c as Ir,d as dr,e as hr,f as jr,g as qr,h as vr,i as zr,j as Ar,k as Er,l as Fr}from"./chunk-WTOBEKFQ.js";import{A as O,B as P,C as Q,D as fr,F as xr,G as mr,H as nr,I as ir,L as sr,M as gr,N as cr,O as ur,P as Cr,Q as ar,R as br,S as wr,T as yr,a as u,b as l,c as k,d as C,e as a,f as b,g as w,h as y,i as I,j as d,k as h,l as j,m as q,n as v,o as z,p as A,q as D,r as E,s as F,t as G,u as H,v as J,w as K,x as L,y as M,z as N}from"./chunk-UM3YF5EC.js";import{a as or,b as tr,c as er,d as pr}from"./chunk-GPYZK4WY.js";import{a as p,b as f,c as x,d as m,e as n,f as i,g as s,h as g,i as c,k as R,l as S,m as T,n as U,o as V,p as W,q as X,r as Y,s as Z,t as _,u as $,v as B,w as rr}from"./chunk-DU7UPWBW.js";var o=class{constructor(t,e){this.type=t;this.config=e}};function Gr(r,t){return new o("gsi",{pk:r,sk:t})}function Hr(r){return new o("lsi",{sk:r})}export{H as AddAction,dr as BatchGetBase,Ir as BatchGetBuilder,jr as BatchWriteBase,hr as BatchWriteBuilder,l as BinaryExpression,br as ConditionCheckBuilder,K as DeleteAction,ar as DeleteBuilder,Er as DynamoDB,n as ENTITY_SYMBOLS,tr as Entity,u as Expression,C as FunctionExpression,p as INFER_MODE,o as IndexBuilder,ur as InsertBase,cr as InsertBuilder,sr as ItemSizeExceededError,k as LogicalExpression,x as NULLS,f as ORDER,or as PhysicalTable,i as RELATION_SYMBOLS,vr as Relation,qr as RelationnalQueryBuilder,J as RemoveAction,fr as RetryHandler,kr as SelectBase,lr as SelectBuilder,G as SetAction,m as TABLE_SYMBOLS,yr as TransactionExecutor,gr as TransactionFailedError,wr as TransactionProxy,F as UpdateAction,Cr as UpdateBuilder,L as add,P as addToSet,A as and,M as append,v as attributeExists,j as beginsWith,d as between,R as binary,S as binarySet,T as boolean,E as buildExpression,Dr as compareSchema,nr as compositeKey,q as contains,U as date,zr as defineRelations,Q as deleteFromSet,er as dynamoEntity,pr as dynamoTable,a as eq,Ar as extractMetadata,rr as getColumnBuilders,s as getEntityColumns,Gr as gsi,b as gt,w as gte,N as ifNotExists,h as inList,B as json,V as list,Hr as lsi,y as lt,I as lte,W as map,c as mapToLogical,Fr as mizzle,X as number,Y as numberSet,D as operators,z as or,mr as prefixKey,O as remove,ir as resolveStrategies,g as resolveTableName,xr as staticKey,Z as string,_ as stringSet,$ as uuid};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aurios/mizzle",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
4
4
  "description": "a drizzle-like orm for dynamoDB",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -238,6 +238,18 @@ export function extractMetadata(schema: Record<string, unknown>): InternalRelati
238
238
  entities: {},
239
239
  };
240
240
 
241
+ // If the schema itself is a MultiRelationsDefinition, unwrap it
242
+ if (schema && (schema as any)[RELATION_SYMBOLS.RELATION_CONFIG] && (schema as any).definitions) {
243
+ const multiDef = schema as unknown as MultiRelationsDefinition;
244
+ for (const [key, entity] of Object.entries(multiDef.schema)) {
245
+ metadata.entities[key] = {
246
+ entity,
247
+ relations: multiDef.definitions[key] || {},
248
+ };
249
+ }
250
+ return metadata;
251
+ }
252
+
241
253
  // First pass: identify entities
242
254
  for (const [key, value] of Object.entries(schema)) {
243
255
  if (value instanceof Entity) {
package/src/db.ts CHANGED
@@ -10,15 +10,21 @@ import { DeleteBuilder } from "./builders/delete";
10
10
  import { BatchGetBuilder } from "./builders/batch-get";
11
11
  import { BatchWriteBuilder, type BatchWriteOperation } from "./builders/batch-write";
12
12
  import { TransactionProxy } from "./builders/transaction";
13
- import { extractMetadata, type InternalRelationalSchema } from "./core/relations";
13
+ import { extractMetadata, type InternalRelationalSchema, type MultiRelationsDefinition } from "./core/relations";
14
14
  import { RetryHandler, type RetryConfig } from "./core/retry";
15
15
  import { MizzleClient, type IMizzleClient } from "./core/client";
16
16
 
17
- export type QuerySchema<TSchema extends Record<string, any>> = {
18
- [K in keyof TSchema as TSchema[K] extends Entity ? K : never]: RelationnalQueryBuilder<
19
- TSchema[K] extends Entity ? TSchema[K] : never
20
- >;
21
- };
17
+ export type QuerySchema<TSchema extends Record<string, any>> = TSchema extends MultiRelationsDefinition<
18
+ infer T
19
+ >
20
+ ? {
21
+ [K in keyof T]: RelationnalQueryBuilder<T[K]>;
22
+ }
23
+ : {
24
+ [K in keyof TSchema as TSchema[K] extends Entity ? K : never]: RelationnalQueryBuilder<
25
+ TSchema[K] extends Entity ? TSchema[K] : never
26
+ >;
27
+ };
22
28
 
23
29
  /**
24
30
  * DynamoDB database instance.
@@ -0,0 +1,33 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
3
+ import { dynamoTable, dynamoEntity } from "../src/core/table";
4
+ import { defineRelations } from "../src/core/relations";
5
+ import { string, uuid } from "../src/columns";
6
+ import { mizzle } from "../src/db";
7
+
8
+ describe("User Issue Reproduction: MultiRelationsDefinition as schema", () => {
9
+ const table = dynamoTable("mizzle-test", {
10
+ pk: string("pk"),
11
+ sk: string("sk"),
12
+ });
13
+
14
+ const shoppingLists = dynamoEntity(table, "shoppingLists", {
15
+ id: uuid("id"),
16
+ name: string("name"),
17
+ });
18
+
19
+ const client = new DynamoDBClient({ region: "us-east-1" });
20
+
21
+ it("should allow using MultiRelationsDefinition directly in mizzle config", () => {
22
+ const relations = defineRelations({ shoppingLists }, () => ({}));
23
+
24
+ const db = mizzle({
25
+ client,
26
+ relations
27
+ });
28
+
29
+ // This is the part that fails in TypeScript for the user
30
+ // We are testing runtime behavior here, but the types should also be checked
31
+ expect(db.query.shoppingLists).toBeDefined();
32
+ });
33
+ });