Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Drizzle] Add support for XataFiles #1403

Draft
wants to merge 64 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
b7c53e9
Experimental ORM check for pgroll
SferaDev Jan 31, 2024
9c3f594
Update
SferaDev Feb 1, 2024
152e3f7
Update
SferaDev Feb 5, 2024
a50e902
Update
SferaDev Feb 5, 2024
c7964f1
Update `pgroll` schema for `alter_column` (#1343)
SferaDev Feb 1, 2024
2210e2f
Add github action to update pgroll spec (#1345)
SferaDev Feb 2, 2024
685f2b8
Install tsx on workflow (#1346)
SferaDev Feb 2, 2024
5528493
Update pgroll spec (#1351)
xata-bot Feb 2, 2024
aba29fd
Update dependencies (#1352)
SferaDev Feb 7, 2024
c69e362
Force npmjs snapshots (#1353)
SferaDev Feb 5, 2024
412fa1e
timeout to build job (#1349)
eemmiillyy Feb 5, 2024
0672b6d
feat: pgroll migration format (#1350)
eemmiillyy Feb 5, 2024
ef60e40
[OpenAPI] Spec updates (#1354)
xata-bot Feb 6, 2024
5547cda
[OpenAPI] Spec updates (#1355)
xata-bot Feb 6, 2024
a1600d8
Revamp drizzle drivers
SferaDev Feb 7, 2024
251bfae
Merge remote-tracking branch 'origin/main' into drizzle-pure-sql-test
SferaDev Feb 7, 2024
93f7713
Update test suite
SferaDev Feb 7, 2024
c6aa138
Apply suggestions from code review
SferaDev Feb 7, 2024
d6565a4
Update test
SferaDev Feb 7, 2024
b0e1a7d
Update import
SferaDev Feb 7, 2024
efb2ac6
Wrap in describe
SferaDev Feb 7, 2024
a161abc
Add concurrency
SferaDev Feb 7, 2024
1af08d3
Fix SSL problem with staging
SferaDev Feb 7, 2024
afec17e
Fix test
SferaDev Feb 7, 2024
e3a3761
Make them concurrent
SferaDev Feb 7, 2024
2d7a05d
Skip tests that are failing
SferaDev Feb 8, 2024
d21ada6
Update test
SferaDev Feb 8, 2024
c397ef3
Update migrate code
SferaDev Feb 8, 2024
58786f3
Merge branch 'main' into drizzle-pure-sql-test
SferaDev Feb 8, 2024
7ab1fbe
Rename test
SferaDev Feb 8, 2024
1cc8a90
Enable skipped tests
SferaDev Feb 9, 2024
d585755
Merge branch 'main' into drizzle-pure-sql-test
SferaDev Feb 9, 2024
248bb57
Update tests
SferaDev Feb 19, 2024
296af44
Update tests
SferaDev Feb 19, 2024
576c1fe
Merge remote-tracking branch 'origin/main' into drizzle-pure-sql-test
SferaDev Feb 19, 2024
945daa4
Merge branch 'main' into drizzle-pure-sql-test
SferaDev Feb 20, 2024
397b46f
Add support for array response type
SferaDev Feb 20, 2024
cf45f35
Update test
SferaDev Feb 20, 2024
fea0a25
Disable SQL tests with breaking change (#1377)
SferaDev Feb 20, 2024
002e1b5
Use new responseType param
SferaDev Feb 20, 2024
794db33
Update sessions
SferaDev Feb 20, 2024
1e59dfb
Merge remote-tracking branch 'origin/main' into drizzle-pure-sql-test
SferaDev Feb 23, 2024
0bf59f4
Enable SSL in tests
SferaDev Feb 23, 2024
c42ba17
Update client
SferaDev Feb 26, 2024
92101ca
Merge branch 'main' into drizzle-pure-sql-test
SferaDev Feb 26, 2024
22b08e8
Apply suggestions from code review
SferaDev Feb 26, 2024
32eb096
Update test matrix
SferaDev Feb 26, 2024
e4650f2
Run migrations via pg only for now
SferaDev Feb 26, 2024
42cf85b
Update dependencies
SferaDev Feb 26, 2024
751d0d2
Fix build
SferaDev Feb 26, 2024
f493ff3
Merge remote-tracking branch 'origin/main' into drizzle-pure-sql-test
SferaDev Feb 27, 2024
d4856d4
Merge remote-tracking branch 'origin/main' into drizzle-pure-sql-test
SferaDev Feb 27, 2024
0ae148b
Update tests
SferaDev Feb 27, 2024
276059e
Update changesets
SferaDev Feb 27, 2024
bfc9497
Add exports for pg
SferaDev Mar 1, 2024
6bb701a
Remove transaction tests
SferaDev Mar 5, 2024
c456a04
Enable http tests
SferaDev Mar 5, 2024
8d2adaa
Merge remote-tracking branch 'origin/main' into drizzle-pure-sql-test
SferaDev Mar 5, 2024
2df9986
Updates to drivers
SferaDev Mar 7, 2024
692c915
Merge branch 'main' into drizzle-pure-sql-test
SferaDev Mar 8, 2024
7261393
Delete .changeset/serious-eels-grow.md
SferaDev Mar 8, 2024
678f41e
Apply suggestions from code review
SferaDev Mar 8, 2024
eb78114
[Drizzle] Add support for XataFiles
SferaDev Mar 11, 2024
cb9d0b3
Updates
SferaDev Mar 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/yellow-mugs-fry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@xata.io/drizzle': patch
---

Update drizzle driver
11 changes: 9 additions & 2 deletions packages/plugin-client-drizzle/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
"import": "./dist/index.mjs",
"require": "./dist/index.cjs",
"types": "./dist/index.d.ts"
},
"./pg": {
"import": "./dist/pg.mjs",
"require": "./dist/pg.cjs",
"types": "./dist/pg.d.ts"
}
},
"scripts": {
Expand All @@ -22,10 +27,12 @@
"url": "https://github.com/xataio/client-ts/issues"
},
"dependencies": {
"@xata.io/client": "workspace:*"
"@xata.io/client": "workspace:*",
"pg": "^8.11.3"
},
"devDependencies": {
"drizzle-orm": "^0.29.3"
"@types/pg": "^8.11.2",
"drizzle-orm": "^0.29.5"
},
"peerDependencies": {
"drizzle-orm": "^0.28.5"
Expand Down
26 changes: 25 additions & 1 deletion packages/plugin-client-drizzle/rollup.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,29 @@ export default [
file: `dist/index.d.ts`,
format: 'es'
}
}
},
{
input: 'src/pg/index.ts',
plugins: [esbuild()],
output: [
{
file: `dist/pg.cjs`,
format: 'cjs',
sourcemap: true
},
{
file: `dist/pg.mjs`,
format: 'es',
sourcemap: true
}
]
},
{
input: 'src/pg/index.ts',
plugins: [dts()],
output: {
file: `dist/pg.d.ts`,
format: 'es'
}
},
];
64 changes: 0 additions & 64 deletions packages/plugin-client-drizzle/src/generate.ts

This file was deleted.

79 changes: 79 additions & 0 deletions packages/plugin-client-drizzle/src/http/driver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import {
DefaultLogger,
DrizzleConfig,
ExtractTablesWithRelations,
Logger,
RelationalSchemaConfig,
TablesRelationalConfig,
createTableRelationsHelpers,
entityKind,
extractTablesRelationalConfig
} from 'drizzle-orm';
import { XataHttpSession, type XataHttpClient, type XataHttpQueryResultHKT } from './session.js';
import { PgDatabase, PgDialect } from 'drizzle-orm/pg-core';

export interface XataDriverOptions {
logger?: Logger;
}

export class XataHttpDriver {
static readonly [entityKind]: string = 'XataDriver';

constructor(private client: XataHttpClient, private dialect: PgDialect, private options: XataDriverOptions = {}) {
this.initMappers();
}

createSession(
schema: RelationalSchemaConfig<TablesRelationalConfig> | undefined
): XataHttpSession<Record<string, unknown>, TablesRelationalConfig> {
return new XataHttpSession(this.client, this.dialect, schema, {
logger: this.options.logger
});
}

initMappers() {
// TODO: Add custom type parsers
}
}

export class XataHttpDatabase<TSchema extends Record<string, unknown> = Record<string, never>> extends PgDatabase<
XataHttpQueryResultHKT,
TSchema
> {
static readonly [entityKind]: string = 'XataHttpDatabase';

/** @internal */
declare readonly session: XataHttpSession<TSchema, ExtractTablesWithRelations<TSchema>>;
}

export function drizzle<TSchema extends Record<string, unknown> = Record<string, never>>(
client: XataHttpClient,
config: DrizzleConfig<TSchema> = {}
): XataHttpDatabase<TSchema> {
const dialect = new PgDialect();
let logger;
if (config.logger === true) {
logger = new DefaultLogger();
} else if (config.logger !== false) {
logger = config.logger;
}

let schema: RelationalSchemaConfig<TablesRelationalConfig> | undefined;
if (config.schema) {
const tablesConfig = extractTablesRelationalConfig(config.schema, createTableRelationsHelpers);
schema = {
fullSchema: config.schema,
schema: tablesConfig.tables,
tableNamesMap: tablesConfig.tableNamesMap
};
}

const driver = new XataHttpDriver(client, dialect, { logger });
const session = driver.createSession(schema);

return new XataHttpDatabase(
dialect,
session,
schema as RelationalSchemaConfig<ExtractTablesWithRelations<TSchema>> | undefined
);
}
2 changes: 2 additions & 0 deletions packages/plugin-client-drizzle/src/http/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './driver.js';
export * from './session.js';
60 changes: 60 additions & 0 deletions packages/plugin-client-drizzle/src/http/migrator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { MigrationConfig, readMigrationFiles } from 'drizzle-orm/migrator';
import { XataHttpDatabase } from './driver';
import { SQL, sql } from 'drizzle-orm';

/**
* This function reads migrationFolder and execute each unapplied migration and mark it as executed in database
*
* NOTE: The Xata HTTP driver does not support transactions. This means that if any part of a migration fails,
* no rollback will be executed. Currently, you will need to handle unsuccessful migration yourself.
* @param db - drizzle db instance
* @param config - path to migration folder generated by drizzle-kit
*/
export async function migrate<TSchema extends Record<string, unknown>>(
db: XataHttpDatabase<TSchema>,
config: string | MigrationConfig
) {
const migrations = readMigrationFiles(config);
const migrationsTable =
typeof config === 'string' ? '__drizzle_migrations' : config.migrationsTable ?? '__drizzle_migrations';
const migrationsSchema = typeof config === 'string' ? 'drizzle' : config.migrationsSchema ?? 'drizzle';
const migrationTableCreate = sql`
CREATE TABLE IF NOT EXISTS ${sql.identifier(migrationsSchema)}.${sql.identifier(migrationsTable)} (
id SERIAL PRIMARY KEY,
hash text NOT NULL,
created_at bigint
)
`;
await db.session.execute(sql`CREATE SCHEMA IF NOT EXISTS ${sql.identifier(migrationsSchema)}`);
await db.session.execute(migrationTableCreate);

const dbMigrations = await db.session.all<{
id: number;
hash: string;
created_at: string;
}>(
sql`select id, hash, created_at from ${sql.identifier(migrationsSchema)}.${sql.identifier(
migrationsTable
)} order by created_at desc limit 1`
);

const lastDbMigration = dbMigrations[0];
const rowsToInsert: SQL[] = [];
for await (const migration of migrations) {
if (!lastDbMigration || Number(lastDbMigration.created_at) < migration.folderMillis) {
for (const stmt of migration.sql) {
await db.session.execute(sql.raw(stmt));
}

rowsToInsert.push(
sql`insert into ${sql.identifier(migrationsSchema)}.${sql.identifier(
migrationsTable
)} ("hash", "created_at") values(${migration.hash}, ${migration.folderMillis})`
);
}
}

for await (const rowToInsert of rowsToInsert) {
await db.session.execute(rowToInsert);
}
}
Loading
Loading