@@ -226,7 +226,7 @@ describe('generateDatabase — docker-compose.yml', () => {
226226 expect ( content ) . toContain ( 'postgres:16' ) ;
227227 expect ( content ) . toContain ( 'db_data:/var/lib/postgresql/data' ) ;
228228 expect ( content ) . toContain ( 'pg_isready' ) ;
229- expect ( content ) . toContain ( "'-d', 'test-app'" ) ;
229+ expect ( content ) . toContain ( `POSTGRES_DB: ${ pgOptions . projectName } ` ) ;
230230 expect ( content ) . toContain ( 'healthcheck' ) ;
231231 expect ( content ) . toContain ( 'backend' ) ;
232232 expect ( content ) . toContain ( 'tsx watch src/index.ts' ) ;
@@ -324,10 +324,10 @@ describe('generateDatabase — tokenRepository.ts', () => {
324324 expect ( compose ) . toContain ( 'app:' ) ;
325325 expect ( compose ) . toContain ( 'dockerfile: Dockerfile.app' ) ;
326326 expect ( compose ) . toContain ( 'user: root' ) ;
327- expect ( compose ) . toContain (
328- 'command: sh -c "chown -R node:node /app/node_modules && su-exec node sh -c \'echo Installing dependencies... && npm install --no-package-lock --no-audit --no-fund --loglevel=error && ./node_modules/.bin/tsx watch src/index.ts\'"' ,
329- ) ;
330- expect ( compose ) . toContain ( " '3000:3000'" ) ;
327+ expect ( compose ) . toContain ( 'tsx watch src/index.ts' ) ;
328+ expect ( compose ) . toContain ( ' su-exec node' ) ;
329+ expect ( compose ) . toContain ( 'chown -R node:node /app/node_modules' ) ;
330+ expect ( compose ) . toContain ( '3000:3000' ) ;
331331 expect ( compose ) . toContain ( './package.json:/app/package.json:ro' ) ;
332332 expect ( compose ) . toContain ( 'app_node_modules:/app/node_modules' ) ;
333333 expect ( compose ) . toContain ( 'DATABASE_URL: file:./data.db' ) ;
@@ -337,10 +337,10 @@ describe('generateDatabase — tokenRepository.ts', () => {
337337 expect ( compose ) . toContain ( 'path: ./tsconfig.json' ) ;
338338 expect ( compose ) . toContain ( 'app-extension-ui:' ) ;
339339 expect ( compose ) . toContain ( 'dockerfile: Dockerfile.app-extension-ui' ) ;
340- expect ( compose ) . toContain (
341- 'command: sh -c "chown -R node:node /app/node_modules && su-exec node sh -c \'echo Installing dependencies... && npm install --no-package-lock --no-audit --no-fund --loglevel=error && npm run dev:frontend\'"' ,
342- ) ;
343- expect ( compose ) . toContain ( " '5173:5173'" ) ;
340+ expect ( compose ) . toContain ( 'npm run dev:frontend' ) ;
341+ expect ( compose ) . toContain ( ' su-exec node' ) ;
342+ expect ( compose ) . toContain ( 'chown -R node:node /app/node_modules' ) ;
343+ expect ( compose ) . toContain ( '5173:5173' ) ;
344344 expect ( compose ) . toContain ( './package.json:/app/package.json:ro' ) ;
345345 expect ( compose ) . toContain ( 'app_extension_ui_node_modules:/app/node_modules' ) ;
346346 expect ( compose ) . toContain ( 'develop:' ) ;
@@ -386,6 +386,8 @@ describe('generateDatabase — tokenRepository.ts', () => {
386386 expect ( compose ) . toContain ( 'DATABASE_URL: postgresql://app:app@db:5432/test-app' ) ;
387387 expect ( compose ) . toContain ( 'depends_on:' ) ;
388388 expect ( compose ) . toContain ( 'condition: service_healthy' ) ;
389+ expect ( compose ) . toContain ( 'postgres_data:/var/lib/postgresql/data' ) ;
390+ expect ( compose ) . not . toContain ( 'db_data:' ) ;
389391 } ) ;
390392
391393 it ( 'postgres schema uses text for access_token and refresh_token' , async ( ) => {
@@ -447,6 +449,60 @@ describe('generateDatabase — tokenRepository.ts', () => {
447449 } ) ;
448450} ) ;
449451
452+ describe ( 'generateDatabase — ComposeBuilder behavior' , ( ) => {
453+ it ( 'sqlite compose has no db service and no database image' , async ( ) => {
454+ const { generateDatabase } = await import ( './database.js' ) ;
455+ await generateDatabase ( tmpDir , sqliteOptions ) ;
456+ const content = await read ( 'docker-compose.yml' ) ;
457+ expect ( content ) . not . toContain ( 'image:' ) ;
458+ expect ( content ) . not . toContain ( 'db:' ) ;
459+ } ) ;
460+
461+ it ( 'postgres compose has db service with correct image, env, and healthcheck' , async ( ) => {
462+ const { generateDatabase } = await import ( './database.js' ) ;
463+ await generateDatabase ( tmpDir , pgOptions ) ;
464+ const content = await read ( 'docker-compose.yml' ) ;
465+ expect ( content ) . toContain ( 'postgres:16' ) ;
466+ expect ( content ) . toContain ( 'POSTGRES_USER: app' ) ;
467+ expect ( content ) . toContain ( 'POSTGRES_PASSWORD: app' ) ;
468+ expect ( content ) . toContain ( `POSTGRES_DB: ${ pgOptions . projectName } ` ) ;
469+ expect ( content ) . toContain ( '5432:5432' ) ;
470+ expect ( content ) . toContain ( 'pg_isready' ) ;
471+ expect ( content ) . toContain ( 'interval: 5s' ) ;
472+ expect ( content ) . toContain ( 'retries: 5' ) ;
473+ } ) ;
474+
475+ it ( 'mysql compose has db service with correct image, env, and healthcheck' , async ( ) => {
476+ const { generateDatabase } = await import ( './database.js' ) ;
477+ await generateDatabase ( tmpDir , mysqlOptions ) ;
478+ const content = await read ( 'docker-compose.yml' ) ;
479+ expect ( content ) . toContain ( 'mysql:8' ) ;
480+ expect ( content ) . toContain ( 'MYSQL_ROOT_PASSWORD: app' ) ;
481+ expect ( content ) . toContain ( 'MYSQL_USER: app' ) ;
482+ expect ( content ) . toContain ( `MYSQL_DATABASE: ${ mysqlOptions . projectName } ` ) ;
483+ expect ( content ) . toContain ( '127.0.0.1:3307:3306' ) ;
484+ expect ( content ) . toContain ( 'mysqladmin' ) ;
485+ expect ( content ) . toContain ( 'interval: 5s' ) ;
486+ expect ( content ) . toContain ( 'retries: 5' ) ;
487+ } ) ;
488+
489+ it ( 'when false: postgres compose without app extensions has no app-extension-ui service' , async ( ) => {
490+ const { generateDatabase } = await import ( './database.js' ) ;
491+ await generateDatabase ( tmpDir , pgOptions ) ;
492+ const content = await read ( 'docker-compose.yml' ) ;
493+ expect ( content ) . not . toContain ( 'app-extension-ui' ) ;
494+ expect ( content ) . not . toContain ( 'Dockerfile.app-extension-ui' ) ;
495+ } ) ;
496+
497+ it ( 'mysql with app extensions uses mysql_data volume name' , async ( ) => {
498+ const { generateDatabase } = await import ( './database.js' ) ;
499+ await generateDatabase ( tmpDir , { ...mysqlOptions , appExtensions : [ 'custom-panel' ] } ) ;
500+ const compose = await read ( 'docker-compose.yml' ) ;
501+ expect ( compose ) . toContain ( 'mysql_data:/var/lib/mysql' ) ;
502+ expect ( compose ) . not . toContain ( 'db_data:' ) ;
503+ } ) ;
504+ } ) ;
505+
450506describe ( 'generateDatabase — Dockerfile' , ( ) => {
451507 it ( 'generates Dockerfile with USER node when no app extensions' , async ( ) => {
452508 const { generateDatabase } = await import ( './database.js' ) ;
0 commit comments