Skip to content
This repository was archived by the owner on Sep 2, 2022. It is now read-only.

Commit 574c453

Browse files
committed
Merge branch 'alpha' into beta
2 parents 93b5af5 + e541203 commit 574c453

114 files changed

Lines changed: 7025 additions & 1643 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

cli/packages/prisma-cli-core/src/commands/delete/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ export default class Delete extends Command {
1515
description: 'Path to .env file to inject env vars',
1616
char: 'e',
1717
}),
18+
['project']: flags.string({
19+
description: 'Path to Prisma definition file',
20+
char: 'p',
21+
}),
1822
}
1923
async run() {
2024
const { force } = this.flags

cli/packages/prisma-cli-core/src/commands/deploy/deploy.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ ${chalk.gray(
5858
description: 'Path to .env file to inject env vars',
5959
char: 'e',
6060
}),
61+
['project']: flags.string({
62+
description: 'Path to Prisma definition file',
63+
char: 'p',
64+
}),
6165
}
6266
private deploying: boolean = false
6367
private showedHooks: boolean = false

cli/packages/prisma-cli-core/src/commands/export/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ export default class Export extends Command {
1616
description: 'Path to .env file to inject env vars',
1717
char: 'e',
1818
}),
19+
['project']: flags.string({
20+
description: 'Path to Prisma definition file',
21+
char: 'p',
22+
}),
1923
}
2024
async run() {
2125
let exportPath =

cli/packages/prisma-cli-core/src/commands/generate/generate.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ export default class GenereateCommand extends Command {
2727
description: 'Path to .env file to inject env vars',
2828
char: 'e',
2929
}),
30+
['project']: flags.string({
31+
description: 'Path to Prisma definition file',
32+
char: 'p',
33+
}),
3034
['endpoint']: flags.boolean({
3135
description:
3236
'Use a specific endpoint for schema generation or pick endpoint from prisma.yml',
@@ -99,11 +103,16 @@ export default class GenereateCommand extends Command {
99103
const resolvedOutput = output.startsWith('/')
100104
? output
101105
: path.join(this.config.definitionDir, output)
102-
103-
fs.mkdirpSync(resolvedOutput)
104-
106+
105107
if (generator === 'graphql-schema') {
108+
if (!resolvedOutput.endsWith('.graphql')) {
109+
throw new Error(`Error: ${chalk.bold('output')} for generator ${chalk.bold('graphql-schema')} should be a ${chalk.green(chalk.bold('.graphql'))}-file. Please change the ${chalk.bold('output')} property for this generator in ${chalk.green(chalk.bold('prisma.yml'))}`)
110+
}
111+
112+
fs.mkdirpSync(path.resolve(resolvedOutput, '../'))
106113
await this.generateSchema(resolvedOutput, schemaString)
114+
} else {
115+
fs.mkdirpSync(resolvedOutput)
107116
}
108117

109118
const isMongo =
@@ -158,7 +167,7 @@ export default class GenereateCommand extends Command {
158167
}
159168

160169
async generateSchema(output: string, schemaString: string) {
161-
fs.writeFileSync(path.join(output, 'prisma.graphql'), schemaString)
170+
fs.writeFileSync(output, schemaString)
162171

163172
this.out.log(`Saving Prisma GraphQL schema (SDL) at ${output}`)
164173
}

cli/packages/prisma-cli-core/src/commands/import/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ export default class Import extends Command {
1515
description: 'Path to .env file to inject env vars',
1616
char: 'e',
1717
}),
18+
['project']: flags.string({
19+
description: 'Path to Prisma definition file',
20+
char: 'p',
21+
}),
1822
}
1923
async run() {
2024
const { data } = this.flags

cli/packages/prisma-cli-core/src/commands/info/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ export default class InfoCommand extends Command {
3939
description: 'Path to .env file to inject env vars',
4040
char: 'e',
4141
}),
42+
['project']: flags.string({
43+
description: 'Path to Prisma definition file',
44+
char: 'p',
45+
}),
4246
}
4347
async run() {
4448
const { json, secret } = this.flags

cli/packages/prisma-cli-core/src/commands/introspect/introspect.ts

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import {
1616
ConnectorData,
1717
getConnectorWithDatabase,
1818
IntermediateConnectorData,
19+
populateMongoDatabase,
20+
sanitizeMongoUri,
1921
} from './util'
2022

2123
export default class IntrospectCommand extends Command {
@@ -26,6 +28,16 @@ export default class IntrospectCommand extends Command {
2628
char: 'i',
2729
description: 'Interactive mode',
2830
}),
31+
32+
['env-file']: flags.string({
33+
description: 'Path to .env file to inject env vars',
34+
char: 'e',
35+
}),
36+
['project']: flags.string({
37+
description: 'Path to Prisma definition file',
38+
char: 'p',
39+
}),
40+
2941
/**
3042
* Postgres Params
3143
*/
@@ -164,7 +176,7 @@ ${chalk.bold(
164176
const introspection = await connector.introspect(databaseName)
165177
const sdl = existingDatamodel
166178
? await introspection.getNormalizedDatamodel(existingDatamodel)
167-
: await introspection.getDatamodel()
179+
: await introspection.getNormalizedDatamodel()
168180

169181
const renderer = DefaultRenderer.create(
170182
introspection.databaseType,
@@ -244,7 +256,12 @@ ${chalk.bold(
244256

245257
async getConnector(): Promise<IntermediateConnectorData> {
246258
const hasExecuteRaw = await this.hasExecuteRaw()
247-
const credentials = await this.getCredentials(hasExecuteRaw)
259+
let credentials = this.getCredentialsByFlags()
260+
let interactive = false
261+
if (!credentials) {
262+
credentials = await this.getCredentialsInteractively(hasExecuteRaw)
263+
interactive = true
264+
}
248265
if (credentials) {
249266
const {
250267
connector,
@@ -255,6 +272,7 @@ ${chalk.bold(
255272
disconnect,
256273
databaseType: credentials.type,
257274
databaseName: credentials.schema,
275+
interactive,
258276
}
259277
}
260278

@@ -282,12 +300,11 @@ ${chalk.bold(
282300
disconnect,
283301
databaseType: client.databaseType,
284302
databaseName,
303+
interactive: false,
285304
}
286305
}
287306

288-
async getCredentials(
289-
hasExecuteRaw: boolean,
290-
): Promise<DatabaseCredentials | null> {
307+
getCredentialsByFlags(): DatabaseCredentials | null {
291308
const requiredPostgresFlags = ['pg-host', 'pg-user', 'pg-password', 'pg-db']
292309
const requiredMysqlFlags = ['mysql-host', 'mysql-user', 'mysql-password']
293310

@@ -321,7 +338,7 @@ ${chalk.bold(
321338

322339
if (mysqlFlags.length >= requiredMysqlFlags.length) {
323340
return {
324-
host: flags['myqsl-host'],
341+
host: flags['mysql-host'],
325342
port: parseInt(flags['mysql-port'], 10),
326343
user: flags['mysql-user'],
327344
password: flags['mysql-password'],
@@ -335,22 +352,31 @@ ${chalk.bold(
335352
host: flags['pg-host'],
336353
user: flags['pg-user'],
337354
password: flags['pg-password'],
338-
database: flags['pg-database'],
355+
database: flags['pg-db'],
339356
port: parseInt(flags['pg-port'], 10),
340357
schema: flags['pg-schema'], // this is optional and can be undefined
341358
type: DatabaseType.postgres,
342359
}
343360
}
344361

345362
if (flags['mongo-uri']) {
363+
const uri = flags['mongo-uri']
364+
const database = flags['mongo-db'] // this is optional and can be undefined
365+
const credentials = populateMongoDatabase({ uri, database })
346366
return {
347-
uri: flags['mongo-uri'],
348-
schema: flags['mongo-db'], // this is optional and can be undefined
367+
uri: sanitizeMongoUri(credentials.uri),
368+
schema: credentials.database,
349369
type: DatabaseType.mongo,
350370
}
351371
}
352372

353-
if (flags.interactive || !hasExecuteRaw) {
373+
return null
374+
}
375+
376+
async getCredentialsInteractively(
377+
hasExecuteRaw: boolean,
378+
): Promise<DatabaseCredentials | null> {
379+
if (this.flags.interactive || !hasExecuteRaw) {
354380
const endpointDialog = new EndpointDialog({
355381
out: this.out,
356382
client: this.client,
@@ -359,11 +385,12 @@ ${chalk.bold(
359385
definition: this.definition,
360386
shouldAskForGenerator: false,
361387
})
362-
return await endpointDialog.getDatabase(true)
388+
return endpointDialog.getDatabase(true)
363389
}
364390

365391
return null
366392
}
393+
367394
handleMissingArgs(
368395
requiredArgs: string[],
369396
providedArgs: string[],
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { sanitizeMongoUri, populateMongoDatabase } from './util'
2+
3+
test('sanitizeMongoUri', () => {
4+
expect(sanitizeMongoUri('mongodb://localhost')).toBe(
5+
'mongodb://localhost/admin',
6+
)
7+
expect(sanitizeMongoUri('mongodb://localhost/')).toBe(
8+
'mongodb://localhost/admin',
9+
)
10+
expect(sanitizeMongoUri('mongodb://localhost:27017')).toBe(
11+
'mongodb://localhost:27017/admin',
12+
)
13+
expect(sanitizeMongoUri('mongodb://localhost:27017/')).toBe(
14+
'mongodb://localhost:27017/admin',
15+
)
16+
expect(sanitizeMongoUri('mongodb://localhost:27017/prisma')).toBe(
17+
'mongodb://localhost:27017/prisma',
18+
)
19+
expect(
20+
sanitizeMongoUri(
21+
'mongodb+srv://prisma:asdas9djasdpassword@cluster100.mongodb.net/test?retryWrites=true',
22+
),
23+
).toBe(
24+
'mongodb+srv://prisma:asdas9djasdpassword@cluster100.mongodb.net/test?retryWrites=true',
25+
)
26+
})
27+
28+
test('populateMongoDatabase', () => {
29+
expect(populateMongoDatabase({ uri: 'mongodb://localhost:27017/prisma' }))
30+
.toMatchInlineSnapshot(`
31+
Object {
32+
"database": "prisma",
33+
"uri": "mongodb://localhost:27017/prisma",
34+
}
35+
`)
36+
expect(
37+
populateMongoDatabase({
38+
uri: 'mongodb://localhost:27017/prisma',
39+
database: 'another-db',
40+
}),
41+
).toMatchInlineSnapshot(`
42+
Object {
43+
"database": "another-db",
44+
"uri": "mongodb://localhost:27017/prisma",
45+
}
46+
`)
47+
expect(
48+
populateMongoDatabase({
49+
uri: 'mongodb://localhost:27017/prisma?authSource=admin',
50+
}),
51+
).toMatchInlineSnapshot(`
52+
Object {
53+
"database": "prisma",
54+
"uri": "mongodb://localhost:27017/prisma?authSource=admin",
55+
}
56+
`)
57+
expect(
58+
populateMongoDatabase({
59+
uri: 'mongodb://localhost:27017/',
60+
database: 'database',
61+
}),
62+
).toMatchInlineSnapshot(`
63+
Object {
64+
"database": "database",
65+
"uri": "mongodb://localhost:27017/",
66+
}
67+
`)
68+
expect(() =>
69+
populateMongoDatabase({
70+
uri: 'mongodb://localhost:27017/',
71+
}),
72+
).toThrow()
73+
})

cli/packages/prisma-cli-core/src/commands/introspect/util.ts

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { omit } from 'lodash'
77
import { Connectors } from 'prisma-db-introspection'
88
import { DatabaseType } from 'prisma-datamodel'
99
import { IConnector } from 'prisma-db-introspection/dist/common/connector'
10+
import { URL } from 'url'
1011

1112
function replaceLocalDockerHost(credentials: DatabaseCredentials) {
1213
if (credentials.host) {
@@ -53,6 +54,7 @@ export interface ConnectorData extends ConnectorAndDisconnect {
5354
export interface IntermediateConnectorData extends ConnectorAndDisconnect {
5455
databaseType: DatabaseType
5556
databaseName?: string
57+
interactive: boolean
5658
}
5759

5860
export async function getConnectedConnectorFromCredentials(
@@ -88,7 +90,13 @@ export async function getConnectorWithDatabase(
8890
connectorData: IntermediateConnectorData,
8991
endpointDialog: EndpointDialog,
9092
): Promise<ConnectorData> {
91-
const { connector, disconnect, databaseType, ...result } = connectorData
93+
const {
94+
connector,
95+
disconnect,
96+
databaseType,
97+
interactive,
98+
...result
99+
} = connectorData
92100
let { databaseName } = result
93101

94102
let schemas: string[]
@@ -98,9 +106,14 @@ export async function getConnectorWithDatabase(
98106
throw new Error(`Could not connect to database. ${e.message}`)
99107
}
100108

109+
if (!databaseName && !interactive) {
110+
throw new Error(`Please provide a database name`)
111+
}
112+
101113
if (databaseName && !schemas.includes(databaseName)) {
102114
const schemaWord =
103115
databaseType === DatabaseType.postgres ? 'schema' : 'database'
116+
104117
throw new Error(
105118
`The provided ${schemaWord} "${databaseName}" does not exist. The following are available: ${schemas.join(
106119
', ',
@@ -171,3 +184,40 @@ function getConnectedMongoClient(
171184
)
172185
})
173186
}
187+
188+
export function sanitizeMongoUri(mongoUri: string) {
189+
const url = new URL(mongoUri)
190+
if (url.pathname === '/' || url.pathname.length === 0) {
191+
url.pathname = 'admin'
192+
}
193+
194+
return url.toString()
195+
}
196+
197+
export function populateMongoDatabase({
198+
uri,
199+
database,
200+
}: {
201+
uri: string
202+
database?: string
203+
}): { uri: string; database: string } {
204+
const url = new URL(uri)
205+
if ((url.pathname === '/' || url.pathname.length === 0) && !database) {
206+
throw new Error(
207+
`Please provide a Mongo database in your connection string.\nRead more here https://docs.mongodb.com/manual/reference/connection-string/`,
208+
)
209+
}
210+
211+
if (!database) {
212+
database = url.pathname.slice(1)
213+
}
214+
215+
return {
216+
uri,
217+
database,
218+
}
219+
}
220+
221+
export function hasAuthSource(uri: string): boolean {
222+
return new URL(uri).searchParams.has('authSource')
223+
}

cli/packages/prisma-cli-core/src/commands/playground/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ export default class Playground extends Command {
3737
description: 'Path to .env file to inject env vars',
3838
char: 'e',
3939
}),
40+
['project']: flags.string({
41+
description: 'Path to Prisma definition file',
42+
char: 'p',
43+
}),
4044
'server-only': flags.boolean({
4145
char: 's',
4246
description: 'Run only the server',

0 commit comments

Comments
 (0)