feat: drizzle json generation
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
import fs from 'fs';
|
||||
import { sql, eq } from 'drizzle-orm';
|
||||
import { drizzle } from 'drizzle-orm/node-postgres';
|
||||
import type { Connect } from 'payload/dist/database/types';
|
||||
import { Client, Pool } from 'pg';
|
||||
import { pushSchema } from 'drizzle-kit/utils';
|
||||
import { generateDrizzleJson, pushSchema } from 'drizzle-kit/utils';
|
||||
import { configToJSONSchema } from 'payload/dist/utilities/configToJSONSchema';
|
||||
import prompts from 'prompts';
|
||||
|
||||
@@ -23,30 +24,30 @@ export const connect: Connect = async function connect(
|
||||
) {
|
||||
let db: DrizzleDB;
|
||||
|
||||
const schema: Record<string, GenericEnum | GenericTable | GenericRelation> = {};
|
||||
this.schema = {};
|
||||
|
||||
Object.entries(this.tables).forEach(([key, val]) => {
|
||||
schema[`${key}`] = val;
|
||||
this.schema[`${key}`] = val;
|
||||
});
|
||||
|
||||
Object.entries(this.relations).forEach(([key, val]) => {
|
||||
schema[`${key}`] = val;
|
||||
this.schema[`${key}`] = val;
|
||||
});
|
||||
|
||||
Object.entries(this.enums).forEach(([key, val]) => {
|
||||
schema[`${key}`] = val;
|
||||
this.schema[`${key}`] = val;
|
||||
});
|
||||
|
||||
try {
|
||||
if ('pool' in this && this.pool !== false) {
|
||||
const pool = new Pool(this.pool);
|
||||
db = drizzle(pool, { schema });
|
||||
db = drizzle(pool, { schema: this.schema });
|
||||
await pool.connect();
|
||||
}
|
||||
|
||||
if ('client' in this && this.client !== false) {
|
||||
const client = new Client(this.client);
|
||||
db = drizzle(client, { schema });
|
||||
db = drizzle(client, { schema: this.schema });
|
||||
await client.connect();
|
||||
}
|
||||
|
||||
@@ -66,12 +67,11 @@ export const connect: Connect = async function connect(
|
||||
this.payload.logger.info('Connected to Postgres successfully');
|
||||
this.db = db;
|
||||
|
||||
|
||||
// Only push schema if not in production
|
||||
if (process.env.NODE_ENV === 'production') return;
|
||||
|
||||
// This will prompt if clarifications are needed for Drizzle to push new schema
|
||||
const { hasDataLoss, warnings, statementsToExecute, apply } = await pushSchema(schema, this.db);
|
||||
const { hasDataLoss, warnings, statementsToExecute, apply } = await pushSchema(this.schema, this.db);
|
||||
|
||||
this.payload.logger.debug({
|
||||
msg: 'Schema push results',
|
||||
@@ -113,6 +113,20 @@ export const connect: Connect = async function connect(
|
||||
}
|
||||
}
|
||||
|
||||
this.migrationDir = '.migrations';
|
||||
|
||||
// Create drizzle snapshot if it doesn't exist
|
||||
if (!fs.existsSync(`${this.migrationDir}/drizzle-snapshot.json`)) {
|
||||
// Ensure migration dir exists
|
||||
if (!fs.existsSync(this.migrationDir)) {
|
||||
fs.mkdirSync(this.migrationDir);
|
||||
}
|
||||
|
||||
const drizzleJSON = generateDrizzleJson(this.schema);
|
||||
|
||||
fs.writeFileSync(`${this.migrationDir}/drizzle-snapshot.json`, JSON.stringify(drizzleJSON, null, 2));
|
||||
}
|
||||
|
||||
const jsonSchema = configToJSONSchema(this.payload.config);
|
||||
|
||||
await apply();
|
||||
|
||||
@@ -2,11 +2,21 @@
|
||||
import fs from 'fs';
|
||||
import { CreateMigration } from 'payload/dist/database/types';
|
||||
|
||||
import { generateDrizzleJson, generateMigration } from 'drizzle-kit/utils';
|
||||
import { eq } from 'drizzle-orm';
|
||||
import { jsonb, numeric, pgEnum, pgTable, varchar } from 'drizzle-orm/pg-core';
|
||||
import { SanitizedCollectionConfig } from 'payload/dist/collections/config/types';
|
||||
import type { DatabaseAdapter, Init } from 'payload/dist/database/types';
|
||||
import { configToJSONSchema } from 'payload/dist/utilities/configToJSONSchema';
|
||||
import prompts from 'prompts';
|
||||
import { buildTable } from './schema/build';
|
||||
import type { GenericEnum, GenericRelation, GenericTable, PostgresAdapter } from './types';
|
||||
|
||||
const migrationTemplate = `
|
||||
import payload, { Payload } from 'payload';
|
||||
|
||||
export async function up(payload: Payload): Promise<void> {
|
||||
{{SQL}}
|
||||
await payload.db.db.execute(\`{{SQL}}\`);
|
||||
};
|
||||
|
||||
export async function down(payload: Payload): Promise<void> {
|
||||
@@ -14,11 +24,13 @@ export async function down(payload: Payload): Promise<void> {
|
||||
};
|
||||
`;
|
||||
|
||||
export const createMigration: CreateMigration = async function createMigration({
|
||||
export const createMigration: CreateMigration = async function createMigration(
|
||||
this: PostgresAdapter,
|
||||
payload,
|
||||
migrationDir,
|
||||
migrationName,
|
||||
}) {
|
||||
) {
|
||||
payload.logger.info({ msg: 'Creating migration from postgres adapter...' });
|
||||
const dir = migrationDir || '.migrations'; // TODO: Verify path after linking
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir);
|
||||
@@ -33,8 +45,12 @@ export const createMigration: CreateMigration = async function createMigration({
|
||||
const formattedName = migrationName.replace(/\W/g, '_');
|
||||
const fileName = `${timestamp}_${formattedName}.ts`;
|
||||
const filePath = `${dir}/${fileName}`;
|
||||
fs.writeFileSync(filePath, migrationTemplate);
|
||||
payload.logger.info({ msg: `Migration created at ${filePath}` });
|
||||
|
||||
const snapshotJSON = fs.readFileSync(`${dir}/drizzle-snapshot.json`, 'utf8');
|
||||
const drizzleJsonBefore = generateDrizzleJson(JSON.parse(snapshotJSON));
|
||||
const drizzleJsonAfter = generateDrizzleJson(this.schema, drizzleJsonBefore.id);
|
||||
const sqlStatements = await generateMigration(drizzleJsonBefore, drizzleJsonAfter);
|
||||
fs.writeFileSync(filePath, migrationTemplate.replace('{{SQL}}', sqlStatements.join('\n')));
|
||||
|
||||
// TODO:
|
||||
// Get the most recent migration schema from the file system
|
||||
|
||||
@@ -9,6 +9,7 @@ export type DrizzleDB = NodePgDatabase<Record<string, never>>
|
||||
|
||||
type BaseArgs = {
|
||||
migrationDir?: string;
|
||||
migrationName?: string;
|
||||
}
|
||||
|
||||
type ClientArgs = {
|
||||
@@ -49,6 +50,7 @@ export type PostgresAdapter = DatabaseAdapter & Args & {
|
||||
enums: Record<string, GenericEnum>
|
||||
relations: Record<string, GenericRelation>
|
||||
tables: Record<string, GenericTable>
|
||||
schema: Record<string, GenericEnum | GenericTable | GenericRelation>
|
||||
}
|
||||
|
||||
export type PostgresAdapterResult = (args: { payload: Payload }) => PostgresAdapter
|
||||
|
||||
Reference in New Issue
Block a user