From 52eed079145ee1ff8f04c8ed775a96da293a6477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Galeran?= Date: Thu, 24 Feb 2022 12:34:25 +0100 Subject: [PATCH] fix(migrate): getDbInfo `TypeError: Cannot read property 'url' of undefined` (#11958) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Joël Galeran Co-authored-by: Jan Piotrowski --- packages/migrate/src/__tests__/DbPull.test.ts | 101 +++++++++++------- .../only-generator/schema.prisma | 4 + packages/migrate/src/commands/DbDrop.ts | 5 + .../migrate/src/utils/ensureDatabaseExists.ts | 18 +++- packages/migrate/src/utils/printDatasource.ts | 4 +- packages/sdk/src/engine-commands/getConfig.ts | 6 +- 6 files changed, 94 insertions(+), 44 deletions(-) create mode 100644 packages/migrate/src/__tests__/fixtures/schema-only-mongodb/only-generator/schema.prisma diff --git a/packages/migrate/src/__tests__/DbPull.test.ts b/packages/migrate/src/__tests__/DbPull.test.ts index 53893de6b11c..c79241be763d 100644 --- a/packages/migrate/src/__tests__/DbPull.test.ts +++ b/packages/migrate/src/__tests__/DbPull.test.ts @@ -194,14 +194,14 @@ describe('common/sqlite', () => { expect(ctx.mocked['console.info'].mock.calls.join('\n')).toMatchInlineSnapshot(``) expect(ctx.mocked['console.error'].mock.calls.join('\n')).toMatchInlineSnapshot(` - // *** WARNING *** - // - // These models were enriched with \`@@map\` information taken from the previous Prisma schema. - // - Model "AwesomeNewPost" - // - Model "AwesomeProfile" - // - Model "AwesomeUser" - // - `) + // *** WARNING *** + // + // These models were enriched with \`@@map\` information taken from the previous Prisma schema. + // - Model "AwesomeNewPost" + // - Model "AwesomeProfile" + // - Model "AwesomeUser" + // + `) expect(ctx.fs.read('prisma/reintrospection.prisma')).toStrictEqual(originalSchema) }) @@ -624,14 +624,14 @@ describeIf(process.platform !== 'win32' && !isMacOrWindowsCI)('MongoDB', () => { expect(ctx.mocked['console.info'].mock.calls.join('\n')).toMatchInlineSnapshot(``) expect(ctx.mocked['console.error'].mock.calls.join('\n')).toMatchInlineSnapshot(` - // *** WARNING *** - // - // The following fields had data stored in multiple types. The most common type was chosen. If loading data with a type that does not match the one in the data model, the client will crash. Please see the issue: https://github.com/prisma/prisma/issues/9654 - // - Model "users", field: "numberOrString1", chosen data type: "Int32" - // - Type "UsersHobbies", field: "numberOrString2", chosen data type: "Int32" - // - Type "UsersHobbiesObjects", field: "numberOrString3", chosen data type: "Int32" - // - `) + // *** WARNING *** + // + // The following fields had data stored in multiple types. The most common type was chosen. If loading data with a type that does not match the one in the data model, the client will crash. Please see the issue: https://github.com/prisma/prisma/issues/9654 + // - Model "users", field: "numberOrString1", chosen data type: "Int32" + // - Type "UsersHobbies", field: "numberOrString2", chosen data type: "Int32" + // - Type "UsersHobbiesObjects", field: "numberOrString3", chosen data type: "Int32" + // + `) }) test('introspection --print --composite-type-depth=0 (no existing models)', async () => { @@ -666,12 +666,12 @@ describeIf(process.platform !== 'win32' && !isMacOrWindowsCI)('MongoDB', () => { expect(ctx.mocked['console.info'].mock.calls.join('\n')).toMatchInlineSnapshot(``) expect(ctx.mocked['console.error'].mock.calls.join('\n')).toMatchInlineSnapshot(` - // *** WARNING *** - // - // The following fields had data stored in multiple types. The most common type was chosen. If loading data with a type that does not match the one in the data model, the client will crash. Please see the issue: https://github.com/prisma/prisma/issues/9654 - // - Model "users", field: "numberOrString1", chosen data type: "Int32" - // - `) + // *** WARNING *** + // + // The following fields had data stored in multiple types. The most common type was chosen. If loading data with a type that does not match the one in the data model, the client will crash. Please see the issue: https://github.com/prisma/prisma/issues/9654 + // - Model "users", field: "numberOrString1", chosen data type: "Int32" + // + `) }) test('introspection --print --composite-type-depth=1 (no existing models)', async () => { @@ -714,13 +714,13 @@ describeIf(process.platform !== 'win32' && !isMacOrWindowsCI)('MongoDB', () => { expect(ctx.mocked['console.info'].mock.calls.join('\n')).toMatchInlineSnapshot(``) expect(ctx.mocked['console.error'].mock.calls.join('\n')).toMatchInlineSnapshot(` - // *** WARNING *** - // - // The following fields had data stored in multiple types. The most common type was chosen. If loading data with a type that does not match the one in the data model, the client will crash. Please see the issue: https://github.com/prisma/prisma/issues/9654 - // - Model "users", field: "numberOrString1", chosen data type: "Int32" - // - Type "UsersHobbies", field: "numberOrString2", chosen data type: "Int32" - // - `) + // *** WARNING *** + // + // The following fields had data stored in multiple types. The most common type was chosen. If loading data with a type that does not match the one in the data model, the client will crash. Please see the issue: https://github.com/prisma/prisma/issues/9654 + // - Model "users", field: "numberOrString1", chosen data type: "Int32" + // - Type "UsersHobbies", field: "numberOrString2", chosen data type: "Int32" + // + `) }) test('introspection --force --composite-type-depth=-1 (existing models)', async () => { @@ -796,14 +796,14 @@ describeIf(process.platform !== 'win32' && !isMacOrWindowsCI)('MongoDB', () => { expect(ctx.mocked['console.info'].mock.calls.join('\n')).toMatchInlineSnapshot(``) expect(ctx.mocked['console.error'].mock.calls.join('\n')).toMatchInlineSnapshot(` - // *** WARNING *** - // - // The following fields had data stored in multiple types. The most common type was chosen. If loading data with a type that does not match the one in the data model, the client will crash. Please see the issue: https://github.com/prisma/prisma/issues/9654 - // - Model "users", field: "numberOrString1", chosen data type: "Int32" - // - Type "UsersHobbies", field: "numberOrString2", chosen data type: "Int32" - // - Type "UsersHobbiesObjects", field: "numberOrString3", chosen data type: "Int32" - // - `) + // *** WARNING *** + // + // The following fields had data stored in multiple types. The most common type was chosen. If loading data with a type that does not match the one in the data model, the client will crash. Please see the issue: https://github.com/prisma/prisma/issues/9654 + // - Model "users", field: "numberOrString1", chosen data type: "Int32" + // - Type "UsersHobbies", field: "numberOrString2", chosen data type: "Int32" + // - Type "UsersHobbiesObjects", field: "numberOrString3", chosen data type: "Int32" + // + `) }) // describeIf is making eslint not happy about the names @@ -820,6 +820,33 @@ describeIf(process.platform !== 'win32' && !isMacOrWindowsCI)('MongoDB', () => { expect(ctx.mocked['console.error'].mock.calls.join('\n')).toMatchInlineSnapshot(``) }) + // In this case it should not error and the line `Datasource "x"` not be printed + test('introspection --url - only generator defined', async () => { + ctx.fixture('schema-only-mongodb/only-generator') + const introspect = new DbPull() + const result = introspect.parse(['--url', MONGO_URI]) + await expect(result).resolves.toMatchInlineSnapshot(``) + expect(ctx.mocked['console.log'].mock.calls.join('\n')).toMatchInlineSnapshot(``) + expect(ctx.mocked['console.info'].mock.calls.join('\n')).not.toContain(`Datasource `) + expect(ctx.mocked['console.info'].mock.calls.join('\n')).toMatchInlineSnapshot(` + Prisma schema loaded from schema.prisma + + Introspecting … + + ✔ Introspected 1 model and 2 embedded documents and wrote them into schema.prisma in XXXms + + *** WARNING *** + + The following fields had data stored in multiple types. The most common type was chosen. If loading data with a type that does not match the one in the data model, the client will crash. Please see the issue: https://github.com/prisma/prisma/issues/9654 + - Model "users", field: "numberOrString1", chosen data type: "Int32" + - Type "UsersHobbies", field: "numberOrString2", chosen data type: "Int32" + - Type "UsersHobbiesObjects", field: "numberOrString3", chosen data type: "Int32" + + Run prisma generate to generate Prisma Client. + `) + expect(ctx.mocked['console.error'].mock.calls.join('\n')).toMatchInlineSnapshot(``) + }) + test('introspection with --force', async () => { ctx.fixture('schema-only-mongodb') const introspect = new DbPull() diff --git a/packages/migrate/src/__tests__/fixtures/schema-only-mongodb/only-generator/schema.prisma b/packages/migrate/src/__tests__/fixtures/schema-only-mongodb/only-generator/schema.prisma new file mode 100644 index 000000000000..733bfdc03a36 --- /dev/null +++ b/packages/migrate/src/__tests__/fixtures/schema-only-mongodb/only-generator/schema.prisma @@ -0,0 +1,4 @@ +generator client { + provider = "prisma-client-js" + previewFeatures = ["mongoDb"] +} diff --git a/packages/migrate/src/commands/DbDrop.ts b/packages/migrate/src/commands/DbDrop.ts index 3be8308963d0..72b2b9efac6b 100644 --- a/packages/migrate/src/commands/DbDrop.ts +++ b/packages/migrate/src/commands/DbDrop.ts @@ -75,6 +75,11 @@ ${chalk.bold('Examples')} await printDatasource(schemaPath) const dbInfo = await getDbInfo(schemaPath) + if (!dbInfo.url) { + // TODO better error + throw new Error('Connection url is undefined.') + } + const schemaDir = (await getSchemaDir(schemaPath))! console.info() // empty line diff --git a/packages/migrate/src/utils/ensureDatabaseExists.ts b/packages/migrate/src/utils/ensureDatabaseExists.ts index bb2970761e2c..71848b2ab6a0 100644 --- a/packages/migrate/src/utils/ensureDatabaseExists.ts +++ b/packages/migrate/src/utils/ensureDatabaseExists.ts @@ -10,9 +10,9 @@ export type DbType = 'MySQL' | 'PostgreSQL' | 'SQLite' | 'SQL Server' | 'Cockroa // TODO: extract functions in their own files? export async function getDbInfo(schemaPath?: string): Promise<{ - name: string // from datasource name - url: string // from getConfig schemaWord: 'database' // legacy? could be removed? + name?: string // from datasource name + url?: string // from getConfig dbLocation?: string // host without credentials dbType?: DbType // pretty name dbName?: string // database name @@ -20,7 +20,19 @@ export async function getDbInfo(schemaPath?: string): Promise<{ }> { const datamodel = await getSchema(schemaPath) const config = await getConfig({ datamodel }) - const activeDatasource = config.datasources[0] + const activeDatasource = config.datasources?.[0] + + if (!activeDatasource) { + return { + name: undefined, + schemaWord: 'database', + dbType: undefined, + dbName: undefined, + dbLocation: undefined, + url: undefined, + } + } + const url = activeDatasource.url.value if (activeDatasource.provider === 'sqlserver') { diff --git a/packages/migrate/src/utils/printDatasource.ts b/packages/migrate/src/utils/printDatasource.ts index b208d8a4172b..fa29634d106e 100644 --- a/packages/migrate/src/utils/printDatasource.ts +++ b/packages/migrate/src/utils/printDatasource.ts @@ -25,7 +25,9 @@ export async function printDatasource(schemaPath: string): Promise { ), ) } - } else { + } else if (dbInfo.name) { console.info(chalk.dim(`Datasource "${dbInfo.name}"`)) + } else { + // Nothing } } diff --git a/packages/sdk/src/engine-commands/getConfig.ts b/packages/sdk/src/engine-commands/getConfig.ts index 87fac7a72cec..7d04a3833f1c 100644 --- a/packages/sdk/src/engine-commands/getConfig.ts +++ b/packages/sdk/src/engine-commands/getConfig.ts @@ -20,9 +20,9 @@ const unlink = promisify(fs.unlink) const MAX_BUFFER = 1_000_000_000 export interface ConfigMetaFormat { - datasources: DataSource[] - generators: GeneratorConfig[] - warnings: string[] + datasources: DataSource[] | [] + generators: GeneratorConfig[] | [] + warnings: string[] | [] } export type GetConfigOptions = {