-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add local Unix domain socket support (#336)
Adds a new Connector.startLocalProxy method that starts a local proxy tunnel listening to the location defined at listenOptions enabling usage of the Connector by drivers and different libraries / frameworks that are not currently supported by the Connector directly but that can connect to databases via Unix sockets.
- Loading branch information
1 parent
404a85f
commit 72575ba
Showing
20 changed files
with
682 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// Copyright 2024 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
const {resolve} = require('node:path'); | ||
const {Connector} = require('@google-cloud/cloud-sql-connector'); | ||
const {PrismaClient} = require('@prisma/client'); | ||
|
||
async function connect({instanceConnectionName, user, database}) { | ||
const path = resolve('mysql.socket'); | ||
const connector = new Connector(); | ||
await connector.startLocalProxy({ | ||
instanceConnectionName, | ||
ipType: 'PUBLIC', | ||
authType: 'IAM', | ||
listenOptions: {path}, | ||
}); | ||
|
||
const datasourceUrl = `mysql://${user}@localhost/${database}?socket=${path}`; | ||
const prisma = new PrismaClient({datasourceUrl}); | ||
|
||
return { | ||
prisma, | ||
async close() { | ||
await prisma.$disconnect(); | ||
connector.close(); | ||
}, | ||
}; | ||
} | ||
|
||
module.exports = { | ||
connect, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// Copyright 2024 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
import {resolve} from 'node:path'; | ||
import {Connector} from '@google-cloud/cloud-sql-connector'; | ||
import {PrismaClient} from '@prisma/client'; | ||
|
||
export async function connect({instanceConnectionName, user, database}) { | ||
const path = resolve('mysql.socket'); | ||
const connector = new Connector(); | ||
await connector.startLocalProxy({ | ||
instanceConnectionName, | ||
ipType: 'PUBLIC', | ||
authType: 'IAM', | ||
listenOptions: {path}, | ||
}); | ||
|
||
const datasourceUrl = `mysql://${user}@localhost/${database}?socket=${path}`; | ||
const prisma = new PrismaClient({datasourceUrl}); | ||
|
||
return { | ||
prisma, | ||
async close() { | ||
await prisma.$disconnect(); | ||
connector.close(); | ||
}, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// Copyright 2024 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
import {resolve} from 'node:path'; | ||
import { | ||
AuthTypes, | ||
Connector, | ||
IpAddressTypes, | ||
} from '@google-cloud/cloud-sql-connector'; | ||
import {PrismaClient} from '@prisma/client'; | ||
|
||
export async function connect({instanceConnectionName, user, database}) { | ||
const path = resolve('mysql.socket'); | ||
const connector = new Connector(); | ||
await connector.startLocalProxy({ | ||
instanceConnectionName, | ||
ipType: IpAddressTypes.PUBLIC, | ||
authType: AuthTypes.IAM, | ||
listenOptions: {path}, | ||
}); | ||
|
||
const datasourceUrl = `mysql://${user}@localhost/${database}?socket=${path}`; | ||
const prisma = new PrismaClient({datasourceUrl}); | ||
|
||
return { | ||
prisma, | ||
async close() { | ||
await prisma.$disconnect(); | ||
connector.close(); | ||
}, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
datasource db { | ||
provider = "mysql" | ||
url = env("DB_URL") | ||
} | ||
|
||
model User { | ||
id Int @id @default(autoincrement()) | ||
} | ||
|
||
generator client { | ||
provider = "prisma-client-js" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// Copyright 2024 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
const {execSync} = require('node:child_process'); | ||
const {resolve} = require('node:path'); | ||
const t = require('tap'); | ||
|
||
function generatePrismaClient() { | ||
const schemaPath = resolve(__dirname, '../schema.prisma'); | ||
|
||
execSync(`npx prisma generate --schema=${schemaPath}`); | ||
} | ||
|
||
t.test('mysql prisma cjs', async t => { | ||
// prisma client generation should normally be part of a regular Prisma | ||
// setup on user end but in order to tests in many different databases | ||
// we run the generation step at runtime for each variation | ||
generatePrismaClient(); | ||
|
||
const {connect} = require('../connect.cjs'); | ||
const {prisma, close} = await connect({ | ||
instanceConnectionName: process.env.MYSQL_IAM_CONNECTION_NAME, | ||
user: process.env.MYSQL_IAM_USER, | ||
database: process.env.MYSQL_DB, | ||
}); | ||
const [{now}] = await prisma.$queryRaw`SELECT NOW() as now`; | ||
t.ok(now.getTime(), 'should have valid returned date object'); | ||
await close(); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// Copyright 2024 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
import { execSync } from 'node:child_process'; | ||
import { dirname, resolve } from 'node:path' | ||
import { fileURLToPath } from 'node:url' | ||
import t from 'tap'; | ||
|
||
function generatePrismaClient() { | ||
const p = fileURLToPath(import.meta.url) | ||
const __dirname = dirname(p) | ||
const schemaPath = resolve(__dirname, '../schema.prisma'); | ||
|
||
execSync(`npx prisma generate --schema=${schemaPath}`); | ||
} | ||
|
||
t.test('mysql prisma mjs', async t => { | ||
// prisma client generation should normally be part of a regular Prisma | ||
// setup on user end but in order to tests in many different databases | ||
// we run the generation step at runtime for each variation | ||
generatePrismaClient(); | ||
|
||
const { connect } = await import('../connect.mjs'); | ||
const { prisma, close } = await connect({ | ||
instanceConnectionName: process.env.MYSQL_IAM_CONNECTION_NAME, | ||
user: process.env.MYSQL_IAM_USER, | ||
database: process.env.MYSQL_DB, | ||
}); | ||
const [{ now }] = await prisma.$queryRaw`SELECT NOW() as now` | ||
t.ok(now.getTime(), 'should have valid returned date object'); | ||
await close(); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// Copyright 2024 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
import {execSync} from 'node:child_process'; | ||
import {resolve} from 'node:path'; | ||
import t from 'tap'; | ||
|
||
function generatePrismaClient() { | ||
const schemaPath = resolve(__dirname, '../schema.prisma'); | ||
|
||
execSync(`npx prisma generate --schema=${schemaPath}`); | ||
} | ||
|
||
t.test('mysql prisma ts', async t => { | ||
// prisma client generation should normally be part of a regular Prisma | ||
// setup on user end but in order to tests in many different databases | ||
// we run the generation step at runtime for each variation | ||
generatePrismaClient(); | ||
|
||
const { | ||
default: {connect}, | ||
} = await import('../connect.ts'); | ||
const {prisma, close} = await connect({ | ||
instanceConnectionName: process.env.MYSQL_IAM_CONNECTION_NAME, | ||
user: process.env.MYSQL_IAM_USER, | ||
database: process.env.MYSQL_DB, | ||
}); | ||
const [{now}] = await prisma.$queryRaw`SELECT NOW() as now`; | ||
t.ok(now.getTime(), 'should have valid returned date object'); | ||
await close(); | ||
}); |
Oops, something went wrong.