Skip to content

Commit

Permalink
add more generator checks
Browse files Browse the repository at this point in the history
  • Loading branch information
timsuchanek committed Oct 8, 2019
1 parent 7273038 commit 95c92ff
Show file tree
Hide file tree
Showing 12 changed files with 345 additions and 49 deletions.
2 changes: 1 addition & 1 deletion cli/generator-helper/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@prisma/generator-helper",
"version": "0.0.5",
"version": "0.0.6",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"typings": "dist/index.d.ts",
Expand Down
17 changes: 16 additions & 1 deletion cli/generator-helper/src/GeneratorProcess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ import chalk from 'chalk'

let globalMessageId = 1

export class GeneratorError extends Error {
public code: number
public data?: any
constructor(message: string, code: number, data?: any) {
super(message)
this.code = code
this.data = data
}
}

export class GeneratorProcess {
child?: ChildProcessByStdio<any, any, any>
listeners: { [key: string]: (result: any, err?: Error) => void } = {}
Expand Down Expand Up @@ -100,7 +110,12 @@ export class GeneratorProcess {
}
if (this.listeners[data.id]) {
if (data.error) {
this.listeners[data.id](null, data.error)
const error = new GeneratorError(
data.error.message,
data.error.code,
data.error.data,
)
this.listeners[data.id](null, error)
} else {
this.listeners[data.id](data.result)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const stubOptions: GeneratorOptions = {
},
otherGenerators: [],
schemaPath: '',
version: 'latest',
}

describe('generatorHandler', () => {
Expand All @@ -35,7 +36,6 @@ describe('generatorHandler', () => {
path.join(__dirname, 'not-executable'),
)
}).toThrow('is not executable')
// expect(generator.init()).rejects.toThrow('is not executable')
})
test('parsing error', async () => {
const generator = new GeneratorProcess(
Expand Down
2 changes: 1 addition & 1 deletion cli/generator-helper/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export { GeneratorProcess } from './GeneratorProcess'
export { GeneratorProcess, GeneratorError } from './GeneratorProcess'
export { generatorHandler } from './generatorHandler'
export * from './types'
1 change: 1 addition & 0 deletions cli/generator-helper/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ export type GeneratorOptions = {
datasources: DataSource[]
datamodel: string
binaryPaths?: BinaryPaths
version: string // version hash
}

export type EngineType =
Expand Down
3 changes: 2 additions & 1 deletion cli/sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@
},
"dependencies": {
"@prisma/cli": "^0.1.10",
"@prisma/engine-core": "^0.0.97",
"@prisma/fetch-engine": "^0.3.0",
"@prisma/generator-helper": "^0.0.4",
"@prisma/generator-helper": "^0.0.6",
"@prisma/get-platform": "^0.1.2",
"chalk": "^2.4.2",
"execa": "^2.0.5",
Expand Down
22 changes: 14 additions & 8 deletions cli/sdk/src/__tests__/engineCommands.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import { getDMMF, getConfig, dmmfToDml } from '../engineCommands'

describe('getDMMF', () => {
test('simple model', async () => {
const dmmf = await getDMMF(`model A {
const dmmf = await getDMMF({
datamodel: `model A {
id Int @id
name String
}`)
}`,
})

expect(dmmf.datamodel).toMatchInlineSnapshot(`
Object {
Expand Down Expand Up @@ -53,16 +55,19 @@ describe('getDMMF', () => {

describe('getConfig', () => {
test('empty config', async () => {
const config = await getConfig(`model A {
const config = await getConfig({
datamodel: `model A {
id Int @id
name String
}`)
}`,
})

expect(config).toMatchSnapshot()
})

test('with generator and datasource', async () => {
const config = await getConfig(`
const config = await getConfig({
datamodel: `
datasource db {
url = "file:dev.db"
provider = "sqlite"
Expand All @@ -76,7 +81,8 @@ describe('getConfig', () => {
model A {
id Int @id
name String
}`)
}`,
})

expect(config).toMatchSnapshot()
})
Expand All @@ -99,8 +105,8 @@ describe('dmmfToDml', () => {
id Int @id
name String
}`
const dmmf = await getDMMF(datamodel)
const config = await getConfig(datamodel)
const dmmf = await getDMMF({ datamodel })
const config = await getConfig({ datamodel })

const printedDatamodel = await dmmfToDml({
dmmf: dmmf.datamodel,
Expand Down
27 changes: 17 additions & 10 deletions cli/sdk/src/engineCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,19 @@ async function getPrismaPath(): Promise<string> {
return path.join(dir, relative)
}

export async function getDMMF(
datamodel: string,
export type GetDMMFOptions = {
datamodel: string
cwd?: string
prismaPath?: string
datamodelPath?: string
}

export async function getDMMF({
datamodel,
cwd = process.cwd(),
prismaPath?: string,
datamodelPath?: string,
): Promise<DMMF.Document> {
prismaPath,
datamodelPath,
}: GetDMMFOptions): Promise<DMMF.Document> {
prismaPath = prismaPath || (await getPrismaPath())
try {
const result = await execa(prismaPath, ['cli', '--dmmf'], {
Expand All @@ -41,12 +48,12 @@ export async function getDMMF(
}
}

export async function getConfig(
datamodel: string,
export async function getConfig({
datamodel,
cwd = process.cwd(),
prismaPath?: string,
datamodelPath?: string,
): Promise<ConfigMetaFormat> {
prismaPath,
datamodelPath,
}: GetDMMFOptions): Promise<ConfigMetaFormat> {
prismaPath = prismaPath || (await getPrismaPath())
try {
const result = await execa(
Expand Down
103 changes: 97 additions & 6 deletions cli/sdk/src/getGenerators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import { unique } from './unique'
import { pick } from './pick'
import { Generator } from './Generator'
import { resolveOutput } from './resolveOutput'
import { getPlatform } from '@prisma/get-platform'
import { printGeneratorConfig, fixPlatforms } from '@prisma/engine-core'

export type GetGeneratorOptions = {
schemaPath: string
Expand Down Expand Up @@ -44,8 +46,11 @@ export async function getGenerators({
}

const schema = fs.readFileSync(schemaPath, 'utf-8')
const dmmf = await getDMMF(schema)
const config = await getConfig(schema)
const dmmf = await getDMMF({ datamodel: schema, datamodelPath: schemaPath })
const config = await getConfig({
datamodel: schema,
datamodelPath: schemaPath,
})

validateGenerators(config.generators)

Expand Down Expand Up @@ -100,6 +105,7 @@ The generator needs to either define the \`defaultOutput\` path in the manifest
dmmf,
otherGenerators: skipIndex(config.generators, index),
schemaPath,
version: version || 'latest',
}

// we set the options here a bit later after instantiating the Generator,
Expand All @@ -119,10 +125,14 @@ The generator needs to either define the \`defaultOutput\` path in the manifest
const binaries = generators.flatMap(g =>
g.manifest ? g.manifest.requiresEngines || [] : [],
)
const binaryTargets = unique(
let binaryTargets = unique(
config.generators.flatMap(g => g.binaryTargets || []),
)

if (binaryTargets.length === 0) {
binaryTargets = [await getPlatform()]
}

const binariesConfig: BinaryDownloadConfiguration = binaries.reduce(
(acc, curr) => {
acc[engineTypeToBinaryType(curr)] = path.join(__dirname, '../')
Expand All @@ -141,7 +151,11 @@ The generator needs to either define the \`defaultOutput\` path in the manifest
version: version || 'latest',
}

const binaryPaths = await download(downloadParams)
const binaryPathsWithEngineType = await download(downloadParams)
const binaryPaths = mapKeys(
binaryPathsWithEngineType,
binaryTypeToEngineType,
)

for (const generator of generators) {
if (generator.manifest && generator.manifest.requiresEngines) {
Expand Down Expand Up @@ -189,13 +203,21 @@ export const knownBinaryTargets = [
'windows',
]

function validateGenerators(generators: GeneratorConfig[]) {
async function validateGenerators(generators: GeneratorConfig[]) {
const platform = await getPlatform()

for (const generator of generators) {
if (generator.config.platforms) {
throw new Error(
`The \`platforms\` field on the generator definition is deprecated. Please rename it to \`binaryTargets\`.`,
)
}
if (generator.config.pinnedPlatform) {
throw new Error(
`The \`pinnedPlatform\` field on the generator definition is deprecated.
Please use the PRISMA_QUERY_ENGINE_BINARY env var instead to pin the binary target.`,
)
}
if (generator.binaryTargets) {
for (const binaryTarget of generator.binaryTargets) {
if (!knownBinaryTargets.includes(binaryTarget)) {
Expand All @@ -207,6 +229,49 @@ Possible binaryTargets: ${chalk.greenBright(knownBinaryTargets.join(', '))}`,
)
}
}

const binaryTargets =
generator.binaryTargets && generator.binaryTargets.length > 0
? generator.binaryTargets
: ['native']

const resolvedBinaryTargets = binaryTargets.map(p =>
p === 'native' ? platform : p,
)

if (!resolvedBinaryTargets.includes(platform)) {
if (generator) {
console.log(`${chalk.yellow(
'Warning:',
)} Your current platform \`${chalk.bold(
platform,
)}\` is not included in your generator's \`binaryTargets\` configuration ${JSON.stringify(
generator.binaryTargets,
)}.
To fix it, use this generator config in your ${chalk.bold('schema.prisma')}:
${chalk.greenBright(
printGeneratorConfig({
...generator,
binaryTargets: fixPlatforms(generator.binaryTargets as any[], platform),
}),
)}
${chalk.gray(
`Note, that by providing \`native\`, Photon automatically resolves \`${platform}\`.
Read more about deploying Photon: ${chalk.underline(
'https://github.com/prisma/prisma2/blob/master/docs/core/generators/photonjs.md',
)}`,
)}\n`)
} else {
console.log(
`${chalk.yellow('Warning')} The binaryTargets ${JSON.stringify(
binaryTargets,
)} don't include your local platform ${platform}, which you can also point to with \`native\`.
In case you want to fix this, you can provide ${chalk.greenBright(
`binaryTargets: ${JSON.stringify(['native', ...(binaryTargets || [])])}`,
)} in the schema.prisma file.`,
)
}
}
}
}
}
Expand All @@ -226,5 +291,31 @@ function engineTypeToBinaryType(
return 'query-engine'
}

throw new Error(`Could not convert binary type ${engineType}`)
throw new Error(`Could not convert engine type ${engineType}`)
}

function binaryTypeToEngineType(binaryType: string): string {
if (binaryType === 'introspection-engine') {
return 'introspectionEngine'
}

if (binaryType === 'migration-engine') {
return 'migrationEngine'
}

if (binaryType === 'query-engine') {
return 'queryEngine'
}

throw new Error(`Could not convert binary type ${binaryType}`)
}

function mapKeys<T extends object>(
obj: T,
mapper: (key: keyof T) => string,
): any {
return Object.entries(obj).reduce((acc, [key, value]) => {
acc[mapper(key as keyof T)] = value
return acc
}, {})
}
2 changes: 1 addition & 1 deletion cli/sdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ export { Generator } from './Generator'
export { getGenerators, getGenerator } from './getGenerators'
export { isdlToDatamodel2 } from './isdlToDatamodel2'
export { isdlToDmmfDatamodel } from './isdlToDmmfDatamodel'
export { getDMMF, getConfig, dmmfToDml } from './engineCommands'
export { getDMMF, getConfig, dmmfToDml, GetDMMFOptions } from './engineCommands'
2 changes: 1 addition & 1 deletion cli/sdk/src/resolveOutput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export type ResolveOutputOptions = {
export async function resolveOutput(options: ResolveOutputOptions) {
const defaultOutput = stripRelativePath(options.defaultOutput)
if (defaultOutput.startsWith('node_modules')) {
const nodeModulesBase = await resolveNodeModulesBase(options.defaultOutput)
const nodeModulesBase = await resolveNodeModulesBase(options.baseDir)
return path.resolve(nodeModulesBase, defaultOutput)
}

Expand Down

0 comments on commit 95c92ff

Please sign in to comment.