diff --git a/package.json b/package.json index d8fed9fd5..920744dbd 100644 --- a/package.json +++ b/package.json @@ -112,7 +112,7 @@ "@electric-sql/pglite": "*", "@libsql/client": "*", "@valibot/to-json-schema": "^1.5.0", - "better-sqlite3": "^12.5.0", + "better-sqlite3": "^12.5.0 || ^13.0.0", "sqlite3": "*", "valibot": "^1.2.0" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 74bc2b2e9..4ac91585d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -38,7 +38,7 @@ importers: specifier: ^1.1.1 version: 1.1.1 better-sqlite3: - specifier: ^12.5.0 + specifier: ^12.5.0 || ^13.0.0 version: 12.10.0 c12: specifier: ^3.3.4 diff --git a/src/utils/dependencies.ts b/src/utils/dependencies.ts index 2892d3ab4..a53340c22 100644 --- a/src/utils/dependencies.ts +++ b/src/utils/dependencies.ts @@ -1,5 +1,6 @@ import { addDependency } from 'nypm' import { resolvePackageJSON } from 'pkg-types' +import { hasTTY, isCI } from 'std-env' import { logger } from './dev' import nuxtContentContext from './context' import { tryUseNuxt } from '@nuxt/kit' @@ -22,11 +23,13 @@ export async function ensurePackageInstalled(pkg: string) { if (!await isPackageInstalled(pkg)) { logger.error(`Nuxt Content requires \`${pkg}\` module to operate.`) - const confirm = await logger.prompt(`Do you want to install \`${pkg}\` package?`, { - type: 'confirm', - name: 'confirm', - initial: true, - }) + const confirm = hasTTY && !isCI + ? await logger.prompt(`Do you want to install \`${pkg}\` package?`, { + type: 'confirm', + name: 'confirm', + initial: true, + }) + : false if (!confirm) { logger.error(`Nuxt Content requires \`${pkg}\` module to operate. Please install \`${pkg}\` package manually and try again. \`npm install ${pkg}\``) diff --git a/test/unit/ensurePackageInstalled.test.ts b/test/unit/ensurePackageInstalled.test.ts new file mode 100644 index 000000000..af9314cf1 --- /dev/null +++ b/test/unit/ensurePackageInstalled.test.ts @@ -0,0 +1,60 @@ +import { afterEach, describe, expect, test, vi } from 'vitest' + +const logger = { error: vi.fn(), prompt: vi.fn() } +const addDependency = vi.fn() + +vi.mock('../../src/utils/dev', () => ({ logger })) +vi.mock('nypm', () => ({ addDependency })) + +describe('ensurePackageInstalled', () => { + afterEach(() => { + vi.restoreAllMocks() + vi.resetModules() + }) + + test('reports how to install the package instead of prompting when there is no TTY', async () => { + vi.doMock('std-env', async importOriginal => ({ + ...(await importOriginal()), + hasTTY: false, + isCI: false, + })) + const exit = vi.spyOn(process, 'exit').mockImplementation(() => undefined as never) + const { ensurePackageInstalled } = await import('../../src/utils/dependencies') + + await ensurePackageInstalled('@nuxt/content-not-installed') + + expect(logger.prompt).not.toHaveBeenCalled() + expect(logger.error).toHaveBeenLastCalledWith(expect.stringContaining('npm install @nuxt/content-not-installed')) + expect(exit).toHaveBeenCalledWith(1) + }) + + test('reports how to install the package instead of prompting in CI', async () => { + vi.doMock('std-env', async importOriginal => ({ + ...(await importOriginal()), + hasTTY: true, + isCI: true, + })) + const exit = vi.spyOn(process, 'exit').mockImplementation(() => undefined as never) + const { ensurePackageInstalled } = await import('../../src/utils/dependencies') + + await ensurePackageInstalled('@nuxt/content-not-installed') + + expect(logger.prompt).not.toHaveBeenCalled() + expect(logger.error).toHaveBeenLastCalledWith(expect.stringContaining('npm install @nuxt/content-not-installed')) + expect(exit).toHaveBeenCalledWith(1) + }) + + test('prompts to install the package when interactive and not in CI', async () => { + vi.doMock('std-env', async importOriginal => ({ + ...(await importOriginal()), + hasTTY: true, + isCI: false, + })) + vi.spyOn(process, 'exit').mockImplementation(() => undefined as never) + const { ensurePackageInstalled } = await import('../../src/utils/dependencies') + + await ensurePackageInstalled('@nuxt/content-not-installed') + + expect(logger.prompt).toHaveBeenCalled() + }) +})