drizzle-team / drizzle-orm

Headless TypeScript ORM with a head. Runs on Node, Bun and Deno. Lives on the Edge and yes, it's a JavaScript ORM too 😅
https://orm.drizzle.team
Apache License 2.0
24.54k stars 643 forks source link

[BUG]: Vercel Edge + Turso/libsql doesn't build #1745

Closed lightyaer closed 10 months ago

lightyaer commented 10 months ago

What version of drizzle-orm are you using?

0.29.3

What version of drizzle-kit are you using?

^0.20.9

Describe the Bug

Next.js doesn't build when I have a route handler with edge runtime and query a libsql db.

repo to reproduce: https://github.com/lightyaer/test-drizzle-edge

modify .env file to a running instance of turso dev or libsql instance

(bare bones next.js using drizzle-orm) check src/app/api/edge/route.ts;

everything is setup, it works fine when running pnpm dev or even using pnpm dev --turbo, but doesn't get built pnpm build , locally or on vercel.

Error while building


> test-drizzle-edge@0.1.0 build /Users/lightyaer/Code/test-drizzle-edge
> next build

   ▲ Next.js 14.0.4
   - Environments: .env

 ✓ Creating an optimized production build
 ✓ Compiled successfully
 ✓ Linting and checking validity of types
   Collecting page data  ./Users/lightyaer/Code/test-drizzle-edge/.next/server/app/api/edge/route.js:25
        `;await t.run(r);let s=(await t.values(ta`SELECT id, hash, created_at FROM "__drizzle_migrations" ORDER BY created_at DESC LIMIT 1`))[0]??void 0;await t.transaction(async t=>{for(let r of e)if(!s||Number(s[2])<r.folderMillis){for(let e of r.sql)await t.run(ta.raw(e));await t.run(ta`INSERT INTO "__drizzle_migrations" ("hash", "created_at") VALUES(${r.hash}, ${r.folderMillis})`)}})}}class ro{static{this[eD]="TypedQueryBuilder"}getSelectedFields(){return this._.selectedFields}}class ra{static{c=Symbol.toStringTag}static{this[eD]="QueryPromise"}catch(e){return this.then(void 0,e)}finally(e){return this.then(t=>(e?.(),t),t=>{throw e?.(),t})}then(e,t){return this.execute().then(e,t)}constructor(){this[c]="QueryPromise"}}class rl{static{this[eD]="SQLiteSelectBuilder"}constructor(e){this.fields=e.fields,this.session=e.session,this.dialect=e.dialect,this.withList=e.withList,this.distinct=e.distinct}from(e){let t;let r=!!this.fields;return t=this.fields?this.fields:eU(e,e6)?Object.fromEntries(Object.keys(e[e4].selection).map(t=>[t,e[t]])):eU(e,rr)?e[e5].selectedFields:eU(e,tr)?{}:e[eY.Symbol.Columns],new rc({table:e,fields:t,isPartialSelect:r,session:this.session,dialect:this.dialect,withList:this.withList,distinct:this.distinct})}}class ru extends ro{static{this[eD]="SQLiteSelectQueryBuilder"}constructor({table:e,fields:t,isPartialSelect:r,session:s,dialect:n,withList:i,distinct:o}){super(),this.leftJoin=this.createJoin("left"),this.rightJoin=this.createJoin("right"),this.innerJoin=this.createJoin("inner"),this.fullJoin=this.createJoin("full"),this.union=this.createSetOperator("union",!1),this.unionAll=this.createSetOperator("union",!0),this.intersect=this.createSetOperator("intersect",!1),this.except=this.createSetOperator("except",!1),this.config={withList:i,table:e,fields:{...t},distinct:o,setOperators:[]},this.isPartialSelect=r,this.session=s,this.dialect=n,this._={selectedFields:t},this.tableName=rt(e),this.joinsNotNullableMap="string"==typeof this.tableName?{[this.tableName]:!0}:{}}createJoin(e){return(t,r)=>{let s=this.tableName,n=rt(t);if("string"==typeof n&&this.config.joins?.some(e=>e.alias===n))throw Error(`Alias "${n}" is already used in this query`);if(!this.isPartialSelect&&(1===Object.keys(this.joinsNotNullableMap).length&&"string"==typeof s&&(this.config.fields={[s]:this.config.fields}),"string"==typeof n&&!eU(t,tr))){let e=eU(t,e6)?t[e4].selection:eU(t,tc)?t[e5].selectedFields:t[eY.Symbol.Columns];this.config.fields[n]=e}if("function"==typeof r&&(r=r(new Proxy(this.config.fields,new tG({sqlAliasedBehavior:"sql",sqlBehavior:"sql"})))),this.config.joins||(this.config.joins=[]),this.config.joins.push({on:r,table:t,joinType:e,alias:n}),"string"==typeof n)switch(e){case"left":this.joinsNotNullableMap[n]=!1;break;case"right":this.joinsNotNullableMap=Object.fromEntries(Object.entries(this.joinsNotNullableMap).map(([e])=>[e,!1])),this.joinsNotNullableMap[n]=!0;break;case"inner":this.joinsNotNullableMap[n]=!0;break;case"full":this.joinsNotNullableMap=Object.fromEntries(Object.entries(this.joinsNotNullableMap).map(([e])=>[e,!1])),this.joinsNotNullableMap[n]=!1}return this}}createSetOperator(e,t){return r=>{let s="function"==typeof r?r(rd()):r;if(!t7(this.getSelectedFields(),s.getSelectedFields()))throw Error("Set operator error (union / intersect / except): selected fields are not the same or are in a different order");return this.config.setOperators.push({type:e,isAll:t,rightSelect:s}),this}}addSetOperators(e){return this.config.setOperators.push(...e),this}where(e){return"function"==typeof e&&(e=e(new Proxy(this.config.fields,new tG({sqlAliasedBehavior:"sql",sqlBehavior:"sql"})))),this.config.where=e,this}having(e){return"function"==typeof e&&(e=e(new Proxy(this.config.fields,new tG({sqlAliasedBehavior:"sql",sqlBehavior:"sql"})))),this.config.having=e,this}groupBy(...e){if("function"==typeof e[0]){let t=e[0](new Proxy(this.config.fields,new tG({sqlAliasedBehavior:"alias",sqlBehavior:"sql"})));this.config.groupBy=Array.isArray(t)?t:[t]}else this.config.groupBy=e;return this}orderBy(...e){if("function"==typeof e[0]){let t=e[0](new Proxy(this.config.fields,new tG({sqlAliasedBehavior:"alias",sqlBehavior:"sql"}))),r=Array.isArray(t)?t:[t];this.config.setOperators.length>0?this.config.setOperators.at(-1).orderBy=r:this.config.orderBy=r}else this.config.setOperators.length>0?this.config.setOperators.at(-1).orderBy=e:this.config.orderBy=e;return this}limit(e){return this.config.setOperators.length>0?this.config.setOperators.at(-1).limit=e:this.config.limit=e,this}offset(e){return this.config.setOperators.length>0?this.config.setOperators.at(-1).offset=e:this.config.offset=e,this}getSQL(){return this.dialect.buildSelectQuery(this.config)}toSQL(){let{typings:e,...t}=this.dialect.sqlToQuery(this.getSQL());return t}as(e){return new Proxy(new e6(this.getSQL(),this.config.fields,e),new tG({alias:e,sqlAliasedBehavior:"alias",sqlBehavior:"error"}))}getSelectedFields(){return new Proxy(this.config.fields,new tG({alias:this.tableName,sqlAliasedBehavior:"alias",sqlBehavior:"error"}))}$dynamic(){return this}}class rc extends ru{static{this[eD]="SQLiteSelect"}prepare(e){if(!this.session)throw Error("Cannot execute a query on a query builder. Please use a database instance instead.");let t=t5(this.config.fields),r=this.session[e?"prepareOneTimeQuery":"prepareQuery"](this.dialect.sqlToQuery(this.getSQL()),t,"all");return r.joinsNotNullableMap=this.joinsNotNullableMap,r}async execute(){return this.all()}constructor(...e){super(...e),this.run=e=>this.prepare(!0).run(e),this.all=e=>this.prepare(!0).all(e),this.get=e=>this.prepare(!0).get(e),this.values=e=>this.prepare(!0).values(e)}}function rh(e,t){return(r,s,...n)=>{let i=[s,...n].map(r=>({type:e,isAll:t,rightSelect:r}));for(let e of i)if(!t7(r.getSelectedFields(),e.rightSelect.getSelectedFields()))throw Error("Set operator error (union / intersect / except): selected fields are not the same or are in a different order");return r.addSetOperators(i)}}!function(e,t){for(let r of t)for(let t of Object.getOwnPropertyNames(r.prototype))"constructor"!==t&&Object.defineProperty(e.prototype,t,Object.getOwnPropertyDescriptor(r.prototype,t)||Object.create(null))}(rc,[ra]);let rd=()=>({union:rf,unionAll:rp,intersect:rg,except:rm}),rf=rh("union",!1),rp=rh("union",!0),rg=rh("intersect",!1),rm=rh("except",!1);class ry{static{this[eD]="SQLiteQueryBuilder"}$with(e){let t=this;return{as:r=>("function"==typeof r&&(r=r(t)),new Proxy(new e8(r.getSQL(),r.getSelectedFields(),e,!0),new tG({alias:e,sqlAliasedBehavior:"alias",sqlBehavior:"error"})))}}with(...e){let t=this;return{select:function(r){return new rl({fields:r??void 0,session:void 0,dialect:t.getDialect(),withList:e})},selectDistinct:function(r){return new rl({fields:r??void 0,session:void 0,dialect:t.getDialect(),withList:e,distinct:!0})}}}select(e){return new rl({fields:e??void 0,session:void 0,dialect:this.getDialect()})}selectDistinct(e){return new rl({fields:e??void 0,session:void 0,dialect:this.getDialect(),distinct:!0})}getDialect(){return this.dialect||(this.dialect=new rn),this.dialect}}class rv{constructor(e,t,r){this.table=e,this.session=t,this.dialect=r}static{this[eD]="SQLiteUpdateBuilder"}set(e){return new rb(this.table,re(this.table,e),this.session,this.dialect)}}class rb extends ra{constructor(e,t,r,s){super(),this.run=e=>this.prepare(!0).run(e),this.all=e=>this.prepare(!0).all(e),this.get=e=>this.prepare(!0).get(e),this.values=e=>this.prepare(!0).values(e),this.session=r,this.dialect=s,this.config={set:t,table:e}}static{this[eD]="SQLiteUpdate"}where(e){return this.config.where=e,this}returning(e=this.config.table[tY.Symbol.Columns]){return this.config.returning=t5(e),this}getSQL(){return this.dialect.buildUpdateQuery(this.config)}toSQL(){let{typings:e,...t}=this.dialect.sqlToQuery(this.getSQL());return t}prepare(e){return this.session[e?"prepareOneTimeQuery":"prepareQuery"](this.dialect.sqlToQuery(this.getSQL()),this.config.returning
> Build error occurred
Error: Failed to collect page data for /api/edge
    at /Users/lightyaer/Code/test-drizzle-edge/node_modules/.pnpm/next@14.0.4_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/build/utils.js:1220:15
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
  type: 'Error'
}
   Collecting page data  . ELIFECYCLE  Command failed with exit code 1.

Expected behavior

It should build next js

Environment & setup

mac-os 14.2.1 node js 20.10.0

lightyaer commented 10 months ago

found a work around solution here https://github.com/vercel/next.js/issues/59540