Merge branch 'feat/db-adapters' of github.com:payloadcms/payload into feat/db-adapters
This commit is contained in:
@@ -1,16 +1,10 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import { eq, sql } from 'drizzle-orm';
|
||||
import {
|
||||
numeric,
|
||||
pgEnum,
|
||||
pgTable,
|
||||
varchar,
|
||||
jsonb,
|
||||
} from 'drizzle-orm/pg-core';
|
||||
import { pushSchema } 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 { configToJSONSchema } from 'payload/dist/utilities/configToJSONSchema';
|
||||
import type { 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';
|
||||
@@ -22,122 +16,109 @@ const migrationsSchema = pgTable('payload_migrations', {
|
||||
schema: jsonb('schema'),
|
||||
});
|
||||
|
||||
export const init: Init = async function init(
|
||||
this: PostgresAdapter,
|
||||
) {
|
||||
export const init: Init = async function init(this: PostgresAdapter) {
|
||||
if (this.payload.config.localization) {
|
||||
this.enums._locales = pgEnum('_locales', this.payload.config.localization.locales as [string, ...string[]]);
|
||||
this.enums._locales = pgEnum(
|
||||
'_locales',
|
||||
this.payload.config.localization.locales as [string, ...string[]],
|
||||
);
|
||||
}
|
||||
|
||||
this.payload.config.collections.forEach(
|
||||
(collection: SanitizedCollectionConfig) => {
|
||||
buildTable({
|
||||
adapter: this,
|
||||
buildRelationships: true,
|
||||
fields: collection.fields,
|
||||
tableName: collection.slug,
|
||||
timestamps: collection.timestamps,
|
||||
});
|
||||
},
|
||||
);
|
||||
this.payload.config.collections.forEach((collection: SanitizedCollectionConfig) => {
|
||||
buildTable({
|
||||
adapter: this,
|
||||
buildRelationships: true,
|
||||
fields: collection.fields,
|
||||
tableName: collection.slug,
|
||||
timestamps: collection.timestamps,
|
||||
});
|
||||
});
|
||||
|
||||
this.payload.config.globals.forEach((global) => {
|
||||
// create global model
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
// TODO:
|
||||
// Run migrate here????
|
||||
// We need to make sure the files in the `migrationsDir` are all executed
|
||||
// Only push schema if not in production
|
||||
if (process.env.NODE_ENV === 'production') return;
|
||||
|
||||
const schema: Record<string, GenericEnum | GenericTable | GenericRelation> = {};
|
||||
const schema: Record<string, GenericEnum | GenericTable | GenericRelation> = {};
|
||||
|
||||
Object.entries(this.tables).forEach(([key, val]) => {
|
||||
schema[`table_${key}`] = val;
|
||||
});
|
||||
Object.entries(this.tables).forEach(([key, val]) => {
|
||||
schema[`table_${key}`] = val;
|
||||
});
|
||||
|
||||
Object.entries(this.relations).forEach(([key, val]) => {
|
||||
schema[`relation_${key}`] = val;
|
||||
});
|
||||
Object.entries(this.relations).forEach(([key, val]) => {
|
||||
schema[`relation_${key}`] = val;
|
||||
});
|
||||
|
||||
Object.entries(this.enums).forEach(([key, val]) => {
|
||||
schema[`enum_${key}`] = val;
|
||||
});
|
||||
Object.entries(this.enums).forEach(([key, val]) => {
|
||||
schema[`enum_${key}`] = val;
|
||||
});
|
||||
|
||||
// This will prompt if clarifications are needed for Drizzle to push new schema
|
||||
const {
|
||||
hasDataLoss,
|
||||
// This will prompt if clarifications are needed for Drizzle to push new schema
|
||||
const { hasDataLoss, warnings, statementsToExecute, apply } = await pushSchema(schema, this.db);
|
||||
|
||||
this.payload.logger.debug({
|
||||
msg: 'Schema push results',
|
||||
hasDataLoss,
|
||||
warnings,
|
||||
statementsToExecute,
|
||||
});
|
||||
|
||||
if (warnings.length) {
|
||||
this.payload.logger.warn({
|
||||
msg: `Warnings detected during schema push: ${warnings.join('\n')}`,
|
||||
warnings,
|
||||
statementsToExecute,
|
||||
apply,
|
||||
} = await pushSchema(schema, this.db);
|
||||
|
||||
this.payload.logger.info({
|
||||
msg: 'Schema push results',
|
||||
hasDataLoss,
|
||||
warnings,
|
||||
statementsToExecute,
|
||||
});
|
||||
|
||||
if (warnings.length) {
|
||||
if (hasDataLoss) {
|
||||
this.payload.logger.warn({
|
||||
msg: `Warnings detected during schema push: ${warnings.join('\n')}`,
|
||||
warnings,
|
||||
msg: 'DATA LOSS WARNING: Possible data loss detected if schema is pushed.',
|
||||
});
|
||||
|
||||
if (hasDataLoss) {
|
||||
this.payload.logger.warn({
|
||||
msg: 'DATA LOSS WARNING: Possible data loss detected if schema is pushed.',
|
||||
});
|
||||
}
|
||||
|
||||
const { confirm: acceptWarnings } = await prompts(
|
||||
{
|
||||
type: 'confirm',
|
||||
name: 'confirm',
|
||||
message: 'Accept warnings and push schema to database?',
|
||||
initial: false,
|
||||
},
|
||||
{
|
||||
onCancel: () => {
|
||||
process.exit(0);
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
// Exit if user does not accept warnings.
|
||||
// Q: Is this the right type of exit for this interaction?
|
||||
if (!acceptWarnings) {
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
const jsonSchema = configToJSONSchema(this.payload.config);
|
||||
const { confirm: acceptWarnings } = await prompts(
|
||||
{
|
||||
type: 'confirm',
|
||||
name: 'confirm',
|
||||
message: 'Accept warnings and push schema to database?',
|
||||
initial: false,
|
||||
},
|
||||
{
|
||||
onCancel: () => {
|
||||
process.exit(0);
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
// This should mirror the generated table definition from schema/build.ts
|
||||
await this.db.execute(sql`CREATE TABLE IF NOT EXISTS "payload_migrations" (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name character varying,
|
||||
batch numeric,
|
||||
schema jsonb,
|
||||
created_at timestamp without time zone DEFAULT now() NOT NULL,
|
||||
updated_at timestamp without time zone DEFAULT now() NOT NULL
|
||||
);`);
|
||||
|
||||
const devPush = await this.db.select().from(migrationsSchema).where(eq(migrationsSchema.batch, '-1'));
|
||||
|
||||
if (!devPush.length) {
|
||||
await this.db.insert(migrationsSchema).values({
|
||||
name: 'dev',
|
||||
batch: '-1',
|
||||
schema: JSON.stringify(jsonSchema),
|
||||
});
|
||||
} else {
|
||||
await this.db.update(migrationsSchema).set({
|
||||
schema: JSON.stringify(jsonSchema),
|
||||
}).where(eq(migrationsSchema.batch, '-1'));
|
||||
// Exit if user does not accept warnings.
|
||||
// Q: Is this the right type of exit for this interaction?
|
||||
if (!acceptWarnings) {
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
await apply();
|
||||
const jsonSchema = configToJSONSchema(this.payload.config);
|
||||
|
||||
await apply();
|
||||
|
||||
const devPush = await this.db
|
||||
.select()
|
||||
.from(migrationsSchema)
|
||||
.where(eq(migrationsSchema.batch, '-1'));
|
||||
|
||||
if (!devPush.length) {
|
||||
await this.db.insert(migrationsSchema).values({
|
||||
name: 'dev',
|
||||
batch: '-1',
|
||||
schema: JSON.stringify(jsonSchema),
|
||||
});
|
||||
} else {
|
||||
await this.db
|
||||
.update(migrationsSchema)
|
||||
.set({
|
||||
schema: JSON.stringify(jsonSchema),
|
||||
})
|
||||
.where(eq(migrationsSchema.batch, '-1'));
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user