@@ -2,7 +2,10 @@ import { describe, it, expect, beforeEach, afterEach } from "vitest";
22import { Project } from "ts-morph" ;
33import * as path from "node:path" ;
44import * as fs from "node:fs/promises" ;
5- import { getZeroSchemaDefsFromConfig } from "../src/cli/config" ;
5+ import {
6+ getZeroSchemaDefsFromConfig ,
7+ discoverAllTsConfigs ,
8+ } from "../src/cli/config" ;
69import * as oneToOneSchema from "./schemas/one-to-one.zero" ;
710import { getGeneratedSchema } from "../src/cli/shared" ;
811import type { DrizzleToZeroSchema } from "../src/relations" ;
@@ -443,15 +446,15 @@ describe("getGeneratedSchema", () => {
443446 } ) ;
444447
445448 // Verify the import statement includes .js extension
446- expect ( generatedSchema ) . toContain ( 'from "./tests/schemas/one-to-one.zero.js";' ) ;
447-
449+ expect ( generatedSchema ) . toContain (
450+ 'from "./tests/schemas/one-to-one.zero.js";' ,
451+ ) ;
452+
448453 // Verify the rest of the schema is still generated correctly
449454 expect ( generatedSchema ) . toContain ( "export const schema = {" ) ;
450455 expect ( generatedSchema ) . toContain ( '"users": {' ) ;
451456 } ) ;
452457
453-
454-
455458 it ( "should add .js file extensions to drizzle-kit imports when jsFileExtension is true" , async ( ) => {
456459 // Mock the DrizzleToZeroSchema type
457460 vi . mock ( "drizzle-zero" , ( ) => ( {
@@ -498,7 +501,7 @@ describe("getGeneratedSchema", () => {
498501
499502 // Verify the import statement includes .js extension for drizzle schema
500503 expect ( generatedSchema ) . toContain ( 'from "./mock-drizzle-schema.js";' ) ;
501-
504+
502505 // Verify the rest of the schema is still generated correctly
503506 expect ( generatedSchema ) . toContain ( "export const schema = {" ) ;
504507 expect ( generatedSchema ) . toContain ( '"users": {' ) ;
@@ -629,12 +632,12 @@ describe("drizzle-kit functions", () => {
629632 // Create a temporary schema file that exports a valid drizzle schema
630633 const tempSchemaContent = `
631634 import { pgTable, serial, text } from 'drizzle-orm/pg-core';
632-
635+
633636 export const users = pgTable('users', {
634637 id: serial('id').primaryKey(),
635638 name: text('name').notNull()
636639 });
637-
640+
638641 export default { users };
639642 ` ;
640643
@@ -708,3 +711,134 @@ describe("drizzle-kit functions", () => {
708711 } ) ;
709712 } ) ;
710713} ) ;
714+
715+ describe ( "discoverAllTsConfigs" , ( ) => {
716+ const tempDir = path . resolve ( __dirname , "temp_tsconfigs" ) ;
717+
718+ beforeEach ( async ( ) => {
719+ await fs . mkdir ( tempDir , { recursive : true } ) ;
720+ } ) ;
721+
722+ afterEach ( async ( ) => {
723+ await fs . rm ( tempDir , { recursive : true , force : true } ) ;
724+ } ) ;
725+
726+ it ( "should find a single tsconfig with no references" , async ( ) => {
727+ const rootPath = path . join ( tempDir , "tsconfig.json" ) ;
728+ await fs . writeFile ( rootPath , JSON . stringify ( { compilerOptions : { } } ) ) ;
729+
730+ const result = await discoverAllTsConfigs ( rootPath ) ;
731+ expect ( result ) . toEqual ( new Set ( [ rootPath ] ) ) ;
732+ } ) ;
733+
734+ it ( "should find one level of project references" , async ( ) => {
735+ const rootPath = path . join ( tempDir , "tsconfig.json" ) ;
736+ const libADir = path . join ( tempDir , "libs" , "lib-a" ) ;
737+ const libBDir = path . join ( tempDir , "libs" , "lib-b" ) ;
738+ const libAPath = path . join ( libADir , "tsconfig.json" ) ;
739+ const libBPath = path . join ( libBDir , "tsconfig.json" ) ;
740+
741+ await fs . mkdir ( libADir , { recursive : true } ) ;
742+ await fs . mkdir ( libBDir , { recursive : true } ) ;
743+
744+ await fs . writeFile (
745+ rootPath ,
746+ JSON . stringify ( {
747+ references : [ { path : "./libs/lib-a" } , { path : "./libs/lib-b" } ] ,
748+ } ) ,
749+ ) ;
750+ await fs . writeFile ( libAPath , JSON . stringify ( { compilerOptions : { } } ) ) ;
751+ await fs . writeFile ( libBPath , JSON . stringify ( { compilerOptions : { } } ) ) ;
752+
753+ const result = await discoverAllTsConfigs ( rootPath ) ;
754+ expect ( result ) . toEqual ( new Set ( [ rootPath , libAPath , libBPath ] ) ) ;
755+ } ) ;
756+
757+ it ( "should handle multi-level nested project references" , async ( ) => {
758+ const rootPath = path . join ( tempDir , "tsconfig.json" ) ;
759+ const appDir = path . join ( tempDir , "apps" , "my-app" ) ;
760+ const sharedUiDir = path . join ( tempDir , "libs" , "shared-ui" ) ;
761+ const utilsDir = path . join ( tempDir , "libs" , "utils" ) ;
762+
763+ const appPath = path . join ( appDir , "tsconfig.json" ) ;
764+ const sharedUiPath = path . join ( sharedUiDir , "tsconfig.json" ) ;
765+ const utilsPath = path . join ( utilsDir , "tsconfig.json" ) ;
766+
767+ await fs . mkdir ( appDir , { recursive : true } ) ;
768+ await fs . mkdir ( sharedUiDir , { recursive : true } ) ;
769+ await fs . mkdir ( utilsDir , { recursive : true } ) ;
770+
771+ await fs . writeFile (
772+ rootPath ,
773+ JSON . stringify ( { references : [ { path : "./apps/my-app" } ] } ) ,
774+ ) ;
775+ await fs . writeFile (
776+ appPath ,
777+ JSON . stringify ( { references : [ { path : "../../libs/shared-ui" } ] } ) ,
778+ ) ;
779+ await fs . writeFile (
780+ sharedUiPath ,
781+ JSON . stringify ( { references : [ { path : "../utils" } ] } ) ,
782+ ) ;
783+ await fs . writeFile ( utilsPath , JSON . stringify ( { compilerOptions : { } } ) ) ;
784+
785+ const result = await discoverAllTsConfigs ( rootPath ) ;
786+ expect ( result ) . toEqual (
787+ new Set ( [ rootPath , appPath , sharedUiPath , utilsPath ] ) ,
788+ ) ;
789+ } ) ;
790+
791+ it ( "should correctly handle circular references" , async ( ) => {
792+ const rootPath = path . join ( tempDir , "tsconfig.json" ) ;
793+ const libADir = path . join ( tempDir , "libs" , "lib-a" ) ;
794+ const libBDir = path . join ( tempDir , "libs" , "lib-b" ) ;
795+ const libAPath = path . join ( libADir , "tsconfig.json" ) ;
796+ const libBPath = path . join ( libBDir , "tsconfig.json" ) ;
797+
798+ await fs . mkdir ( libADir , { recursive : true } ) ;
799+ await fs . mkdir ( libBDir , { recursive : true } ) ;
800+
801+ await fs . writeFile (
802+ rootPath ,
803+ JSON . stringify ( { references : [ { path : "./libs/lib-a" } ] } ) ,
804+ ) ;
805+ await fs . writeFile (
806+ libAPath ,
807+ JSON . stringify ( { references : [ { path : "../lib-b" } ] } ) ,
808+ ) ;
809+ await fs . writeFile (
810+ libBPath ,
811+ JSON . stringify ( { references : [ { path : "../lib-a" } ] } ) ,
812+ ) ;
813+
814+ const result = await discoverAllTsConfigs ( rootPath ) ;
815+ expect ( result ) . toEqual ( new Set ( [ rootPath , libAPath , libBPath ] ) ) ;
816+ } ) ;
817+
818+ it ( "should continue gracefully if a referenced tsconfig is not found" , async ( ) => {
819+ const rootPath = path . join ( tempDir , "tsconfig.json" ) ;
820+ const libGoodDir = path . join ( tempDir , "libs" , "good" ) ;
821+ const libGoodPath = path . join ( libGoodDir , "tsconfig.json" ) ;
822+
823+ const warnSpy = vi . spyOn ( console , "warn" ) . mockImplementation ( ( ) => { } ) ;
824+
825+ await fs . mkdir ( libGoodDir , { recursive : true } ) ;
826+
827+ await fs . writeFile (
828+ rootPath ,
829+ JSON . stringify ( {
830+ references : [ { path : "./libs/good" } , { path : "./libs/bad" } ] ,
831+ } ) ,
832+ ) ;
833+ await fs . writeFile ( libGoodPath , JSON . stringify ( { compilerOptions : { } } ) ) ;
834+
835+ const result = await discoverAllTsConfigs ( rootPath ) ;
836+ expect ( result ) . toEqual ( new Set ( [ rootPath , libGoodPath ] ) ) ;
837+
838+ expect ( warnSpy ) . toHaveBeenCalledWith (
839+ expect . stringContaining ( "Could not resolve reference path: ./libs/bad" ) ,
840+ ) ;
841+
842+ warnSpy . mockRestore ( ) ;
843+ } ) ;
844+ } ) ;
0 commit comments