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

Commit f783df8

Browse files
committed
Merge branch 'beta'
2 parents f5c6dc8 + 433b613 commit f783df8

135 files changed

Lines changed: 7411 additions & 1947 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/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"@types/fs-extra": "^5.0.0",
1414
"@types/graphql": "^14.0.3",
1515
"@types/node": "^8.0.22",
16+
"@types/semver": "^5.5.0",
1617
"faker": "^4.1.0",
1718
"graphql-tools": "^4.0.3",
1819
"husky": "^1.2.0",
@@ -76,6 +77,7 @@
7677
}
7778
},
7879
"dependencies": {
80+
"@types/express": "^4.16.1",
7981
"adm-zip": "^0.4.7",
8082
"archiver": "^2.0.3",
8183
"callsites": "^2.0.0",
@@ -107,6 +109,7 @@
107109
"prisma-generate-schema": "1.20.4",
108110
"prisma-yml": "1.0.95",
109111
"scuid": "^1.0.2",
112+
"semver": "^5.6.0",
110113
"sillyname": "^0.1.0",
111114
"source-map-support": "^0.4.18",
112115
"table": "^4.0.1"
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { Command, flags, Flags } from 'prisma-cli-engine'
2+
import chalk from 'chalk'
3+
import * as opn from 'opn'
4+
import { satisfiesVersion } from '../../utils/satisfiesVersion'
5+
6+
export default class Admin extends Command {
7+
static topic = 'admin'
8+
static description = 'Open service endpoints in Prisma Admin'
9+
10+
static flags: Flags = {
11+
'env-file': flags.string({
12+
description: 'Path to .env file to inject env vars',
13+
char: 'e',
14+
}),
15+
}
16+
17+
async run() {
18+
const envFile = this.flags['env-file']
19+
await this.definition.load(this.flags, envFile)
20+
21+
const serviceName = this.definition.service!
22+
const stage = this.definition.stage!
23+
24+
const token = this.definition.getToken(serviceName, stage)
25+
const cluster = await this.definition.getCluster(false)
26+
const clusterVersion = await cluster!.getVersion()
27+
28+
if (satisfiesVersion(clusterVersion!, '1.29.0')) {
29+
let adminUrl = this.definition.endpoint + '/_admin'
30+
if (token && token.length > 0) {
31+
adminUrl += `?token=${token}`
32+
}
33+
this.out.log(`Opening Prisma Admin ${adminUrl} in the browser`)
34+
opn(adminUrl).catch(() => {})
35+
} else {
36+
this.out.log(`Your Prisma server at ${chalk.bold(
37+
`${this.definition.endpoint}`,
38+
)} doesn't support Prisma Admin yet. Prisma Admin is supported from Prisma ${chalk.green(
39+
`1.29`,
40+
)} and higher. Your Prisma server currently uses Prisma ${chalk.red(
41+
`${clusterVersion}`,
42+
)}.\n\n
43+
Please upgrade your Prisma server to use Prisma Admin.`)
44+
this.out.exit(1)
45+
}
46+
}
47+
48+
normalizeVersion(version: string) {
49+
version = version.replace(/-beta.*/, '').replace('-alpha', '')
50+
const regex = /(\d+\.\d+)/
51+
const match = regex.exec(version)
52+
if (match) {
53+
return match[1] + '.0'
54+
}
55+
return version
56+
}
57+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export default class ConsoleCommand extends Command {
99
async run() {
1010
const url = `https://app.prisma.io`
1111

12-
this.out.log(`Opening prisma console ${url} in the browser`)
12+
this.out.log(`Opening Prisma console ${url} in the browser`)
1313
opn(url).catch(() => {}) // Prevent `unhandledRejection` error.
1414
}
1515
}

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: 26 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,18 @@ import * as path from 'path'
66
import * as fs from 'fs-extra'
77
import { Seeder } from '../seed/Seeder'
88
const debug = require('debug')('deploy')
9-
import { prettyTime, concatName, defaultDockerCompose } from '../../utils/util'
9+
import {
10+
prettyTime,
11+
concatName,
12+
defaultDockerCompose,
13+
printAdminLink,
14+
} from '../../utils/util'
1015
import * as sillyname from 'sillyname'
1116
import { EndpointDialog } from '../../utils/EndpointDialog'
1217
import { spawnSync } from 'npm-run'
1318
import { spawnSync as nativeSpawnSync } from 'child_process'
1419
import * as figures from 'figures'
20+
import { satisfiesVersion } from '../../utils/satisfiesVersion'
1521

1622
export default class Deploy extends Command {
1723
static topic = 'deploy'
@@ -58,10 +64,12 @@ ${chalk.gray(
5864
description: 'Path to .env file to inject env vars',
5965
char: 'e',
6066
}),
67+
['project']: flags.string({
68+
description: 'Path to Prisma definition file',
69+
char: 'p',
70+
}),
6171
}
62-
private deploying: boolean = false
6372
private showedHooks: boolean = false
64-
private loggedIn: boolean = false
6573
async run() {
6674
/**
6775
* Get Args
@@ -95,7 +103,6 @@ ${chalk.gray(
95103
*/
96104
let workspace: string | undefined | null = this.definition.getWorkspace()
97105
let cluster
98-
let dockerComposeYml = defaultDockerCompose
99106
if (!serviceName || !stage || interactive) {
100107
await this.env.fetchClusters()
101108
const endpointDialog = new EndpointDialog({
@@ -111,7 +118,6 @@ ${chalk.gray(
111118
workspace = results.workspace
112119
serviceName = results.service
113120
stage = results.stage
114-
dockerComposeYml = results.dockerComposeYml
115121
this.definition.replaceEndpoint(results.endpoint)
116122
// Reload definition because we are changing the yml file
117123
await this.definition.load(this.flags, envFile)
@@ -182,12 +188,6 @@ ${chalk.gray(
182188
)
183189
}
184190

185-
private getSillyName() {
186-
return `${slugify(sillyname()).split('-')[0]}-${Math.round(
187-
Math.random() * 1000,
188-
)}`
189-
}
190-
191191
private async projectExists(
192192
cluster: Cluster,
193193
name: string,
@@ -232,7 +232,6 @@ ${chalk.gray(
232232
workspace: string | null,
233233
noMigrate: boolean,
234234
): Promise<void> {
235-
this.deploying = true
236235
let before = Date.now()
237236

238237
const b = s => `\`${chalk.bold(s)}\``
@@ -351,9 +350,8 @@ ${chalk.gray(
351350
}
352351

353352
// no action required
354-
this.deploying = false
355353
if (migrationResult.migration) {
356-
this.printEndpoints(
354+
await this.printEndpoints(
357355
cluster,
358356
serviceName,
359357
stageName,
@@ -458,149 +456,32 @@ ${chalk.gray(
458456
}
459457
}
460458

461-
private printEndpoints(
459+
private async printEndpoints(
462460
cluster: Cluster,
463461
serviceName: string,
464462
stageName: string,
465463
workspace?: string,
466464
) {
467-
this.out.log(`\n${chalk.bold(
468-
'Your Prisma GraphQL database endpoint is live:',
469-
)}
465+
const version = await cluster.getVersion()
466+
const hasAdmin = satisfiesVersion(version!, '1.29.0')
467+
const adminText = hasAdmin
468+
? printAdminLink(
469+
cluster.getApiEndpoint(serviceName, stageName, workspace),
470+
)
471+
: ''
470472

471-
${chalk.bold('HTTP:')} ${cluster.getApiEndpoint(
472-
serviceName,
473-
stageName,
474-
workspace,
475-
)}
476-
${chalk.bold('WS:')} ${cluster.getWSEndpoint(
473+
this.out.log(`\n${'Your Prisma GraphQL database endpoint is live:'}
474+
475+
${'HTTP:'} ${cluster.getApiEndpoint(serviceName, stageName, workspace)}
476+
${'WS:'} ${cluster.getWSEndpoint(
477477
serviceName,
478478
stageName,
479479
workspace,
480-
)}
480+
)}${adminText}
481481
`)
482482
}
483-
484-
private getCloudClusters(): Cluster[] {
485-
return this.env.clusters.filter(c => c.shared || c.isPrivate)
486-
}
487-
488-
private async clusterSelection(loggedIn: boolean): Promise<string> {
489-
debug({ loggedIn })
490-
491-
const choices = loggedIn
492-
? await this.getLoggedInChoices()
493-
: this.getPublicChoices()
494-
495-
const question = {
496-
name: 'cluster',
497-
type: 'list',
498-
message: `Please choose the cluster you want to deploy to`,
499-
choices,
500-
pageSize: 9,
501-
}
502-
503-
const { cluster } = await this.out.prompt(question)
504-
505-
if (cluster === 'login') {
506-
await this.client.login()
507-
this.loggedIn = true
508-
return this.clusterSelection(true)
509-
}
510-
511-
return cluster
512-
}
513-
514-
private getLocalClusterChoices(): string[][] {
515-
return [['local', 'Local cluster (requires Docker)']]
516-
}
517-
518-
private async getLoggedInChoices(): Promise<any[]> {
519-
await this.env.fetchClusters()
520-
const localChoices = this.getLocalClusterChoices()
521-
const combinations: string[][] = []
522-
const remoteClusters = this.env.clusters.filter(
523-
c => c.shared || c.isPrivate,
524-
)
525-
526-
remoteClusters.forEach(cluster => {
527-
const label = this.env.sharedClusters.includes(cluster.name)
528-
? 'Free development cluster (hosted on Prisma Cloud)'
529-
: 'Private Prisma Cluster'
530-
combinations.push([`${cluster.workspaceSlug}/${cluster.name}`, label])
531-
})
532-
533-
const allCombinations = [...combinations, ...localChoices]
534-
535-
return [
536-
new inquirer.Separator(' '),
537-
...this.convertChoices(allCombinations),
538-
new inquirer.Separator(' '),
539-
new inquirer.Separator(
540-
chalk.dim(
541-
`You can learn more about deployment in the docs: http://bit.ly/prisma-graphql-deployment`,
542-
),
543-
),
544-
]
545-
}
546-
547-
private convertChoices(
548-
choices: string[][],
549-
): Array<{ value: string; name: string }> {
550-
const padded = this.out.printPadded(choices, 0, 6).split('\n')
551-
return padded.map((name, index) => ({
552-
name,
553-
value: choices[index][0],
554-
}))
555-
}
556-
557-
private getPublicChoices(): any[] {
558-
const publicChoices = [
559-
[
560-
'prisma-eu1',
561-
'Public development cluster (hosted in EU on Prisma Cloud)',
562-
],
563-
[
564-
'prisma-us1',
565-
'Public development cluster (hosted in US on Prisma Cloud)',
566-
],
567-
]
568-
const allCombinations = [...publicChoices, ...this.getLocalClusterChoices()]
569-
570-
return [
571-
...this.convertChoices(allCombinations),
572-
new inquirer.Separator(' '),
573-
{
574-
value: 'login',
575-
name: 'Log in or create new account on Prisma Cloud',
576-
},
577-
new inquirer.Separator(' '),
578-
new inquirer.Separator(
579-
chalk.dim(
580-
`Note: When not logged in, service deployments to Prisma Cloud expire after 7 days.`,
581-
),
582-
),
583-
new inquirer.Separator(
584-
chalk.dim(
585-
`You can learn more about deployment in the docs: http://bit.ly/prisma-graphql-deployment`,
586-
),
587-
),
588-
new inquirer.Separator(' '),
589-
]
590-
}
591483
}
592484

593485
export function isValidProjectName(projectName: string): boolean {
594486
return /^[A-Z](.*)/.test(projectName)
595-
}
596-
597-
function slugify(text) {
598-
return text
599-
.toString()
600-
.toLowerCase()
601-
.replace(/\s+/g, '-') // Replace spaces with -
602-
.replace(/[^\w\-]+/g, '') // Remove all non-word chars
603-
.replace(/\-\-+/g, '-') // Replace multiple - with single -
604-
.replace(/^-+/, '') // Trim - from start of text
605-
.replace(/-+$/, '') // Trim - from end of text
606-
}
487+
}

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 =

0 commit comments

Comments
 (0)