@payloadcms/drizzle
Advanced tools
Comparing version 3.0.0-canary.79e92af to 3.0.0-canary.81a972d
@@ -7,3 +7,3 @@ import toSnakeCase from 'to-snake-case'; | ||
const db = this.sessions[await req?.transactionID]?.db || this.drizzle; | ||
const { joins, where } = await buildQuery({ | ||
const { joins, where } = buildQuery({ | ||
adapter: this, | ||
@@ -10,0 +10,0 @@ fields: collectionConfig.fields, |
import type { CreateGlobalVersionArgs, TypeWithID, TypeWithVersion } from 'payload'; | ||
import type { DrizzleAdapter } from './types.js'; | ||
export declare function createGlobalVersion<T extends TypeWithID>(this: DrizzleAdapter, { autosave, globalSlug, req, versionData }: CreateGlobalVersionArgs): Promise<TypeWithVersion<T>>; | ||
export declare function createGlobalVersion<T extends TypeWithID>(this: DrizzleAdapter, { autosave, globalSlug, publishedLocale, req, snapshot, versionData, }: CreateGlobalVersionArgs): Promise<TypeWithVersion<T>>; | ||
//# sourceMappingURL=createGlobalVersion.d.ts.map |
@@ -5,3 +5,3 @@ import { sql } from 'drizzle-orm'; | ||
import { upsertRow } from './upsertRow/index.js'; | ||
export async function createGlobalVersion({ autosave, globalSlug, req = {}, versionData }) { | ||
export async function createGlobalVersion({ autosave, globalSlug, publishedLocale, req = {}, snapshot, versionData }) { | ||
const db = this.sessions[await req?.transactionID]?.db || this.drizzle; | ||
@@ -15,6 +15,8 @@ const global = this.payload.globals.config.find(({ slug })=>slug === globalSlug); | ||
latest: true, | ||
publishedLocale, | ||
snapshot, | ||
version: versionData | ||
}, | ||
db, | ||
fields: buildVersionGlobalFields(global), | ||
fields: buildVersionGlobalFields(this.payload.config, global), | ||
operation: 'create', | ||
@@ -21,0 +23,0 @@ req, |
@@ -9,3 +9,5 @@ import { APIError } from 'payload'; | ||
let defaultTableName = `${prefix}${toSnakeCase(name ?? slug)}`; | ||
if (versions) defaultTableName = `_${defaultTableName}${adapter.versionsSuffix}`; | ||
if (versions) { | ||
defaultTableName = `_${defaultTableName}${adapter.versionsSuffix}`; | ||
} | ||
let customTableNameResult; | ||
@@ -19,3 +21,5 @@ if (!customNameDefinition && target === 'enumName') { | ||
}) : customNameDefinition; | ||
if (versionsCustomName) customTableNameResult = `_${customTableNameResult}${adapter.versionsSuffix}`; | ||
if (versionsCustomName) { | ||
customTableNameResult = `_${customTableNameResult}${adapter.versionsSuffix}`; | ||
} | ||
} | ||
@@ -22,0 +26,0 @@ const result = customTableNameResult || defaultTableName; |
import type { CreateVersionArgs, TypeWithID, TypeWithVersion } from 'payload'; | ||
import type { DrizzleAdapter } from './types.js'; | ||
export declare function createVersion<T extends TypeWithID>(this: DrizzleAdapter, { autosave, collectionSlug, parent, req, versionData, }: CreateVersionArgs<T>): Promise<TypeWithVersion<T>>; | ||
export declare function createVersion<T extends TypeWithID>(this: DrizzleAdapter, { autosave, collectionSlug, parent, publishedLocale, req, snapshot, versionData, }: CreateVersionArgs<T>): Promise<TypeWithVersion<T>>; | ||
//# sourceMappingURL=createVersion.d.ts.map |
@@ -5,3 +5,3 @@ import { sql } from 'drizzle-orm'; | ||
import { upsertRow } from './upsertRow/index.js'; | ||
export async function createVersion({ autosave, collectionSlug, parent, req = {}, versionData }) { | ||
export async function createVersion({ autosave, collectionSlug, parent, publishedLocale, req = {}, snapshot, versionData }) { | ||
const db = this.sessions[await req?.transactionID]?.db || this.drizzle; | ||
@@ -14,13 +14,21 @@ const collection = this.payload.collections[collectionSlug].config; | ||
}; | ||
if (version.id) delete version.id; | ||
if (version.id) { | ||
delete version.id; | ||
} | ||
const data = { | ||
autosave, | ||
latest: true, | ||
parent, | ||
publishedLocale, | ||
snapshot, | ||
version | ||
}; | ||
if ('createdAt' in version) { | ||
data.createdAt = version.createdAt; | ||
} | ||
const result = await upsertRow({ | ||
adapter: this, | ||
data: { | ||
autosave, | ||
latest: true, | ||
parent, | ||
version | ||
}, | ||
data, | ||
db, | ||
fields: buildVersionCollectionFields(collection), | ||
fields: buildVersionCollectionFields(this.payload.config, collection), | ||
operation: 'create', | ||
@@ -35,7 +43,7 @@ req, | ||
sql: sql` | ||
UPDATE ${table} | ||
SET latest = false | ||
WHERE ${table.id} != ${result.id} | ||
AND ${table.parent} = ${parent} | ||
` | ||
UPDATE ${table} | ||
SET latest = false | ||
WHERE ${table.id} != ${result.id} | ||
AND ${table.parent} = ${parent} | ||
` | ||
}); | ||
@@ -42,0 +50,0 @@ } |
@@ -7,3 +7,3 @@ import { eq } from 'drizzle-orm'; | ||
import { transform } from './transform/read/index.js'; | ||
export const deleteOne = async function deleteOne({ collection: collectionSlug, req = {}, where: whereArg }) { | ||
export const deleteOne = async function deleteOne({ collection: collectionSlug, joins: joinQuery, req = {}, where: whereArg }) { | ||
const db = this.sessions[await req?.transactionID]?.db || this.drizzle; | ||
@@ -13,3 +13,3 @@ const collection = this.payload.collections[collectionSlug].config; | ||
let docToDelete; | ||
const { joins, selectFields, where } = await buildQuery({ | ||
const { joins, selectFields, where } = buildQuery({ | ||
adapter: this, | ||
@@ -46,2 +46,3 @@ fields: collection.fields, | ||
fields: collection.fields, | ||
joinQuery, | ||
tableName | ||
@@ -56,3 +57,4 @@ }); | ||
data: docToDelete, | ||
fields: collection.fields | ||
fields: collection.fields, | ||
joinQuery | ||
}); | ||
@@ -59,0 +61,0 @@ await this.deleteWhere({ |
@@ -9,3 +9,3 @@ import { inArray } from 'drizzle-orm'; | ||
const tableName = this.tableNameMap.get(`_${toSnakeCase(collectionConfig.slug)}${this.versionsSuffix}`); | ||
const fields = buildVersionCollectionFields(collectionConfig); | ||
const fields = buildVersionCollectionFields(this.payload.config, collectionConfig); | ||
const { docs } = await findMany({ | ||
@@ -12,0 +12,0 @@ adapter: this, |
// eslint-disable-next-line @typescript-eslint/require-await | ||
export const destroy = async function destroy() { | ||
if (this.enums) this.enums = {}; | ||
if (this.enums) { | ||
this.enums = {}; | ||
} | ||
this.schema = {}; | ||
@@ -5,0 +7,0 @@ this.tables = {}; |
import toSnakeCase from 'to-snake-case'; | ||
import { findMany } from './find/findMany.js'; | ||
export const find = async function find({ collection, limit, locale, page = 1, pagination, req = {}, sort: sortArg, where }) { | ||
export const find = async function find({ collection, joins, limit, locale, page = 1, pagination, req = {}, sort: sortArg, where }) { | ||
const collectionConfig = this.payload.collections[collection].config; | ||
@@ -10,2 +10,3 @@ const sort = typeof sortArg === 'string' ? sortArg : collectionConfig.defaultSort; | ||
fields: collectionConfig.fields, | ||
joins, | ||
limit, | ||
@@ -12,0 +13,0 @@ locale, |
import type { DBQueryConfig } from 'drizzle-orm'; | ||
import type { Field } from 'payload'; | ||
import type { DrizzleAdapter } from '../types.js'; | ||
import type { Field, JoinQuery } from 'payload'; | ||
import type { BuildQueryJoinAliases, DrizzleAdapter } from '../types.js'; | ||
type BuildFindQueryArgs = { | ||
@@ -8,11 +8,17 @@ adapter: DrizzleAdapter; | ||
fields: Field[]; | ||
joinQuery?: JoinQuery; | ||
/** | ||
* The joins array will be mutated by pushing any joins needed for the where queries of join field joins | ||
*/ | ||
joins?: BuildQueryJoinAliases; | ||
locale?: string; | ||
tableName: string; | ||
}; | ||
export type Result = DBQueryConfig<'many', true, any, any> & { | ||
with?: DBQueryConfig<'many', true, any, any> & { | ||
export type Result = { | ||
with?: { | ||
_locales?: DBQueryConfig<'many', true, any, any>; | ||
}; | ||
}; | ||
export declare const buildFindManyArgs: ({ adapter, depth, fields, tableName, }: BuildFindQueryArgs) => Record<string, unknown>; | ||
} & DBQueryConfig<'many', true, any, any>; | ||
} & DBQueryConfig<'many', true, any, any>; | ||
export declare const buildFindManyArgs: ({ adapter, depth, fields, joinQuery, joins, locale, tableName, }: BuildFindQueryArgs) => Record<string, unknown>; | ||
export {}; | ||
//# sourceMappingURL=buildFindManyArgs.d.ts.map |
import { traverseFields } from './traverseFields.js'; | ||
// Generate the Drizzle query for findMany based on | ||
// a collection field structure | ||
export const buildFindManyArgs = ({ adapter, depth, fields, tableName })=>{ | ||
export const buildFindManyArgs = ({ adapter, depth, fields, joinQuery, joins = [], locale, tableName })=>{ | ||
const result = { | ||
@@ -58,3 +58,7 @@ with: {} | ||
fields, | ||
joinQuery, | ||
joins, | ||
locale, | ||
path: '', | ||
tablePath: '', | ||
topLevelArgs: result, | ||
@@ -61,0 +65,0 @@ topLevelTableName: tableName |
@@ -8,3 +8,3 @@ import type { Field, FindArgs } from 'payload'; | ||
} & Omit<FindArgs, 'collection'>; | ||
export declare const findMany: ({ adapter, fields, limit: limitArg, locale, page, pagination, req, skip, sort, tableName, where: whereArg, }: Args) => Promise<{ | ||
export declare const findMany: ({ adapter, fields, joins: joinQuery, limit: limitArg, locale, page, pagination, req, skip, sort, tableName, where: whereArg, }: Args) => Promise<{ | ||
docs: any; | ||
@@ -11,0 +11,0 @@ hasNextPage: boolean; |
@@ -6,3 +6,3 @@ import { inArray } from 'drizzle-orm'; | ||
import { buildFindManyArgs } from './buildFindManyArgs.js'; | ||
export const findMany = async function find({ adapter, fields, limit: limitArg, locale, page = 1, pagination, req = {}, skip, sort, tableName, where: whereArg }) { | ||
export const findMany = async function find({ adapter, fields, joins: joinQuery, limit: limitArg, locale, page = 1, pagination, req = {}, skip, sort, tableName, where: whereArg }) { | ||
const db = adapter.sessions[await req.transactionID]?.db || adapter.drizzle; | ||
@@ -19,3 +19,3 @@ let limit = limitArg; | ||
} | ||
const { joins, orderBy, selectFields, where } = await buildQuery({ | ||
const { joins, orderBy, selectFields, where } = buildQuery({ | ||
adapter, | ||
@@ -43,2 +43,4 @@ fields, | ||
fields, | ||
joinQuery, | ||
joins, | ||
tableName | ||
@@ -127,3 +129,4 @@ }); | ||
data, | ||
fields | ||
fields, | ||
joinQuery | ||
}); | ||
@@ -130,0 +133,0 @@ }); |
@@ -1,3 +0,3 @@ | ||
import type { Field } from 'payload'; | ||
import type { DrizzleAdapter } from '../types.js'; | ||
import type { Field, JoinQuery } from 'payload'; | ||
import type { BuildQueryJoinAliases, DrizzleAdapter } from '../types.js'; | ||
import type { Result } from './buildFindManyArgs.js'; | ||
@@ -11,8 +11,12 @@ type TraverseFieldArgs = { | ||
fields: Field[]; | ||
joinQuery: JoinQuery; | ||
joins?: BuildQueryJoinAliases; | ||
locale?: string; | ||
path: string; | ||
tablePath: string; | ||
topLevelArgs: Record<string, unknown>; | ||
topLevelTableName: string; | ||
}; | ||
export declare const traverseFields: ({ _locales, adapter, currentArgs, currentTableName, depth, fields, path, topLevelArgs, topLevelTableName, }: TraverseFieldArgs) => Record<string, unknown>; | ||
export declare const traverseFields: ({ _locales, adapter, currentArgs, currentTableName, depth, fields, joinQuery, joins, locale, path, tablePath, topLevelArgs, topLevelTableName, }: TraverseFieldArgs) => Record<string, unknown>; | ||
export {}; | ||
//# sourceMappingURL=traverseFields.d.ts.map |
@@ -1,7 +0,12 @@ | ||
/* eslint-disable no-param-reassign */ import { fieldAffectsData, tabHasName } from 'payload/shared'; | ||
import { fieldAffectsData, fieldIsVirtual, tabHasName } from 'payload/shared'; | ||
import toSnakeCase from 'to-snake-case'; | ||
export const traverseFields = ({ _locales, adapter, currentArgs, currentTableName, depth, fields, path, topLevelArgs, topLevelTableName })=>{ | ||
import { buildOrderBy } from '../queries/buildOrderBy.js'; | ||
import buildQuery from '../queries/buildQuery.js'; | ||
export const traverseFields = ({ _locales, adapter, currentArgs, currentTableName, depth, fields, joinQuery = {}, joins, locale, path, tablePath, topLevelArgs, topLevelTableName })=>{ | ||
fields.forEach((field)=>{ | ||
if (fieldIsVirtual(field)) { | ||
return; | ||
} | ||
// handle simple relationship | ||
if (depth > 0 && (field.type === 'upload' || field.type === 'relationship' && !field.hasMany && typeof field.relationTo === 'string')) { | ||
if (depth > 0 && (field.type === 'upload' || field.type === 'relationship') && !field.hasMany && typeof field.relationTo === 'string') { | ||
if (field.localized) { | ||
@@ -21,3 +26,6 @@ _locales.with[`${path}${field.name}`] = true; | ||
fields: field.fields, | ||
joinQuery, | ||
joins, | ||
path, | ||
tablePath, | ||
topLevelArgs, | ||
@@ -31,2 +39,3 @@ topLevelTableName | ||
const tabPath = tabHasName(tab) ? `${path}${tab.name}_` : path; | ||
const tabTablePath = tabHasName(tab) ? `${tablePath}${toSnakeCase(tab.name)}_` : tablePath; | ||
traverseFields({ | ||
@@ -39,3 +48,6 @@ _locales, | ||
fields: tab.fields, | ||
joinQuery, | ||
joins, | ||
path: tabPath, | ||
tablePath: tabTablePath, | ||
topLevelArgs, | ||
@@ -60,3 +72,3 @@ topLevelTableName | ||
}; | ||
const arrayTableName = adapter.tableNameMap.get(`${currentTableName}_${path}${toSnakeCase(field.name)}`); | ||
const arrayTableName = adapter.tableNameMap.get(`${currentTableName}_${tablePath}${toSnakeCase(field.name)}`); | ||
const arrayTableNameWithLocales = `${arrayTableName}${adapter.localesSuffix}`; | ||
@@ -80,3 +92,5 @@ if (adapter.tables[arrayTableNameWithLocales]) { | ||
fields: field.fields, | ||
joinQuery, | ||
path: '', | ||
tablePath: '', | ||
topLevelArgs, | ||
@@ -131,3 +145,5 @@ topLevelTableName | ||
fields: block.fields, | ||
joinQuery, | ||
path: '', | ||
tablePath: '', | ||
topLevelArgs, | ||
@@ -140,14 +156,73 @@ topLevelTableName | ||
case 'group': | ||
traverseFields({ | ||
_locales, | ||
adapter, | ||
currentArgs, | ||
currentTableName, | ||
depth, | ||
fields: field.fields, | ||
path: `${path}${field.name}_`, | ||
topLevelArgs, | ||
topLevelTableName | ||
}); | ||
break; | ||
{ | ||
traverseFields({ | ||
_locales, | ||
adapter, | ||
currentArgs, | ||
currentTableName, | ||
depth, | ||
fields: field.fields, | ||
joinQuery, | ||
joins, | ||
path: `${path}${field.name}_`, | ||
tablePath: `${tablePath}${toSnakeCase(field.name)}_`, | ||
topLevelArgs, | ||
topLevelTableName | ||
}); | ||
break; | ||
} | ||
case 'join': | ||
{ | ||
// when `joinsQuery` is false, do not join | ||
if (joinQuery === false) { | ||
break; | ||
} | ||
const { limit: limitArg = 10, sort, where } = joinQuery[`${path.replaceAll('_', '.')}${field.name}`] || {}; | ||
let limit = limitArg; | ||
if (limit !== 0) { | ||
// get an additional document and slice it later to determine if there is a next page | ||
limit += 1; | ||
} | ||
const fields = adapter.payload.collections[field.collection].config.fields; | ||
const joinTableName = `${adapter.tableNameMap.get(toSnakeCase(field.collection))}${field.localized && adapter.payload.config.localization ? adapter.localesSuffix : ''}`; | ||
const selectFields = {}; | ||
const orderBy = buildOrderBy({ | ||
adapter, | ||
fields, | ||
joins: [], | ||
locale, | ||
selectFields, | ||
sort, | ||
tableName: joinTableName | ||
}); | ||
const withJoin = { | ||
columns: selectFields, | ||
orderBy: ()=>[ | ||
orderBy.order(orderBy.column) | ||
] | ||
}; | ||
if (limit) { | ||
withJoin.limit = limit; | ||
} | ||
if (field.localized) { | ||
withJoin.columns._locale = true; | ||
withJoin.columns._parentID = true; | ||
} else { | ||
withJoin.columns.id = true; | ||
} | ||
if (where) { | ||
const { where: joinWhere } = buildQuery({ | ||
adapter, | ||
fields, | ||
joins, | ||
locale, | ||
sort, | ||
tableName: joinTableName, | ||
where | ||
}); | ||
withJoin.where = ()=>joinWhere; | ||
} | ||
currentArgs.with[`${path.replaceAll('.', '_')}${field.name}`] = withJoin; | ||
break; | ||
} | ||
default: | ||
@@ -154,0 +229,0 @@ { |
@@ -8,3 +8,3 @@ import { buildVersionGlobalFields } from 'payload'; | ||
const tableName = this.tableNameMap.get(`_${toSnakeCase(globalConfig.slug)}${this.versionsSuffix}`); | ||
const fields = buildVersionGlobalFields(globalConfig); | ||
const fields = buildVersionGlobalFields(this.payload.config, globalConfig); | ||
return findMany({ | ||
@@ -11,0 +11,0 @@ adapter: this, |
@@ -22,3 +22,5 @@ import fs from 'fs'; | ||
// Use arg if provided | ||
if (migrationDir) return migrationDir; | ||
if (migrationDir) { | ||
return migrationDir; | ||
} | ||
// Check other common locations | ||
@@ -25,0 +27,0 @@ if (fs.existsSync(srcDir)) { |
import type { FindOneArgs, TypeWithID } from 'payload'; | ||
import type { DrizzleAdapter } from './types.js'; | ||
export declare function findOne<T extends TypeWithID>(this: DrizzleAdapter, { collection, locale, req, where }: FindOneArgs): Promise<T>; | ||
export declare function findOne<T extends TypeWithID>(this: DrizzleAdapter, { collection, joins, locale, req, where }: FindOneArgs): Promise<T>; | ||
//# sourceMappingURL=findOne.d.ts.map |
import toSnakeCase from 'to-snake-case'; | ||
import { findMany } from './find/findMany.js'; | ||
export async function findOne({ collection, locale, req = {}, where }) { | ||
export async function findOne({ collection, joins, locale, req = {}, where }) { | ||
const collectionConfig = this.payload.collections[collection].config; | ||
@@ -9,2 +9,3 @@ const tableName = this.tableNameMap.get(toSnakeCase(collectionConfig.slug)); | ||
fields: collectionConfig.fields, | ||
joins, | ||
limit: 1, | ||
@@ -11,0 +12,0 @@ locale, |
@@ -8,3 +8,3 @@ import { buildVersionCollectionFields } from 'payload'; | ||
const tableName = this.tableNameMap.get(`_${toSnakeCase(collectionConfig.slug)}${this.versionsSuffix}`); | ||
const fields = buildVersionCollectionFields(collectionConfig); | ||
const fields = buildVersionCollectionFields(this.payload.config, collectionConfig); | ||
return findMany({ | ||
@@ -11,0 +11,0 @@ adapter: this, |
@@ -90,2 +90,3 @@ import { commitTransaction, initTransaction, killTransaction, readMigrationFiles } from 'payload'; | ||
}); | ||
process.exit(1); | ||
} | ||
@@ -92,0 +93,0 @@ } |
@@ -1,2 +0,2 @@ | ||
/* eslint-disable no-restricted-syntax, no-await-in-loop */ import { commitTransaction, getMigrations, initTransaction, killTransaction, readMigrationFiles } from 'payload'; | ||
import { commitTransaction, getMigrations, initTransaction, killTransaction, readMigrationFiles } from 'payload'; | ||
import { migrationTableExists } from './utilities/migrationTableExists.js'; | ||
@@ -3,0 +3,0 @@ import { parseError } from './utilities/parseError.js'; |
@@ -71,2 +71,3 @@ import { commitTransaction, initTransaction, killTransaction, readMigrationFiles } from 'payload'; | ||
}); | ||
process.exit(1); | ||
} | ||
@@ -73,0 +74,0 @@ } |
@@ -1,2 +0,2 @@ | ||
/* eslint-disable no-restricted-syntax, no-await-in-loop */ import { commitTransaction, getMigrations, initTransaction, killTransaction, readMigrationFiles } from 'payload'; | ||
import { commitTransaction, getMigrations, initTransaction, killTransaction, readMigrationFiles } from 'payload'; | ||
import { migrationTableExists } from './utilities/migrationTableExists.js'; | ||
@@ -98,2 +98,3 @@ import { parseError } from './utilities/parseError.js'; | ||
}); | ||
process.exit(1); | ||
} | ||
@@ -100,0 +101,0 @@ } |
@@ -1,2 +0,2 @@ | ||
/* eslint-disable no-restricted-syntax, no-await-in-loop */ import { commitTransaction, getMigrations, initTransaction, killTransaction, readMigrationFiles } from 'payload'; | ||
import { commitTransaction, getMigrations, initTransaction, killTransaction, readMigrationFiles } from 'payload'; | ||
import { migrationTableExists } from './utilities/migrationTableExists.js'; | ||
@@ -52,3 +52,5 @@ /** | ||
let msg = `Error running migration ${migrationFile.name}.`; | ||
if (err instanceof Error) msg += ` ${err.message}`; | ||
if (err instanceof Error) { | ||
msg += ` ${err.message}`; | ||
} | ||
await killTransaction(req); | ||
@@ -55,0 +57,0 @@ payload.logger.error({ |
@@ -30,3 +30,2 @@ import { Table } from 'console-table-printer'; | ||
Name: migration.name, | ||
// eslint-disable-next-line perfectionist/sort-objects | ||
Batch: existingMigration?.batch, | ||
@@ -33,0 +32,0 @@ Ran: existingMigration ? 'Yes' : 'No' |
@@ -1,2 +0,2 @@ | ||
import { sql } from 'drizzle-orm'; | ||
import { count, sql } from 'drizzle-orm'; | ||
import { chainMethods } from '../find/chainMethods.js'; | ||
@@ -17,4 +17,4 @@ export const countDistinct = async function countDistinct({ db, joins, tableName, where }) { | ||
query: db.select({ | ||
count: sql`count | ||
(DISTINCT ${this.tables[tableName].id})` | ||
count: joins.length > 0 ? sql`count | ||
(DISTINCT ${this.tables[tableName].id})`.mapWith(Number) : count() | ||
}).from(this.tables[tableName]).where(where) | ||
@@ -21,0 +21,0 @@ }); |
@@ -9,3 +9,5 @@ import { formatJSONPathSegment } from './formatJSONPathSegment.js'; | ||
const formattedSegment = formatJSONPathSegment(segment); | ||
if (i + 1 === segments.length) return `${res}->>${formattedSegment}`; | ||
if (i + 1 === segments.length) { | ||
return `${res}->>${formattedSegment}`; | ||
} | ||
return `${res}->${formattedSegment}`; | ||
@@ -12,0 +14,0 @@ }, ''); |
@@ -81,2 +81,3 @@ import fs from 'fs'; | ||
imports, | ||
packageName: payload.db.packageName, | ||
upSQL: upSQL || ` // Migration code` | ||
@@ -83,0 +84,0 @@ })); |
import type { MigrationTemplateArgs } from 'payload'; | ||
export declare const indent: (text: string) => string; | ||
export declare const getMigrationTemplate: ({ downSQL, imports, upSQL, }: MigrationTemplateArgs) => string; | ||
export declare const getMigrationTemplate: ({ downSQL, imports, packageName, upSQL, }: MigrationTemplateArgs) => string; | ||
//# sourceMappingURL=getMigrationTemplate.d.ts.map |
export const indent = (text)=>text.split('\n').map((line)=>` ${line}`).join('\n'); | ||
export const getMigrationTemplate = ({ downSQL, imports, upSQL })=>`import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres' | ||
export const getMigrationTemplate = ({ downSQL, imports, packageName, upSQL })=>`import { MigrateUpArgs, MigrateDownArgs, sql } from '${packageName}' | ||
${imports ? `${imports}\n` : ''} | ||
@@ -4,0 +4,0 @@ export async function up({ payload, req }: MigrateUpArgs): Promise<void> { |
@@ -48,3 +48,3 @@ import { uniqueIndex } from 'drizzle-orm/pg-core'; | ||
const versionsTableName = this.tableNameMap.get(`_${toSnakeCase(collection.slug)}${this.versionsSuffix}`); | ||
const versionFields = buildVersionCollectionFields(collection); | ||
const versionFields = buildVersionCollectionFields(this.payload.config, collection); | ||
buildTable({ | ||
@@ -82,3 +82,3 @@ adapter: this, | ||
}); | ||
const versionFields = buildVersionGlobalFields(global); | ||
const versionFields = buildVersionGlobalFields(this.payload.config, global); | ||
buildTable({ | ||
@@ -85,0 +85,0 @@ adapter: this, |
@@ -17,4 +17,4 @@ import type { PgColumnBuilder } from 'drizzle-orm/pg-core'; | ||
fields: Field[]; | ||
rootRelationships?: Set<string>; | ||
rootRelationsToBuild?: RelationMap; | ||
rootRelationships?: Set<string>; | ||
rootTableIDColType?: string; | ||
@@ -25,4 +25,12 @@ rootTableName?: string; | ||
versions: boolean; | ||
/** | ||
* Tracks whether or not this table is built | ||
* from the result of a localized array or block field at some point | ||
*/ | ||
withinLocalizedArrayOrBlock?: boolean; | ||
}; | ||
type Result = { | ||
hasLocalizedManyNumberField: boolean; | ||
hasLocalizedManyTextField: boolean; | ||
hasLocalizedRelationshipField: boolean; | ||
hasManyNumberField: 'index' | boolean; | ||
@@ -32,4 +40,4 @@ hasManyTextField: 'index' | boolean; | ||
}; | ||
export declare const buildTable: ({ adapter, baseColumns, baseExtraConfig, disableNotNull, disableUnique, fields, rootRelationsToBuild, rootRelationships, rootTableIDColType, rootTableName: incomingRootTableName, tableName, timestamps, versions, }: Args) => Result; | ||
export declare const buildTable: ({ adapter, baseColumns, baseExtraConfig, disableNotNull, disableUnique, fields, rootRelationships, rootRelationsToBuild, rootTableIDColType, rootTableName: incomingRootTableName, tableName, timestamps, versions, withinLocalizedArrayOrBlock, }: Args) => Result; | ||
export {}; | ||
//# sourceMappingURL=build.d.ts.map |
@@ -8,3 +8,3 @@ import { relations } from 'drizzle-orm'; | ||
import { traverseFields } from './traverseFields.js'; | ||
export const buildTable = ({ adapter, baseColumns = {}, baseExtraConfig = {}, disableNotNull, disableUnique = false, fields, rootRelationsToBuild, rootRelationships, rootTableIDColType, rootTableName: incomingRootTableName, tableName, timestamps, versions })=>{ | ||
export const buildTable = ({ adapter, baseColumns = {}, baseExtraConfig = {}, disableNotNull, disableUnique = false, fields, rootRelationships, rootRelationsToBuild, rootTableIDColType, rootTableName: incomingRootTableName, tableName, timestamps, versions, withinLocalizedArrayOrBlock })=>{ | ||
const isRoot = !incomingRootTableName; | ||
@@ -40,8 +40,9 @@ const rootTableName = incomingRootTableName || tableName; | ||
parentTableName: tableName, | ||
relationships, | ||
relationsToBuild, | ||
relationships, | ||
rootRelationsToBuild: rootRelationsToBuild || relationsToBuild, | ||
rootTableIDColType: rootTableIDColType || idColType, | ||
rootTableName, | ||
versions | ||
versions, | ||
withinLocalizedArrayOrBlock | ||
}); | ||
@@ -51,6 +52,7 @@ // split the relationsToBuild by localized and non-localized | ||
const nonLocalizedRelations = new Map(); | ||
relationsToBuild.forEach(({ type, localized, target }, key)=>{ | ||
relationsToBuild.forEach(({ type, localized, relationName, target }, key)=>{ | ||
const map = localized ? localizedRelations : nonLocalizedRelations; | ||
map.set(key, { | ||
type, | ||
relationName, | ||
target | ||
@@ -253,4 +255,8 @@ }); | ||
const relatedCollectionCustomIDType = adapter.payload.collections[relationshipConfig.slug]?.customIDType; | ||
if (relatedCollectionCustomIDType === 'number') colType = 'numeric'; | ||
if (relatedCollectionCustomIDType === 'text') colType = 'varchar'; | ||
if (relatedCollectionCustomIDType === 'number') { | ||
colType = 'numeric'; | ||
} | ||
if (relatedCollectionCustomIDType === 'text') { | ||
colType = 'varchar'; | ||
} | ||
relationshipColumns[`${relationTo}ID`] = parentIDColumnMap[colType](`${formattedRelationTo}_id`); | ||
@@ -326,3 +332,3 @@ relationExtraConfig[`${relationTo}IdFk`] = (cols)=>foreignKey({ | ||
const result = {}; | ||
nonLocalizedRelations.forEach(({ type, target }, key)=>{ | ||
nonLocalizedRelations.forEach(({ type, relationName, target }, key)=>{ | ||
if (type === 'one') { | ||
@@ -341,3 +347,3 @@ result[key] = one(adapter.tables[target], { | ||
result[key] = many(adapter.tables[target], { | ||
relationName: key | ||
relationName: relationName || key | ||
}); | ||
@@ -369,2 +375,5 @@ } | ||
return { | ||
hasLocalizedManyNumberField, | ||
hasLocalizedManyTextField, | ||
hasLocalizedRelationshipField, | ||
hasManyNumberField, | ||
@@ -371,0 +380,0 @@ hasManyTextField, |
@@ -13,3 +13,5 @@ import { index, uniqueIndex } from 'drizzle-orm/pg-core'; | ||
} | ||
if (unique) return uniqueIndex(`${tableName}_${columnName}_idx`).on(columns[0], ...columns.slice(1)); | ||
if (unique) { | ||
return uniqueIndex(`${tableName}_${columnName}_idx`).on(columns[0], ...columns.slice(1)); | ||
} | ||
return index(`${tableName}_${columnName}_idx`).on(columns[0], ...columns.slice(1)); | ||
@@ -16,0 +18,0 @@ }; |
@@ -18,4 +18,4 @@ import type { IndexBuilder, PgColumnBuilder } from 'drizzle-orm/pg-core'; | ||
parentTableName: string; | ||
relationships: Set<string>; | ||
relationsToBuild: RelationMap; | ||
relationships: Set<string>; | ||
rootRelationsToBuild?: RelationMap; | ||
@@ -25,2 +25,7 @@ rootTableIDColType: string; | ||
versions: boolean; | ||
/** | ||
* Tracks whether or not this table is built | ||
* from the result of a localized array or block field at some point | ||
*/ | ||
withinLocalizedArrayOrBlock?: boolean; | ||
}; | ||
@@ -35,4 +40,4 @@ type Result = { | ||
}; | ||
export declare const traverseFields: ({ adapter, columnPrefix, columns, disableNotNull, disableUnique, fieldPrefix, fields, forceLocalized, indexes, localesColumns, localesIndexes, newTableName, parentTableName, relationsToBuild, relationships, rootRelationsToBuild, rootTableIDColType, rootTableName, versions, }: Args) => Result; | ||
export declare const traverseFields: ({ adapter, columnPrefix, columns, disableNotNull, disableUnique, fieldPrefix, fields, forceLocalized, indexes, localesColumns, localesIndexes, newTableName, parentTableName, relationships, relationsToBuild, rootRelationsToBuild, rootTableIDColType, rootTableName, versions, withinLocalizedArrayOrBlock, }: Args) => Result; | ||
export {}; | ||
//# sourceMappingURL=traverseFields.d.ts.map |
import { relations } from 'drizzle-orm'; | ||
import { PgNumericBuilder, PgUUIDBuilder, PgVarcharBuilder, boolean, foreignKey, index, integer, jsonb, numeric, text, timestamp, varchar } from 'drizzle-orm/pg-core'; | ||
import { boolean, foreignKey, index, integer, jsonb, numeric, PgNumericBuilder, PgUUIDBuilder, PgVarcharBuilder, text, timestamp, varchar } from 'drizzle-orm/pg-core'; | ||
import { InvalidConfiguration } from 'payload'; | ||
import { fieldAffectsData, optionIsObject } from 'payload/shared'; | ||
import { fieldAffectsData, fieldIsVirtual, optionIsObject } from 'payload/shared'; | ||
import toSnakeCase from 'to-snake-case'; | ||
@@ -14,3 +14,3 @@ import { createTableName } from '../../createTableName.js'; | ||
import { withDefault } from './withDefault.js'; | ||
export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull, disableUnique = false, fieldPrefix, fields, forceLocalized, indexes, localesColumns, localesIndexes, newTableName, parentTableName, relationsToBuild, relationships, rootRelationsToBuild, rootTableIDColType, rootTableName, versions })=>{ | ||
export const traverseFields = ({ adapter, columnPrefix, columns, disableNotNull, disableUnique = false, fieldPrefix, fields, forceLocalized, indexes, localesColumns, localesIndexes, newTableName, parentTableName, relationships, relationsToBuild, rootRelationsToBuild, rootTableIDColType, rootTableName, versions, withinLocalizedArrayOrBlock })=>{ | ||
const throwValidationError = true; | ||
@@ -24,7 +24,18 @@ let hasLocalizedField = false; | ||
let parentIDColType = 'integer'; | ||
if (columns.id instanceof PgUUIDBuilder) parentIDColType = 'uuid'; | ||
if (columns.id instanceof PgNumericBuilder) parentIDColType = 'numeric'; | ||
if (columns.id instanceof PgVarcharBuilder) parentIDColType = 'varchar'; | ||
if (columns.id instanceof PgUUIDBuilder) { | ||
parentIDColType = 'uuid'; | ||
} | ||
if (columns.id instanceof PgNumericBuilder) { | ||
parentIDColType = 'numeric'; | ||
} | ||
if (columns.id instanceof PgVarcharBuilder) { | ||
parentIDColType = 'varchar'; | ||
} | ||
fields.forEach((field)=>{ | ||
if ('name' in field && field.name === 'id') return; | ||
if ('name' in field && field.name === 'id') { | ||
return; | ||
} | ||
if (fieldIsVirtual(field)) { | ||
return; | ||
} | ||
let columnName; | ||
@@ -61,3 +72,6 @@ let fieldName; | ||
targetIndexes[`${newTableName}_${field.name}Idx`] = createIndex({ | ||
name: fieldName, | ||
name: field.localized ? [ | ||
fieldName, | ||
'_locale' | ||
] : fieldName, | ||
columnName, | ||
@@ -73,3 +87,4 @@ tableName: newTableName, | ||
if (field.hasMany) { | ||
if (field.localized) { | ||
const isLocalized = Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock || forceLocalized; | ||
if (isLocalized) { | ||
hasLocalizedManyTextField = true; | ||
@@ -100,3 +115,4 @@ } | ||
if (field.hasMany) { | ||
if (field.localized) { | ||
const isLocalized = Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock || forceLocalized; | ||
if (isLocalized) { | ||
hasLocalizedManyNumberField = true; | ||
@@ -180,3 +196,4 @@ } | ||
}; | ||
if (field.localized) { | ||
const isLocalized = Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock || forceLocalized; | ||
if (isLocalized) { | ||
baseColumns.locale = adapter.enums.enum__locales('locale').notNull(); | ||
@@ -254,7 +271,8 @@ baseExtraConfig.localeIdx = (cols)=>index(`${selectTableName}_locale_idx`).on(cols.locale); | ||
}; | ||
if (field.localized && adapter.payload.config.localization) { | ||
const isLocalized = Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock || forceLocalized; | ||
if (isLocalized) { | ||
baseColumns._locale = adapter.enums.enum__locales('_locale').notNull(); | ||
baseExtraConfig._localeIdx = (cols)=>index(`${arrayTableName}_locale_idx`).on(cols._locale); | ||
} | ||
const { hasManyNumberField: subHasManyNumberField, hasManyTextField: subHasManyTextField, relationsToBuild: subRelationsToBuild } = buildTable({ | ||
const { hasLocalizedManyNumberField: subHasLocalizedManyNumberField, hasLocalizedManyTextField: subHasLocalizedManyTextField, hasLocalizedRelationshipField: subHasLocalizedRelationshipField, hasManyNumberField: subHasManyNumberField, hasManyTextField: subHasManyTextField, relationsToBuild: subRelationsToBuild } = buildTable({ | ||
adapter, | ||
@@ -266,14 +284,28 @@ baseColumns, | ||
fields: disableUnique ? idToUUID(field.fields) : field.fields, | ||
rootRelationships: relationships, | ||
rootRelationsToBuild, | ||
rootRelationships: relationships, | ||
rootTableIDColType, | ||
rootTableName, | ||
tableName: arrayTableName, | ||
versions | ||
versions, | ||
withinLocalizedArrayOrBlock: isLocalized | ||
}); | ||
if (subHasLocalizedManyNumberField) { | ||
hasLocalizedManyNumberField = subHasLocalizedManyNumberField; | ||
} | ||
if (subHasLocalizedRelationshipField) { | ||
hasLocalizedRelationshipField = subHasLocalizedRelationshipField; | ||
} | ||
if (subHasLocalizedManyTextField) { | ||
hasLocalizedManyTextField = subHasLocalizedManyTextField; | ||
} | ||
if (subHasManyTextField) { | ||
if (!hasManyTextField || subHasManyTextField === 'index') hasManyTextField = subHasManyTextField; | ||
if (!hasManyTextField || subHasManyTextField === 'index') { | ||
hasManyTextField = subHasManyTextField; | ||
} | ||
} | ||
if (subHasManyNumberField) { | ||
if (!hasManyNumberField || subHasManyNumberField === 'index') hasManyNumberField = subHasManyNumberField; | ||
if (!hasManyNumberField || subHasManyNumberField === 'index') { | ||
hasManyNumberField = subHasManyNumberField; | ||
} | ||
} | ||
@@ -346,3 +378,2 @@ relationsToBuild.set(fieldName, { | ||
_orderIdx: (cols)=>index(`${blockTableName}_order_idx`).on(cols._order), | ||
_parentIDIdx: (cols)=>index(`${blockTableName}_parent_id_idx`).on(cols._parentID), | ||
_parentIdFk: (cols)=>foreignKey({ | ||
@@ -357,9 +388,11 @@ name: `${blockTableName}_parent_id_fk`, | ||
}).onDelete('cascade'), | ||
_parentIDIdx: (cols)=>index(`${blockTableName}_parent_id_idx`).on(cols._parentID), | ||
_pathIdx: (cols)=>index(`${blockTableName}_path_idx`).on(cols._path) | ||
}; | ||
if (field.localized && adapter.payload.config.localization) { | ||
const isLocalized = Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock || forceLocalized; | ||
if (isLocalized) { | ||
baseColumns._locale = adapter.enums.enum__locales('_locale').notNull(); | ||
baseExtraConfig._localeIdx = (cols)=>index(`${blockTableName}_locale_idx`).on(cols._locale); | ||
} | ||
const { hasManyNumberField: subHasManyNumberField, hasManyTextField: subHasManyTextField, relationsToBuild: subRelationsToBuild } = buildTable({ | ||
const { hasLocalizedManyNumberField: subHasLocalizedManyNumberField, hasLocalizedManyTextField: subHasLocalizedManyTextField, hasLocalizedRelationshipField: subHasLocalizedRelationshipField, hasManyNumberField: subHasManyNumberField, hasManyTextField: subHasManyTextField, relationsToBuild: subRelationsToBuild } = buildTable({ | ||
adapter, | ||
@@ -371,14 +404,28 @@ baseColumns, | ||
fields: disableUnique ? idToUUID(block.fields) : block.fields, | ||
rootRelationships: relationships, | ||
rootRelationsToBuild, | ||
rootRelationships: relationships, | ||
rootTableIDColType, | ||
rootTableName, | ||
tableName: blockTableName, | ||
versions | ||
versions, | ||
withinLocalizedArrayOrBlock: isLocalized | ||
}); | ||
if (subHasLocalizedManyNumberField) { | ||
hasLocalizedManyNumberField = subHasLocalizedManyNumberField; | ||
} | ||
if (subHasLocalizedRelationshipField) { | ||
hasLocalizedRelationshipField = subHasLocalizedRelationshipField; | ||
} | ||
if (subHasLocalizedManyTextField) { | ||
hasLocalizedManyTextField = subHasLocalizedManyTextField; | ||
} | ||
if (subHasManyTextField) { | ||
if (!hasManyTextField || subHasManyTextField === 'index') hasManyTextField = subHasManyTextField; | ||
if (!hasManyTextField || subHasManyTextField === 'index') { | ||
hasManyTextField = subHasManyTextField; | ||
} | ||
} | ||
if (subHasManyNumberField) { | ||
if (!hasManyNumberField || subHasManyNumberField === 'index') hasManyNumberField = subHasManyNumberField; | ||
if (!hasManyNumberField || subHasManyNumberField === 'index') { | ||
hasManyNumberField = subHasManyNumberField; | ||
} | ||
} | ||
@@ -460,15 +507,28 @@ adapter.relations[`relations_${blockTableName}`] = relations(adapter.tables[blockTableName], ({ many, one })=>{ | ||
parentTableName, | ||
relationships, | ||
relationsToBuild, | ||
relationships, | ||
rootRelationsToBuild, | ||
rootTableIDColType, | ||
rootTableName, | ||
versions | ||
versions, | ||
withinLocalizedArrayOrBlock | ||
}); | ||
if (groupHasLocalizedField) hasLocalizedField = true; | ||
if (groupHasLocalizedRelationshipField) hasLocalizedRelationshipField = true; | ||
if (groupHasManyTextField) hasManyTextField = true; | ||
if (groupHasLocalizedManyTextField) hasLocalizedManyTextField = true; | ||
if (groupHasManyNumberField) hasManyNumberField = true; | ||
if (groupHasLocalizedManyNumberField) hasLocalizedManyNumberField = true; | ||
if (groupHasLocalizedField) { | ||
hasLocalizedField = true; | ||
} | ||
if (groupHasLocalizedRelationshipField) { | ||
hasLocalizedRelationshipField = true; | ||
} | ||
if (groupHasManyTextField) { | ||
hasManyTextField = true; | ||
} | ||
if (groupHasLocalizedManyTextField) { | ||
hasLocalizedManyTextField = true; | ||
} | ||
if (groupHasManyNumberField) { | ||
hasManyNumberField = true; | ||
} | ||
if (groupHasLocalizedManyNumberField) { | ||
hasLocalizedManyNumberField = true; | ||
} | ||
break; | ||
@@ -491,15 +551,28 @@ } | ||
parentTableName, | ||
relationships, | ||
relationsToBuild, | ||
relationships, | ||
rootRelationsToBuild, | ||
rootTableIDColType, | ||
rootTableName, | ||
versions | ||
versions, | ||
withinLocalizedArrayOrBlock | ||
}); | ||
if (groupHasLocalizedField) hasLocalizedField = true; | ||
if (groupHasLocalizedRelationshipField) hasLocalizedRelationshipField = true; | ||
if (groupHasManyTextField) hasManyTextField = true; | ||
if (groupHasLocalizedManyTextField) hasLocalizedManyTextField = true; | ||
if (groupHasManyNumberField) hasManyNumberField = true; | ||
if (groupHasLocalizedManyNumberField) hasLocalizedManyNumberField = true; | ||
if (groupHasLocalizedField) { | ||
hasLocalizedField = true; | ||
} | ||
if (groupHasLocalizedRelationshipField) { | ||
hasLocalizedRelationshipField = true; | ||
} | ||
if (groupHasManyTextField) { | ||
hasManyTextField = true; | ||
} | ||
if (groupHasLocalizedManyTextField) { | ||
hasLocalizedManyTextField = true; | ||
} | ||
if (groupHasManyNumberField) { | ||
hasManyNumberField = true; | ||
} | ||
if (groupHasLocalizedManyNumberField) { | ||
hasLocalizedManyNumberField = true; | ||
} | ||
break; | ||
@@ -527,15 +600,28 @@ } | ||
parentTableName, | ||
relationships, | ||
relationsToBuild, | ||
relationships, | ||
rootRelationsToBuild, | ||
rootTableIDColType, | ||
rootTableName, | ||
versions | ||
versions, | ||
withinLocalizedArrayOrBlock | ||
}); | ||
if (tabHasLocalizedField) hasLocalizedField = true; | ||
if (tabHasLocalizedRelationshipField) hasLocalizedRelationshipField = true; | ||
if (tabHasManyTextField) hasManyTextField = true; | ||
if (tabHasLocalizedManyTextField) hasLocalizedManyTextField = true; | ||
if (tabHasManyNumberField) hasManyNumberField = true; | ||
if (tabHasLocalizedManyNumberField) hasLocalizedManyNumberField = true; | ||
if (tabHasLocalizedField) { | ||
hasLocalizedField = true; | ||
} | ||
if (tabHasLocalizedRelationshipField) { | ||
hasLocalizedRelationshipField = true; | ||
} | ||
if (tabHasManyTextField) { | ||
hasManyTextField = true; | ||
} | ||
if (tabHasLocalizedManyTextField) { | ||
hasLocalizedManyTextField = true; | ||
} | ||
if (tabHasManyNumberField) { | ||
hasManyNumberField = true; | ||
} | ||
if (tabHasLocalizedManyNumberField) { | ||
hasLocalizedManyNumberField = true; | ||
} | ||
break; | ||
@@ -561,15 +647,28 @@ } | ||
parentTableName, | ||
relationships, | ||
relationsToBuild, | ||
relationships, | ||
rootRelationsToBuild, | ||
rootTableIDColType, | ||
rootTableName, | ||
versions | ||
versions, | ||
withinLocalizedArrayOrBlock | ||
}); | ||
if (rowHasLocalizedField) hasLocalizedField = true; | ||
if (rowHasLocalizedRelationshipField) hasLocalizedRelationshipField = true; | ||
if (rowHasManyTextField) hasManyTextField = true; | ||
if (rowHasLocalizedManyTextField) hasLocalizedManyTextField = true; | ||
if (rowHasManyNumberField) hasManyNumberField = true; | ||
if (rowHasLocalizedManyNumberField) hasLocalizedManyNumberField = true; | ||
if (rowHasLocalizedField) { | ||
hasLocalizedField = true; | ||
} | ||
if (rowHasLocalizedRelationshipField) { | ||
hasLocalizedRelationshipField = true; | ||
} | ||
if (rowHasManyTextField) { | ||
hasManyTextField = true; | ||
} | ||
if (rowHasLocalizedManyTextField) { | ||
hasLocalizedManyTextField = true; | ||
} | ||
if (rowHasManyNumberField) { | ||
hasManyNumberField = true; | ||
} | ||
if (rowHasLocalizedManyNumberField) { | ||
hasLocalizedManyNumberField = true; | ||
} | ||
break; | ||
@@ -581,3 +680,3 @@ } | ||
field.relationTo.forEach((relation)=>relationships.add(relation)); | ||
} else if (field.type === 'relationship' && field.hasMany) { | ||
} else if (field.hasMany) { | ||
relationships.add(field.relationTo); | ||
@@ -591,4 +690,8 @@ } else { | ||
const relatedCollectionCustomID = relationshipConfig.fields.find((field)=>fieldAffectsData(field) && field.name === 'id'); | ||
if (relatedCollectionCustomID?.type === 'number') colType = 'numeric'; | ||
if (relatedCollectionCustomID?.type === 'text') colType = 'varchar'; | ||
if (relatedCollectionCustomID?.type === 'number') { | ||
colType = 'numeric'; | ||
} | ||
if (relatedCollectionCustomID?.type === 'text') { | ||
colType = 'varchar'; | ||
} | ||
// make the foreign key column for relationship using the correct id column type | ||
@@ -610,6 +713,21 @@ targetTable[fieldName] = parentIDColumnMap[colType](`${columnName}_id`).references(()=>adapter.tables[tableName].id, { | ||
} | ||
if (adapter.payload.config.localization && field.localized) { | ||
if (Boolean(field.localized && adapter.payload.config.localization) || withinLocalizedArrayOrBlock) { | ||
hasLocalizedRelationshipField = true; | ||
} | ||
break; | ||
case 'join': | ||
{ | ||
// fieldName could be 'posts' or 'group_posts' | ||
// using on as the key for the relation | ||
const localized = adapter.payload.config.localization && field.localized; | ||
const target = `${adapter.tableNameMap.get(toSnakeCase(field.collection))}${localized ? adapter.localesSuffix : ''}`; | ||
relationsToBuild.set(fieldName, { | ||
type: 'many', | ||
// joins are not localized on the parent table | ||
localized: false, | ||
relationName: toSnakeCase(field.on), | ||
target | ||
}); | ||
break; | ||
} | ||
default: | ||
@@ -616,0 +734,0 @@ break; |
export const withDefault = (column, field)=>{ | ||
if (typeof field.defaultValue === 'undefined' || typeof field.defaultValue === 'function') return column; | ||
if (typeof field.defaultValue === 'undefined' || typeof field.defaultValue === 'function') { | ||
return column; | ||
} | ||
if (typeof field.defaultValue === 'string' && field.defaultValue.includes("'")) { | ||
@@ -4,0 +6,0 @@ const escapedString = field.defaultValue.replaceAll("'", "''"); |
import type { DrizzleSnapshotJSON } from 'drizzle-kit/api'; | ||
import type { ColumnBaseConfig, ColumnDataType, DrizzleConfig, Relation, Relations, SQL } from 'drizzle-orm'; | ||
import type { NodePgDatabase } from 'drizzle-orm/node-postgres'; | ||
import type { ForeignKeyBuilder, IndexBuilder, PgColumn, PgEnum, PgInsertOnConflictDoUpdateConfig, PgSchema, PgTableWithColumns, UniqueConstraintBuilder, pgEnum } from 'drizzle-orm/pg-core'; | ||
import type { ForeignKeyBuilder, IndexBuilder, PgColumn, PgEnum, pgEnum, PgInsertOnConflictDoUpdateConfig, PgSchema, PgTableWithColumns, UniqueConstraintBuilder } from 'drizzle-orm/pg-core'; | ||
import type { PgTableFn } from 'drizzle-orm/pg-core/table'; | ||
@@ -13,2 +13,3 @@ import type { Payload, PayloadRequest } from 'payload'; | ||
localized: boolean; | ||
relationName?: string; | ||
target: string; | ||
@@ -15,0 +16,0 @@ type: 'many' | 'one'; |
@@ -15,3 +15,3 @@ import type { SQL } from 'drizzle-orm'; | ||
where: Where[]; | ||
}): Promise<SQL[]>; | ||
}): SQL[]; | ||
//# sourceMappingURL=buildAndOrConditions.d.ts.map |
import { parseParams } from './parseParams.js'; | ||
export async function buildAndOrConditions({ adapter, fields, joins, locale, selectFields, tableName, where }) { | ||
export function buildAndOrConditions({ adapter, fields, joins, locale, selectFields, tableName, where }) { | ||
const completedConditions = []; | ||
// Loop over all AND / OR operations and add them to the AND / OR query param | ||
// Operations should come through as an array | ||
// eslint-disable-next-line no-restricted-syntax | ||
for (const condition of where){ | ||
// If the operation is properly formatted as an object | ||
if (typeof condition === 'object') { | ||
// eslint-disable-next-line no-await-in-loop | ||
const result = await parseParams({ | ||
const result = parseParams({ | ||
adapter, | ||
@@ -13,0 +11,0 @@ fields, |
@@ -1,5 +0,4 @@ | ||
import type { SQL } from 'drizzle-orm'; | ||
import type { asc, desc, SQL } from 'drizzle-orm'; | ||
import type { PgTableWithColumns } from 'drizzle-orm/pg-core'; | ||
import type { Field, Where } from 'payload'; | ||
import { asc, desc } from 'drizzle-orm'; | ||
import type { DrizzleAdapter, GenericColumn, GenericTable } from '../types.js'; | ||
@@ -13,2 +12,3 @@ export type BuildQueryJoinAliases = { | ||
fields: Field[]; | ||
joins?: BuildQueryJoinAliases; | ||
locale?: string; | ||
@@ -19,3 +19,3 @@ sort?: string; | ||
}; | ||
type Result = { | ||
export type BuildQueryResult = { | ||
joins: BuildQueryJoinAliases; | ||
@@ -29,4 +29,4 @@ orderBy: { | ||
}; | ||
declare const buildQuery: ({ adapter, fields, locale, sort, tableName, where: incomingWhere, }: BuildQueryArgs) => Promise<Result>; | ||
declare const buildQuery: ({ adapter, fields, joins, locale, sort, tableName, where: incomingWhere, }: BuildQueryArgs) => BuildQueryResult; | ||
export default buildQuery; | ||
//# sourceMappingURL=buildQuery.d.ts.map |
@@ -1,54 +0,19 @@ | ||
import { asc, desc } from 'drizzle-orm'; | ||
import { getTableColumnFromPath } from './getTableColumnFromPath.js'; | ||
import { buildOrderBy } from './buildOrderBy.js'; | ||
import { parseParams } from './parseParams.js'; | ||
const buildQuery = async function buildQuery({ adapter, fields, locale, sort, tableName, where: incomingWhere }) { | ||
const buildQuery = function buildQuery({ adapter, fields, joins = [], locale, sort, tableName, where: incomingWhere }) { | ||
const selectFields = { | ||
id: adapter.tables[tableName].id | ||
}; | ||
const joins = []; | ||
const orderBy = { | ||
column: null, | ||
order: null | ||
}; | ||
if (sort) { | ||
let sortPath; | ||
if (sort[0] === '-') { | ||
sortPath = sort.substring(1); | ||
orderBy.order = desc; | ||
} else { | ||
sortPath = sort; | ||
orderBy.order = asc; | ||
} | ||
try { | ||
const { columnName: sortTableColumnName, table: sortTable } = getTableColumnFromPath({ | ||
adapter, | ||
collectionPath: sortPath, | ||
fields, | ||
joins, | ||
locale, | ||
pathSegments: sortPath.replace(/__/g, '.').split('.'), | ||
selectFields, | ||
tableName, | ||
value: sortPath | ||
}); | ||
orderBy.column = sortTable?.[sortTableColumnName]; | ||
} catch (err) { | ||
// continue | ||
} | ||
} | ||
if (!orderBy?.column) { | ||
orderBy.order = desc; | ||
const createdAt = adapter.tables[tableName]?.createdAt; | ||
if (createdAt) { | ||
orderBy.column = createdAt; | ||
} else { | ||
orderBy.column = adapter.tables[tableName].id; | ||
} | ||
} | ||
if (orderBy.column) { | ||
selectFields.sort = orderBy.column; | ||
} | ||
const orderBy = buildOrderBy({ | ||
adapter, | ||
fields, | ||
joins, | ||
locale, | ||
selectFields, | ||
sort, | ||
tableName | ||
}); | ||
let where; | ||
if (incomingWhere && Object.keys(incomingWhere).length > 0) { | ||
where = await parseParams({ | ||
where = parseParams({ | ||
adapter, | ||
@@ -55,0 +20,0 @@ fields, |
import type { SQL } from 'drizzle-orm'; | ||
import type { PgTableWithColumns } from 'drizzle-orm/pg-core'; | ||
import type { SQLiteTableWithColumns } from 'drizzle-orm/sqlite-core'; | ||
import type { Field, FieldAffectingData, TabAsField } from 'payload'; | ||
import { type PgTableWithColumns } from 'drizzle-orm/pg-core'; | ||
import type { DrizzleAdapter, GenericColumn } from '../types.js'; | ||
@@ -14,2 +14,6 @@ import type { BuildQueryJoinAliases } from './buildQuery.js'; | ||
columnName?: string; | ||
columns?: { | ||
idType: 'number' | 'text' | 'uuid'; | ||
rawColumn: SQL<unknown>; | ||
}[]; | ||
constraints: Constraint[]; | ||
@@ -46,3 +50,3 @@ field: FieldAffectingData; | ||
/** | ||
* Transforms path to table and column name | ||
* Transforms path to table and column name or to a list of OR columns | ||
* Adds tables to `join` | ||
@@ -49,0 +53,0 @@ * @returns TableColumn |
@@ -5,5 +5,7 @@ import { and, eq, like, sql } from 'drizzle-orm'; | ||
import toSnakeCase from 'to-snake-case'; | ||
import { validate as uuidValidate } from 'uuid'; | ||
import { isPolymorphicRelationship } from '../utilities/isPolymorphicRelationship.js'; | ||
import { getTableAlias } from './getTableAlias.js'; | ||
/** | ||
* Transforms path to table and column name | ||
* Transforms path to table and column name or to a list of OR columns | ||
* Adds tables to `join` | ||
@@ -181,6 +183,6 @@ * @returns TableColumn | ||
} | ||
newTableName = `${tableName}_${tableType}`; | ||
newTableName = `${rootTableName}_${tableType}`; | ||
const joinConstraints = [ | ||
eq(adapter.tables[tableName].id, adapter.tables[newTableName].parent), | ||
eq(adapter.tables[newTableName].path, `${constraintPath}${field.name}`) | ||
eq(adapter.tables[rootTableName].id, adapter.tables[newTableName].parent), | ||
like(adapter.tables[newTableName].path, `${constraintPath}${field.name}`) | ||
]; | ||
@@ -217,6 +219,7 @@ if (locale && field.localized && adapter.payload.config.localization) { | ||
newTableName = adapter.tableNameMap.get(`${tableName}_${tableNameSuffix}${toSnakeCase(field.name)}`); | ||
const arrayParentTable = aliasTable || adapter.tables[tableName]; | ||
constraintPath = `${constraintPath}${field.name}.%.`; | ||
if (locale && field.localized && adapter.payload.config.localization) { | ||
joins.push({ | ||
condition: and(eq(adapter.tables[tableName].id, adapter.tables[newTableName]._parentID), eq(adapter.tables[newTableName]._locale, locale)), | ||
condition: and(eq(arrayParentTable.id, adapter.tables[newTableName]._parentID), eq(adapter.tables[newTableName]._locale, locale)), | ||
table: adapter.tables[newTableName] | ||
@@ -233,3 +236,3 @@ }); | ||
joins.push({ | ||
condition: eq(adapter.tables[tableName].id, adapter.tables[newTableName]._parentID), | ||
condition: eq(arrayParentTable.id, adapter.tables[newTableName]._parentID), | ||
table: adapter.tables[newTableName] | ||
@@ -356,3 +359,3 @@ }); | ||
const newCollectionPath = pathSegments.slice(1).join('.'); | ||
if (Array.isArray(field.relationTo) || field.type === 'relationship' && field.hasMany) { | ||
if (Array.isArray(field.relationTo) || field.hasMany) { | ||
let relationshipFields; | ||
@@ -408,16 +411,39 @@ const relationTableName = `${rootTableName}${adapter.relationshipsSuffix}`; | ||
} else if (newCollectionPath === 'value') { | ||
const tableColumnsNames = field.relationTo.map((relationTo)=>{ | ||
const hasCustomCollectionWithCustomID = field.relationTo.some((relationTo)=>!!adapter.payload.collections[relationTo].customIDType); | ||
const columns = field.relationTo.map((relationTo)=>{ | ||
let idType = adapter.idType === 'uuid' ? 'uuid' : 'number'; | ||
const { customIDType } = adapter.payload.collections[relationTo]; | ||
if (customIDType) { | ||
idType = customIDType; | ||
} | ||
const idTypeTextOrUuid = idType === 'text' || idType === 'uuid'; | ||
// Do not add the column to OR if we know that it can't match by the type | ||
// We can't do the same with idType: 'number' because `value` can be from the REST search query params | ||
if (typeof value === 'number' && idTypeTextOrUuid) { | ||
return null; | ||
} | ||
if (Array.isArray(value) && value.every((val)=>typeof val === 'number') && idTypeTextOrUuid) { | ||
return null; | ||
} | ||
// Do not add the UUID type column if incoming query value doesn't match UUID. If there aren't any collections with | ||
// a custom ID type, we skip this check | ||
// We need this because Postgres throws an error if querying by UUID column with a value that isn't a valid UUID. | ||
if (value && !Array.isArray(value) && idType === 'uuid' && hasCustomCollectionWithCustomID) { | ||
if (!uuidValidate(value)) { | ||
return null; | ||
} | ||
} | ||
if (Array.isArray(value) && idType === 'uuid' && hasCustomCollectionWithCustomID && !value.some((val)=>uuidValidate(val))) { | ||
return null; | ||
} | ||
const relationTableName = adapter.tableNameMap.get(toSnakeCase(adapter.payload.collections[relationTo].config.slug)); | ||
return `"${aliasRelationshipTableName}"."${relationTableName}_id"`; | ||
}); | ||
let column; | ||
if (tableColumnsNames.length === 1) { | ||
column = tableColumnsNames[0]; | ||
} else { | ||
column = `COALESCE(${tableColumnsNames.join(', ')})`; | ||
} | ||
return { | ||
idType, | ||
rawColumn: sql.raw(`"${aliasRelationshipTableName}"."${relationTableName}_id"`) | ||
}; | ||
}).filter(Boolean); | ||
return { | ||
columns, | ||
constraints, | ||
field, | ||
rawColumn: sql.raw(`${column}`), | ||
table: aliasRelationshipTable | ||
@@ -434,3 +460,5 @@ }; | ||
const matchedRelation = relationTo.find((relation)=>relation === val); | ||
if (matchedRelation) return `${matchedRelation}ID`; | ||
if (matchedRelation) { | ||
return `${matchedRelation}ID`; | ||
} | ||
return undefined; | ||
@@ -440,2 +468,11 @@ }, | ||
}; | ||
} else if (isPolymorphicRelationship(value)) { | ||
const { relationTo } = value; | ||
const relationTableName = adapter.tableNameMap.get(toSnakeCase(adapter.payload.collections[relationTo].config.slug)); | ||
return { | ||
constraints, | ||
field, | ||
rawColumn: sql.raw(`"${aliasRelationshipTableName}"."${relationTableName}_id"`), | ||
table: aliasRelationshipTable | ||
}; | ||
} else { | ||
@@ -442,0 +479,0 @@ throw new APIError('Not supported'); |
@@ -14,4 +14,4 @@ import type { SQL } from 'drizzle-orm'; | ||
}; | ||
export declare function parseParams({ adapter, fields, joins, locale, selectFields, tableName, where, }: Args): Promise<SQL>; | ||
export declare function parseParams({ adapter, fields, joins, locale, selectFields, tableName, where, }: Args): SQL; | ||
export {}; | ||
//# sourceMappingURL=parseParams.d.ts.map |
@@ -1,2 +0,2 @@ | ||
/* eslint-disable no-await-in-loop */ import { and, isNotNull, isNull, ne, notInArray, or, sql } from 'drizzle-orm'; | ||
import { and, isNotNull, isNull, ne, notInArray, or, sql } from 'drizzle-orm'; | ||
import { QueryError } from 'payload'; | ||
@@ -7,3 +7,3 @@ import { validOperators } from 'payload/shared'; | ||
import { sanitizeQueryValue } from './sanitizeQueryValue.js'; | ||
export async function parseParams({ adapter, fields, joins, locale, selectFields, tableName, where }) { | ||
export function parseParams({ adapter, fields, joins, locale, selectFields, tableName, where }) { | ||
let result; | ||
@@ -23,3 +23,3 @@ const constraints = []; | ||
if (Array.isArray(condition)) { | ||
const builtConditions = await buildAndOrConditions({ | ||
const builtConditions = buildAndOrConditions({ | ||
adapter, | ||
@@ -45,3 +45,3 @@ fields, | ||
const val = where[relationOrPath][operator]; | ||
const { columnName, constraints: queryConstraints, field, getNotNullColumnByValue, pathSegments, rawColumn, table } = getTableColumnFromPath({ | ||
const { columnName, columns, constraints: queryConstraints, field, getNotNullColumnByValue, pathSegments, rawColumn, table } = getTableColumnFromPath({ | ||
adapter, | ||
@@ -97,4 +97,9 @@ collectionPath: relationOrPath, | ||
exists: { | ||
operator: val === true ? 'is not null' : 'is null' | ||
operator: val === true ? 'is not null' : 'is null', | ||
wildcard: '' | ||
}, | ||
in: { | ||
operator: 'in', | ||
wildcard: '' | ||
}, | ||
like: { | ||
@@ -107,2 +112,6 @@ operator: 'like', | ||
wildcard: '' | ||
}, | ||
not_in: { | ||
operator: 'not in', | ||
wildcard: '' | ||
} | ||
@@ -113,2 +122,11 @@ }; | ||
formattedValue = val; | ||
} else if ([ | ||
'in', | ||
'not_in' | ||
].includes(operator) && Array.isArray(val)) { | ||
if (adapter.name === 'sqlite') { | ||
formattedValue = `(${val.map((v)=>`${v}`).join(',')})`; | ||
} else { | ||
formattedValue = `(${val.map((v)=>`'${v}'`).join(', ')})`; | ||
} | ||
} else { | ||
@@ -145,2 +163,3 @@ formattedValue = `'${operatorKeys[operator].wildcard}${val}${operatorKeys[operator].wildcard}'`; | ||
adapter, | ||
columns, | ||
field, | ||
@@ -154,3 +173,28 @@ operator, | ||
} | ||
const { operator: queryOperator, value: queryValue } = sanitizedQueryValue; | ||
const { columns: queryColumns, operator: queryOperator, value: queryValue } = sanitizedQueryValue; | ||
// Handle polymorphic relationships by value | ||
if (queryColumns) { | ||
if (!queryColumns.length) { | ||
break; | ||
} | ||
let wrapOperator = or; | ||
if (queryValue === null && [ | ||
'equals', | ||
'not_equals' | ||
].includes(operator)) { | ||
if (operator === 'equals') { | ||
wrapOperator = and; | ||
} | ||
constraints.push(wrapOperator(...queryColumns.map(({ rawColumn })=>operator === 'equals' ? isNull(rawColumn) : isNotNull(rawColumn)))); | ||
break; | ||
} | ||
if ([ | ||
'not_equals', | ||
'not_in' | ||
].includes(operator)) { | ||
wrapOperator = and; | ||
} | ||
constraints.push(wrapOperator(...queryColumns.map(({ rawColumn, value })=>adapter.operators[queryOperator](rawColumn, value)))); | ||
break; | ||
} | ||
if (queryOperator === 'not_equals' && queryValue !== null) { | ||
@@ -157,0 +201,0 @@ constraints.push(or(isNull(rawColumn || table[columnName]), /* eslint-disable @typescript-eslint/no-explicit-any */ ne(rawColumn || table[columnName], queryValue))); |
@@ -0,1 +1,2 @@ | ||
import type { SQL } from 'drizzle-orm'; | ||
import { type Field, type TabAsField } from 'payload'; | ||
@@ -5,2 +6,6 @@ import type { DrizzleAdapter } from '../types.js'; | ||
adapter: DrizzleAdapter; | ||
columns?: { | ||
idType: 'number' | 'text' | 'uuid'; | ||
rawColumn: SQL<unknown>; | ||
}[]; | ||
field: Field | TabAsField; | ||
@@ -11,3 +16,8 @@ operator: string; | ||
}; | ||
export declare const sanitizeQueryValue: ({ adapter, field, operator: operatorArg, relationOrPath, val, }: SanitizeQueryValueArgs) => { | ||
type SanitizedColumn = { | ||
rawColumn: SQL<unknown>; | ||
value: unknown; | ||
}; | ||
export declare const sanitizeQueryValue: ({ adapter, columns, field, operator: operatorArg, relationOrPath, val, }: SanitizeQueryValueArgs) => { | ||
columns?: SanitizedColumn[]; | ||
operator: string; | ||
@@ -14,0 +24,0 @@ value: unknown; |
import { APIError, createArrayFromCommaDelineated } from 'payload'; | ||
import { fieldAffectsData } from 'payload/shared'; | ||
export const sanitizeQueryValue = ({ adapter, field, operator: operatorArg, relationOrPath, val })=>{ | ||
import { validate as uuidValidate } from 'uuid'; | ||
import { getCollectionIdType } from '../utilities/getCollectionIdType.js'; | ||
import { isPolymorphicRelationship } from '../utilities/isPolymorphicRelationship.js'; | ||
export const sanitizeQueryValue = ({ adapter, columns, field, operator: operatorArg, relationOrPath, val })=>{ | ||
let operator = operatorArg; | ||
let formattedValue = val; | ||
if (!fieldAffectsData(field)) return { | ||
operator, | ||
value: formattedValue | ||
}; | ||
let formattedColumns; | ||
if (!fieldAffectsData(field)) { | ||
return { | ||
operator, | ||
value: formattedValue | ||
}; | ||
} | ||
if ((field.type === 'relationship' || field.type === 'upload') && !relationOrPath.endsWith('relationTo') && Array.isArray(formattedValue)) { | ||
@@ -25,4 +31,8 @@ const allPossibleIDTypes = []; | ||
if (field.type === 'checkbox' && typeof val === 'string') { | ||
if (val.toLowerCase() === 'true') formattedValue = true; | ||
if (val.toLowerCase() === 'false') formattedValue = false; | ||
if (val.toLowerCase() === 'true') { | ||
formattedValue = true; | ||
} | ||
if (val.toLowerCase() === 'false') { | ||
formattedValue = false; | ||
} | ||
} | ||
@@ -56,3 +66,5 @@ if ([ | ||
} | ||
} else if (typeof val === 'number') formattedValue = new Date(val).toISOString(); | ||
} else if (typeof val === 'number') { | ||
formattedValue = new Date(val).toISOString(); | ||
} | ||
} | ||
@@ -66,16 +78,51 @@ if (field.type === 'relationship' || field.type === 'upload') { | ||
if (typeof field.relationTo === 'string') { | ||
const collection = adapter.payload.collections[field.relationTo]; | ||
const mixedType = collection.customIDType || adapter.idType; | ||
const typeMap = { | ||
number: 'number', | ||
serial: 'number', | ||
text: 'text', | ||
uuid: 'text' | ||
}; | ||
idType = typeMap[mixedType]; | ||
idType = getCollectionIdType({ | ||
adapter, | ||
collection: adapter.payload.collections[field.relationTo] | ||
}); | ||
} else { | ||
// LIMITATION: Only cast to the first relationTo id type, | ||
// otherwise we need to make the db cast which is inefficient | ||
const collection = adapter.payload.collections[field.relationTo[0]]; | ||
idType = collection.customIDType || adapter.idType === 'uuid' ? 'text' : 'number'; | ||
if (isPolymorphicRelationship(val)) { | ||
if (operator !== 'equals') { | ||
throw new APIError(`Only 'equals' operator is supported for polymorphic relationship object notation. Given - ${operator}`); | ||
} | ||
idType = getCollectionIdType({ | ||
adapter, | ||
collection: adapter.payload.collections[val.relationTo] | ||
}); | ||
return { | ||
operator, | ||
value: idType === 'number' ? Number(val.value) : String(val.value) | ||
}; | ||
} | ||
formattedColumns = columns.map(({ idType, rawColumn })=>{ | ||
let formattedValue; | ||
if (Array.isArray(val)) { | ||
formattedValue = val.map((eachVal)=>{ | ||
let formattedValue; | ||
if (idType === 'number') { | ||
formattedValue = Number(eachVal); | ||
if (Number.isNaN(formattedValue)) { | ||
return null; | ||
} | ||
} else { | ||
if (idType === 'uuid' && !uuidValidate(eachVal)) { | ||
return null; | ||
} | ||
formattedValue = String(eachVal); | ||
} | ||
return formattedValue; | ||
}).filter(Boolean); | ||
} else if (idType === 'number') { | ||
formattedValue = Number(val); | ||
if (Number.isNaN(formattedValue)) { | ||
return null; | ||
} | ||
} else { | ||
formattedValue = String(val); | ||
} | ||
return { | ||
rawColumn, | ||
value: formattedValue | ||
}; | ||
}).filter(Boolean); | ||
} | ||
@@ -118,2 +165,3 @@ if (Array.isArray(formattedValue)) { | ||
return { | ||
columns: formattedColumns, | ||
operator, | ||
@@ -120,0 +168,0 @@ value: formattedValue |
import type { QueryPromise, SQL } from 'drizzle-orm'; | ||
import type { ChainedMethods } from '../find/chainMethods.js'; | ||
import type { DrizzleAdapter, DrizzleTransaction } from '../types.js'; | ||
import type { DrizzleAdapter, DrizzleTransaction, GenericColumn } from '../types.js'; | ||
import type { BuildQueryJoinAliases } from './buildQuery.js'; | ||
import { type GenericColumn } from '../types.js'; | ||
type Args = { | ||
@@ -18,6 +17,6 @@ adapter: DrizzleAdapter; | ||
*/ | ||
export declare const selectDistinct: ({ adapter, chainedMethods, db, joins, selectFields, tableName, where, }: Args) => QueryPromise<Record<string, GenericColumn> & { | ||
export declare const selectDistinct: ({ adapter, chainedMethods, db, joins, selectFields, tableName, where, }: Args) => QueryPromise<{ | ||
id: number | string; | ||
}[]>; | ||
}[] & Record<string, GenericColumn>>; | ||
export {}; | ||
//# sourceMappingURL=selectDistinct.d.ts.map |
@@ -7,3 +7,3 @@ import { buildVersionCollectionFields, combineQueries } from 'payload'; | ||
const tableName = this.tableNameMap.get(`_${toSnakeCase(collectionConfig.slug)}${this.versionsSuffix}`); | ||
const fields = buildVersionCollectionFields(collectionConfig); | ||
const fields = buildVersionCollectionFields(this.payload.config, collectionConfig); | ||
const combinedWhere = combineQueries({ | ||
@@ -29,3 +29,2 @@ latest: { | ||
docs: result.docs.map((doc)=>{ | ||
// eslint-disable-next-line no-param-reassign | ||
doc = { | ||
@@ -32,0 +31,0 @@ id: doc.parent, |
@@ -27,2 +27,3 @@ import { v4 as uuid } from 'uuid'; | ||
reject = ()=>{ | ||
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors | ||
rej(); | ||
@@ -45,3 +46,6 @@ return done; | ||
} catch (err) { | ||
this.payload.logger.error(`Error: cannot begin transaction: ${err.message}`, err); | ||
this.payload.logger.error({ | ||
err, | ||
msg: `Error: cannot begin transaction: ${err.message}` | ||
}); | ||
process.exit(1); | ||
@@ -48,0 +52,0 @@ } |
export const commitTransaction = async function commitTransaction(id) { | ||
if (id instanceof Promise) return; | ||
if (id instanceof Promise) { | ||
return; | ||
} | ||
// if the session was deleted it has already been aborted | ||
@@ -4,0 +6,0 @@ if (!this.sessions[id]) { |
@@ -7,5 +7,6 @@ import type { NumberField } from 'payload'; | ||
ref: Record<string, unknown>; | ||
withinArrayOrBlockLocale?: string; | ||
}; | ||
export declare const transformHasManyNumber: ({ field, locale, numberRows, ref }: Args) => void; | ||
export declare const transformHasManyNumber: ({ field, locale, numberRows, ref, withinArrayOrBlockLocale, }: Args) => void; | ||
export {}; | ||
//# sourceMappingURL=hasManyNumber.d.ts.map |
@@ -1,3 +0,13 @@ | ||
/* eslint-disable no-param-reassign */ export const transformHasManyNumber = ({ field, locale, numberRows, ref })=>{ | ||
const result = numberRows.map(({ number })=>number); | ||
export const transformHasManyNumber = ({ field, locale, numberRows, ref, withinArrayOrBlockLocale })=>{ | ||
let result; | ||
if (withinArrayOrBlockLocale) { | ||
result = numberRows.reduce((acc, { locale, number })=>{ | ||
if (locale === withinArrayOrBlockLocale) { | ||
acc.push(number); | ||
} | ||
return acc; | ||
}, []); | ||
} else { | ||
result = numberRows.map(({ number })=>number); | ||
} | ||
if (locale) { | ||
@@ -4,0 +14,0 @@ ref[field.name][locale] = result; |
@@ -7,5 +7,6 @@ import type { TextField } from 'payload'; | ||
textRows: Record<string, unknown>[]; | ||
withinArrayOrBlockLocale?: string; | ||
}; | ||
export declare const transformHasManyText: ({ field, locale, ref, textRows }: Args) => void; | ||
export declare const transformHasManyText: ({ field, locale, ref, textRows, withinArrayOrBlockLocale, }: Args) => void; | ||
export {}; | ||
//# sourceMappingURL=hasManyText.d.ts.map |
@@ -1,3 +0,13 @@ | ||
/* eslint-disable no-param-reassign */ export const transformHasManyText = ({ field, locale, ref, textRows })=>{ | ||
const result = textRows.map(({ text })=>text); | ||
export const transformHasManyText = ({ field, locale, ref, textRows, withinArrayOrBlockLocale })=>{ | ||
let result; | ||
if (withinArrayOrBlockLocale) { | ||
result = textRows.reduce((acc, { locale, text })=>{ | ||
if (locale === withinArrayOrBlockLocale) { | ||
acc.push(text); | ||
} | ||
return acc; | ||
}, []); | ||
} else { | ||
result = textRows.map(({ text })=>text); | ||
} | ||
if (locale) { | ||
@@ -4,0 +14,0 @@ ref[field.name][locale] = result; |
@@ -1,2 +0,2 @@ | ||
import type { Field, SanitizedConfig, TypeWithID } from 'payload'; | ||
import type { Field, JoinQuery, SanitizedConfig, TypeWithID } from 'payload'; | ||
import type { DrizzleAdapter } from '../../types.js'; | ||
@@ -9,6 +9,7 @@ type TransformArgs = { | ||
fields: Field[]; | ||
joinQuery?: JoinQuery; | ||
locale?: string; | ||
}; | ||
export declare const transform: <T extends Record<string, unknown> | TypeWithID>({ adapter, config, data, fields, }: TransformArgs) => T; | ||
export declare const transform: <T extends Record<string, unknown> | TypeWithID>({ adapter, config, data, fields, joinQuery, }: TransformArgs) => T; | ||
export {}; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -1,2 +0,2 @@ | ||
/* eslint-disable no-param-reassign */ import { createBlocksMap } from '../../utilities/createBlocksMap.js'; | ||
import { createBlocksMap } from '../../utilities/createBlocksMap.js'; | ||
import { createPathMap } from '../../utilities/createRelationshipMap.js'; | ||
@@ -6,3 +6,3 @@ import { traverseFields } from './traverseFields.js'; | ||
// into the shape Payload expects based on field schema | ||
export const transform = ({ adapter, config, data, fields })=>{ | ||
export const transform = ({ adapter, config, data, fields, joinQuery })=>{ | ||
let relationships = {}; | ||
@@ -35,2 +35,3 @@ let texts = {}; | ||
fields, | ||
joinQuery, | ||
numbers, | ||
@@ -37,0 +38,0 @@ path: '', |
@@ -7,5 +7,6 @@ import type { RelationshipField, UploadField } from 'payload'; | ||
relations: Record<string, unknown>[]; | ||
withinArrayOrBlockLocale?: string; | ||
}; | ||
export declare const transformRelationship: ({ field, locale, ref, relations }: Args) => void; | ||
export declare const transformRelationship: ({ field, locale, ref, relations, withinArrayOrBlockLocale, }: Args) => void; | ||
export {}; | ||
//# sourceMappingURL=relationship.d.ts.map |
@@ -1,9 +0,13 @@ | ||
/* eslint-disable no-param-reassign */ export const transformRelationship = ({ field, locale, ref, relations })=>{ | ||
export const transformRelationship = ({ field, locale, ref, relations, withinArrayOrBlockLocale })=>{ | ||
let result; | ||
if (!('hasMany' in field) || field.hasMany === false) { | ||
const relation = relations[0]; | ||
let relation = relations[0]; | ||
if (withinArrayOrBlockLocale) { | ||
relation = relations.find((rel)=>rel.locale === withinArrayOrBlockLocale); | ||
} | ||
if (relation) { | ||
// Handle hasOne Poly | ||
if (Array.isArray(field.relationTo)) { | ||
const matchedRelation = Object.entries(relation).find(([key, val])=>val !== null && ![ | ||
const matchedRelation = Object.entries(relation).find(([key, val])=>{ | ||
return val !== null && ![ | ||
'id', | ||
@@ -14,3 +18,4 @@ 'locale', | ||
'path' | ||
].includes(key)); | ||
].includes(key); | ||
}); | ||
if (matchedRelation) { | ||
@@ -28,6 +33,10 @@ const relationTo = matchedRelation[0].replace('ID', ''); | ||
relations.forEach((relation)=>{ | ||
let matchedLocale = true; | ||
if (withinArrayOrBlockLocale) { | ||
matchedLocale = relation.locale === withinArrayOrBlockLocale; | ||
} | ||
// Handle hasMany | ||
if (!Array.isArray(field.relationTo)) { | ||
const relatedData = relation[`${field.relationTo}ID`]; | ||
if (relatedData) { | ||
if (relatedData && matchedLocale) { | ||
transformedRelations.push(relatedData); | ||
@@ -43,3 +52,3 @@ } | ||
'path' | ||
].includes(key)); | ||
].includes(key) && matchedLocale); | ||
if (matchedRelation) { | ||
@@ -46,0 +55,0 @@ const relationTo = matchedRelation[0].replace('ID', ''); |
@@ -1,2 +0,2 @@ | ||
import type { Field, SanitizedConfig, TabAsField } from 'payload'; | ||
import type { Field, JoinQuery, SanitizedConfig, TabAsField } from 'payload'; | ||
import type { DrizzleAdapter } from '../../types.js'; | ||
@@ -34,2 +34,6 @@ import type { BlocksMap } from '../../utilities/createBlocksMap.js'; | ||
/** | ||
* | ||
*/ | ||
joinQuery?: JoinQuery; | ||
/** | ||
* All hasMany number fields, as returned by Drizzle, keyed on an object by field path | ||
@@ -54,5 +58,9 @@ */ | ||
texts: Record<string, Record<string, unknown>[]>; | ||
/** | ||
* Set to a locale if this group of fields is within a localized array or block. | ||
*/ | ||
withinArrayOrBlockLocale?: string; | ||
}; | ||
export declare const traverseFields: <T extends Record<string, unknown>>({ adapter, blocks, config, dataRef, deletions, fieldPrefix, fields, numbers, path, relationships, table, texts, }: TraverseFieldsArgs) => T; | ||
export declare const traverseFields: <T extends Record<string, unknown>>({ adapter, blocks, config, dataRef, deletions, fieldPrefix, fields, joinQuery, numbers, path, relationships, table, texts, withinArrayOrBlockLocale, }: TraverseFieldsArgs) => T; | ||
export {}; | ||
//# sourceMappingURL=traverseFields.d.ts.map |
@@ -1,2 +0,2 @@ | ||
import { fieldAffectsData } from 'payload/shared'; | ||
import { fieldAffectsData, fieldIsVirtual } from 'payload/shared'; | ||
import { transformHasManyNumber } from './hasManyNumber.js'; | ||
@@ -7,3 +7,3 @@ import { transformHasManyText } from './hasManyText.js'; | ||
// for each field type into required Payload shape | ||
export const traverseFields = ({ adapter, blocks, config, dataRef, deletions, fieldPrefix, fields, numbers, path, relationships, table, texts })=>{ | ||
export const traverseFields = ({ adapter, blocks, config, dataRef, deletions, fieldPrefix, fields, joinQuery, numbers, path, relationships, table, texts, withinArrayOrBlockLocale })=>{ | ||
const sanitizedPath = path ? `${path}.` : path; | ||
@@ -23,2 +23,3 @@ const formatted = fields.reduce((result, field)=>{ | ||
})), | ||
joinQuery, | ||
numbers, | ||
@@ -28,3 +29,4 @@ path, | ||
table, | ||
texts | ||
texts, | ||
withinArrayOrBlockLocale | ||
}); | ||
@@ -41,2 +43,3 @@ } | ||
fields: field.fields, | ||
joinQuery, | ||
numbers, | ||
@@ -46,6 +49,10 @@ path, | ||
table, | ||
texts | ||
texts, | ||
withinArrayOrBlockLocale | ||
}); | ||
} | ||
if (fieldAffectsData(field)) { | ||
if (fieldIsVirtual(field)) { | ||
return result; | ||
} | ||
const fieldName = `${fieldPrefix || ''}${field.name}`; | ||
@@ -63,3 +70,5 @@ const fieldData = table[fieldName]; | ||
if (typeof row._locale === 'string') { | ||
if (!arrayResult[row._locale]) arrayResult[row._locale] = []; | ||
if (!arrayResult[row._locale]) { | ||
arrayResult[row._locale] = []; | ||
} | ||
const locale = row._locale; | ||
@@ -84,3 +93,4 @@ const data = {}; | ||
table: row, | ||
texts | ||
texts, | ||
withinArrayOrBlockLocale: locale | ||
}); | ||
@@ -95,3 +105,3 @@ if ('_order' in rowResult) { | ||
} else { | ||
result[field.name] = fieldData.map((row, i)=>{ | ||
result[field.name] = fieldData.reduce((acc, row, i)=>{ | ||
if (row._uuid) { | ||
@@ -104,17 +114,24 @@ row.id = row._uuid; | ||
} | ||
return traverseFields({ | ||
adapter, | ||
blocks, | ||
config, | ||
dataRef: row, | ||
deletions, | ||
fieldPrefix: '', | ||
fields: field.fields, | ||
numbers, | ||
path: `${sanitizedPath}${field.name}.${i}`, | ||
relationships, | ||
table: row, | ||
texts | ||
}); | ||
}); | ||
if (!withinArrayOrBlockLocale || withinArrayOrBlockLocale && withinArrayOrBlockLocale === row._locale) { | ||
if (row._locale) { | ||
delete row._locale; | ||
} | ||
acc.push(traverseFields({ | ||
adapter, | ||
blocks, | ||
config, | ||
dataRef: row, | ||
deletions, | ||
fieldPrefix: '', | ||
fields: field.fields, | ||
numbers, | ||
path: `${sanitizedPath}${field.name}.${i}`, | ||
relationships, | ||
table: row, | ||
texts, | ||
withinArrayOrBlockLocale | ||
})); | ||
} | ||
return acc; | ||
}, []); | ||
} | ||
@@ -135,3 +152,5 @@ } | ||
if (typeof row._locale === 'string') { | ||
if (!result[field.name][row._locale]) result[field.name][row._locale] = []; | ||
if (!result[field.name][row._locale]) { | ||
result[field.name][row._locale] = []; | ||
} | ||
result[field.name][row._locale].push(row); | ||
@@ -157,3 +176,4 @@ delete row._locale; | ||
table: row, | ||
texts | ||
texts, | ||
withinArrayOrBlockLocale: locale | ||
}); | ||
@@ -167,3 +187,3 @@ delete blockResult._order; | ||
} else { | ||
result[field.name] = blocks[blockFieldPath].map((row, i)=>{ | ||
result[field.name] = blocks[blockFieldPath].reduce((acc, row, i)=>{ | ||
delete row._order; | ||
@@ -176,19 +196,28 @@ if (row._uuid) { | ||
if (block) { | ||
return traverseFields({ | ||
adapter, | ||
blocks, | ||
config, | ||
dataRef: row, | ||
deletions, | ||
fieldPrefix: '', | ||
fields: block.fields, | ||
numbers, | ||
path: `${blockFieldPath}.${i}`, | ||
relationships, | ||
table: row, | ||
texts | ||
}); | ||
if (!withinArrayOrBlockLocale || withinArrayOrBlockLocale && withinArrayOrBlockLocale === row._locale) { | ||
if (row._locale) { | ||
delete row._locale; | ||
} | ||
acc.push(traverseFields({ | ||
adapter, | ||
blocks, | ||
config, | ||
dataRef: row, | ||
deletions, | ||
fieldPrefix: '', | ||
fields: block.fields, | ||
numbers, | ||
path: `${blockFieldPath}.${i}`, | ||
relationships, | ||
table: row, | ||
texts, | ||
withinArrayOrBlockLocale | ||
})); | ||
return acc; | ||
} | ||
} else { | ||
acc.push({}); | ||
} | ||
return {}; | ||
}); | ||
return acc; | ||
}, []); | ||
} | ||
@@ -231,3 +260,5 @@ } | ||
if (typeof row.locale === 'string') { | ||
if (!relationsByLocale[row.locale]) relationsByLocale[row.locale] = []; | ||
if (!relationsByLocale[row.locale]) { | ||
relationsByLocale[row.locale] = []; | ||
} | ||
relationsByLocale[row.locale].push(row); | ||
@@ -248,3 +279,4 @@ } | ||
ref: result, | ||
relations: relationPathMatch | ||
relations: relationPathMatch, | ||
withinArrayOrBlockLocale | ||
}); | ||
@@ -255,5 +287,39 @@ } | ||
} | ||
if (field.type === 'join') { | ||
const { limit = 10 } = joinQuery?.[`${fieldPrefix.replaceAll('_', '.')}${field.name}`] || {}; | ||
let fieldResult; | ||
if (Array.isArray(fieldData)) { | ||
if (field.localized) { | ||
fieldResult = fieldData.reduce((joinResult, row)=>{ | ||
if (typeof row._locale === 'string') { | ||
if (!joinResult[row._locale]) { | ||
joinResult[row._locale] = { | ||
docs: [], | ||
hasNextPage: false | ||
}; | ||
} | ||
joinResult[row._locale].docs.push(row._parentID); | ||
} | ||
return joinResult; | ||
}, {}); | ||
Object.keys(fieldResult).forEach((locale)=>{ | ||
fieldResult[locale].hasNextPage = fieldResult[locale].docs.length > limit; | ||
fieldResult[locale].docs = fieldResult[locale].docs.slice(0, limit); | ||
}); | ||
} else { | ||
const hasNextPage = limit !== 0 && fieldData.length > limit; | ||
fieldResult = { | ||
docs: hasNextPage ? fieldData.slice(0, limit) : fieldData, | ||
hasNextPage | ||
}; | ||
} | ||
} | ||
result[field.name] = fieldResult; | ||
return result; | ||
} | ||
if (field.type === 'text' && field?.hasMany) { | ||
const textPathMatch = texts[`${sanitizedPath}${field.name}`]; | ||
if (!textPathMatch) return result; | ||
if (!textPathMatch) { | ||
return result; | ||
} | ||
if (field.localized) { | ||
@@ -264,3 +330,5 @@ result[field.name] = {}; | ||
if (typeof row.locale === 'string') { | ||
if (!textsByLocale[row.locale]) textsByLocale[row.locale] = []; | ||
if (!textsByLocale[row.locale]) { | ||
textsByLocale[row.locale] = []; | ||
} | ||
textsByLocale[row.locale].push(row); | ||
@@ -281,3 +349,4 @@ } | ||
ref: result, | ||
textRows: textPathMatch | ||
textRows: textPathMatch, | ||
withinArrayOrBlockLocale | ||
}); | ||
@@ -289,3 +358,5 @@ } | ||
const numberPathMatch = numbers[`${sanitizedPath}${field.name}`]; | ||
if (!numberPathMatch) return result; | ||
if (!numberPathMatch) { | ||
return result; | ||
} | ||
if (field.localized) { | ||
@@ -296,3 +367,5 @@ result[field.name] = {}; | ||
if (typeof row.locale === 'string') { | ||
if (!numbersByLocale[row.locale]) numbersByLocale[row.locale] = []; | ||
if (!numbersByLocale[row.locale]) { | ||
numbersByLocale[row.locale] = []; | ||
} | ||
numbersByLocale[row.locale].push(row); | ||
@@ -313,3 +386,4 @@ } | ||
numberRows: numberPathMatch, | ||
ref: result | ||
ref: result, | ||
withinArrayOrBlockLocale | ||
}); | ||
@@ -324,3 +398,5 @@ } | ||
if (typeof row.locale === 'string') { | ||
if (!selectResult[row.locale]) selectResult[row.locale] = []; | ||
if (!selectResult[row.locale]) { | ||
selectResult[row.locale] = []; | ||
} | ||
selectResult[row.locale].push(row.value); | ||
@@ -341,2 +417,3 @@ } | ||
table: { | ||
...table, | ||
...localeRow | ||
@@ -364,3 +441,5 @@ } | ||
const refKey = field.localized && locale ? locale : field.name; | ||
if (field.localized && locale) delete table._locale; | ||
if (field.localized && locale) { | ||
delete table._locale; | ||
} | ||
ref[refKey] = traverseFields({ | ||
@@ -378,3 +457,4 @@ adapter, | ||
table, | ||
texts | ||
texts, | ||
withinArrayOrBlockLocale: locale || withinArrayOrBlockLocale | ||
}); | ||
@@ -381,0 +461,0 @@ if ('_order' in ref) { |
@@ -23,5 +23,10 @@ import type { ArrayField } from 'payload'; | ||
texts: Record<string, unknown>[]; | ||
/** | ||
* Set to a locale code if this set of fields is traversed within a | ||
* localized array or block field | ||
*/ | ||
withinArrayOrBlockLocale?: string; | ||
}; | ||
export declare const transformArray: ({ adapter, arrayTableName, baseTableName, blocks, blocksToDelete, data, field, locale, numbers, path, relationships, relationshipsToDelete, selects, texts, }: Args) => ArrayRowToInsert[]; | ||
export declare const transformArray: ({ adapter, arrayTableName, baseTableName, blocks, blocksToDelete, data, field, locale, numbers, path, relationships, relationshipsToDelete, selects, texts, withinArrayOrBlockLocale, }: Args) => ArrayRowToInsert[]; | ||
export {}; | ||
//# sourceMappingURL=array.d.ts.map |
@@ -1,4 +0,4 @@ | ||
/* eslint-disable no-param-reassign */ import { isArrayOfRows } from '../../utilities/isArrayOfRows.js'; | ||
import { isArrayOfRows } from '../../utilities/isArrayOfRows.js'; | ||
import { traverseFields } from './traverseFields.js'; | ||
export const transformArray = ({ adapter, arrayTableName, baseTableName, blocks, blocksToDelete, data, field, locale, numbers, path, relationships, relationshipsToDelete, selects, texts })=>{ | ||
export const transformArray = ({ adapter, arrayTableName, baseTableName, blocks, blocksToDelete, data, field, locale, numbers, path, relationships, relationshipsToDelete, selects, texts, withinArrayOrBlockLocale })=>{ | ||
const newRows = []; | ||
@@ -32,2 +32,5 @@ const hasUUID = adapter.tables[arrayTableName]._uuid; | ||
} | ||
if (withinArrayOrBlockLocale) { | ||
newRow.row._locale = withinArrayOrBlockLocale; | ||
} | ||
traverseFields({ | ||
@@ -51,3 +54,4 @@ adapter, | ||
selects, | ||
texts | ||
texts, | ||
withinArrayOrBlockLocale | ||
}); | ||
@@ -54,0 +58,0 @@ newRows.push(newRow); |
@@ -1,2 +0,2 @@ | ||
import type { BlockField } from 'payload'; | ||
import type { BlocksField } from 'payload'; | ||
import type { DrizzleAdapter } from '../../types.js'; | ||
@@ -12,3 +12,3 @@ import type { BlockRowToInsert, RelationshipToDelete } from './types.js'; | ||
data: Record<string, unknown>[]; | ||
field: BlockField; | ||
field: BlocksField; | ||
locale?: string; | ||
@@ -23,5 +23,10 @@ numbers: Record<string, unknown>[]; | ||
texts: Record<string, unknown>[]; | ||
/** | ||
* Set to a locale code if this set of fields is traversed within a | ||
* localized array or block field | ||
*/ | ||
withinArrayOrBlockLocale?: string; | ||
}; | ||
export declare const transformBlocks: ({ adapter, baseTableName, blocks, blocksToDelete, data, field, locale, numbers, path, relationships, relationshipsToDelete, selects, texts, }: Args) => void; | ||
export declare const transformBlocks: ({ adapter, baseTableName, blocks, blocksToDelete, data, field, locale, numbers, path, relationships, relationshipsToDelete, selects, texts, withinArrayOrBlockLocale, }: Args) => void; | ||
export {}; | ||
//# sourceMappingURL=blocks.d.ts.map |
@@ -1,10 +0,16 @@ | ||
/* eslint-disable no-param-reassign */ import toSnakeCase from 'to-snake-case'; | ||
import toSnakeCase from 'to-snake-case'; | ||
import { traverseFields } from './traverseFields.js'; | ||
export const transformBlocks = ({ adapter, baseTableName, blocks, blocksToDelete, data, field, locale, numbers, path, relationships, relationshipsToDelete, selects, texts })=>{ | ||
export const transformBlocks = ({ adapter, baseTableName, blocks, blocksToDelete, data, field, locale, numbers, path, relationships, relationshipsToDelete, selects, texts, withinArrayOrBlockLocale })=>{ | ||
data.forEach((blockRow, i)=>{ | ||
if (typeof blockRow.blockType !== 'string') return; | ||
if (typeof blockRow.blockType !== 'string') { | ||
return; | ||
} | ||
const matchedBlock = field.blocks.find(({ slug })=>slug === blockRow.blockType); | ||
if (!matchedBlock) return; | ||
if (!matchedBlock) { | ||
return; | ||
} | ||
const blockType = toSnakeCase(blockRow.blockType); | ||
if (!blocks[blockType]) blocks[blockType] = []; | ||
if (!blocks[blockType]) { | ||
blocks[blockType] = []; | ||
} | ||
const newRow = { | ||
@@ -18,3 +24,8 @@ arrays: {}, | ||
}; | ||
if (field.localized && locale) newRow.row._locale = locale; | ||
if (field.localized && locale) { | ||
newRow.row._locale = locale; | ||
} | ||
if (withinArrayOrBlockLocale) { | ||
newRow.row._locale = withinArrayOrBlockLocale; | ||
} | ||
const blockTableName = adapter.tableNameMap.get(`${baseTableName}_blocks_${blockType}`); | ||
@@ -49,3 +60,4 @@ const hasUUID = adapter.tables[blockTableName]._uuid; | ||
selects, | ||
texts | ||
texts, | ||
withinArrayOrBlockLocale | ||
}); | ||
@@ -52,0 +64,0 @@ blocks[blockType].push(newRow); |
@@ -1,2 +0,2 @@ | ||
/* eslint-disable no-param-reassign */ import { traverseFields } from './traverseFields.js'; | ||
import { traverseFields } from './traverseFields.js'; | ||
export const transformForWrite = ({ adapter, data, fields, path = '', tableName })=>{ | ||
@@ -3,0 +3,0 @@ // Split out the incoming data into rows to insert / delete |
@@ -11,3 +11,5 @@ import { valueIsValueWithRelation } from 'payload/shared'; | ||
}; | ||
if ('hasMany' in field && field.hasMany) relationRow.order = i + 1; | ||
if ('hasMany' in field && field.hasMany) { | ||
relationRow.order = i + 1; | ||
} | ||
if (Array.isArray(field.relationTo) && valueIsValueWithRelation(relation)) { | ||
@@ -18,3 +20,5 @@ relationRow[`${relation.relationTo}ID`] = relation.value; | ||
relationRow[`${field.relationTo}ID`] = relation; | ||
if (relation) relationships.push(relationRow); | ||
if (relation) { | ||
relationships.push(relationRow); | ||
} | ||
} | ||
@@ -21,0 +25,0 @@ } |
@@ -1,2 +0,2 @@ | ||
/* eslint-disable no-param-reassign */ import { isArrayOfRows } from '../../utilities/isArrayOfRows.js'; | ||
import { isArrayOfRows } from '../../utilities/isArrayOfRows.js'; | ||
export const transformSelects = ({ id, data, locale })=>{ | ||
@@ -3,0 +3,0 @@ const newRows = []; |
@@ -47,5 +47,10 @@ import type { Field } from 'payload'; | ||
texts: Record<string, unknown>[]; | ||
/** | ||
* Set to a locale code if this set of fields is traversed within a | ||
* localized array or block field | ||
*/ | ||
withinArrayOrBlockLocale?: string; | ||
}; | ||
export declare const traverseFields: ({ adapter, arrays, baseTableName, blocks, blocksToDelete, columnPrefix, data, existingLocales, fieldPrefix, fields, forcedLocale, locales, numbers, parentTableName, path, relationships, relationshipsToDelete, row, selects, texts, }: Args) => void; | ||
export declare const traverseFields: ({ adapter, arrays, baseTableName, blocks, blocksToDelete, columnPrefix, data, existingLocales, fieldPrefix, fields, forcedLocale, locales, numbers, parentTableName, path, relationships, relationshipsToDelete, row, selects, texts, withinArrayOrBlockLocale, }: Args) => void; | ||
export {}; | ||
//# sourceMappingURL=traverseFields.d.ts.map |
@@ -1,2 +0,2 @@ | ||
import { fieldAffectsData } from 'payload/shared'; | ||
import { fieldAffectsData, fieldIsVirtual } from 'payload/shared'; | ||
import toSnakeCase from 'to-snake-case'; | ||
@@ -10,3 +10,3 @@ import { isArrayOfRows } from '../../utilities/isArrayOfRows.js'; | ||
import { transformTexts } from './texts.js'; | ||
export const traverseFields = ({ adapter, arrays, baseTableName, blocks, blocksToDelete, columnPrefix, data, existingLocales, fieldPrefix, fields, forcedLocale, locales, numbers, parentTableName, path, relationships, relationshipsToDelete, row, selects, texts })=>{ | ||
export const traverseFields = ({ adapter, arrays, baseTableName, blocks, blocksToDelete, columnPrefix, data, existingLocales, fieldPrefix, fields, forcedLocale, locales, numbers, parentTableName, path, relationships, relationshipsToDelete, row, selects, texts, withinArrayOrBlockLocale })=>{ | ||
fields.forEach((field)=>{ | ||
@@ -17,2 +17,5 @@ let columnName = ''; | ||
if (fieldAffectsData(field)) { | ||
if (fieldIsVirtual(field)) { | ||
return; | ||
} | ||
columnName = `${columnPrefix || ''}${toSnakeCase(field.name)}`; | ||
@@ -24,3 +27,5 @@ fieldName = `${fieldPrefix || ''}${field.name}`; | ||
const arrayTableName = adapter.tableNameMap.get(`${parentTableName}_${columnName}`); | ||
if (!arrays[arrayTableName]) arrays[arrayTableName] = []; | ||
if (!arrays[arrayTableName]) { | ||
arrays[arrayTableName] = []; | ||
} | ||
if (field.localized) { | ||
@@ -44,3 +49,4 @@ if (typeof data[field.name] === 'object' && data[field.name] !== null) { | ||
selects, | ||
texts | ||
texts, | ||
withinArrayOrBlockLocale: localeKey | ||
}); | ||
@@ -65,3 +71,4 @@ arrays[arrayTableName] = arrays[arrayTableName].concat(newRows); | ||
selects, | ||
texts | ||
texts, | ||
withinArrayOrBlockLocale | ||
}); | ||
@@ -93,3 +100,4 @@ arrays[arrayTableName] = arrays[arrayTableName].concat(newRows); | ||
selects, | ||
texts | ||
texts, | ||
withinArrayOrBlockLocale: localeKey | ||
}); | ||
@@ -112,3 +120,4 @@ } | ||
selects, | ||
texts | ||
texts, | ||
withinArrayOrBlockLocale | ||
}); | ||
@@ -142,3 +151,4 @@ } | ||
selects, | ||
texts | ||
texts, | ||
withinArrayOrBlockLocale: localeKey | ||
}); | ||
@@ -166,3 +176,4 @@ }); | ||
selects, | ||
texts | ||
texts, | ||
withinArrayOrBlockLocale | ||
}); | ||
@@ -176,2 +187,5 @@ } | ||
if ('name' in tab) { | ||
if (fieldIsVirtual(tab)) { | ||
return; | ||
} | ||
if (typeof data[tab.name] === 'object' && data[tab.name] !== null) { | ||
@@ -200,3 +214,4 @@ if (tab.localized) { | ||
selects, | ||
texts | ||
texts, | ||
withinArrayOrBlockLocale: localeKey | ||
}); | ||
@@ -224,3 +239,4 @@ }); | ||
selects, | ||
texts | ||
texts, | ||
withinArrayOrBlockLocale | ||
}); | ||
@@ -249,3 +265,4 @@ } | ||
selects, | ||
texts | ||
texts, | ||
withinArrayOrBlockLocale | ||
}); | ||
@@ -275,3 +292,4 @@ } | ||
selects, | ||
texts | ||
texts, | ||
withinArrayOrBlockLocale | ||
}); | ||
@@ -312,2 +330,3 @@ } | ||
baseRow: { | ||
locale: withinArrayOrBlockLocale, | ||
path: relationshipPath | ||
@@ -358,2 +377,3 @@ }, | ||
baseRow: { | ||
locale: withinArrayOrBlockLocale, | ||
path: textPath | ||
@@ -387,2 +407,3 @@ }, | ||
baseRow: { | ||
locale: withinArrayOrBlockLocale, | ||
path: numberPath | ||
@@ -398,3 +419,5 @@ }, | ||
const selectTableName = adapter.tableNameMap.get(`${parentTableName}_${columnName}`); | ||
if (!selects[selectTableName]) selects[selectTableName] = []; | ||
if (!selects[selectTableName]) { | ||
selects[selectTableName] = []; | ||
} | ||
if (field.localized) { | ||
@@ -416,3 +439,4 @@ if (typeof data[field.name] === 'object' && data[field.name] !== null) { | ||
id: data._uuid || data.id, | ||
data: data[field.name] | ||
data: data[field.name], | ||
locale: withinArrayOrBlockLocale | ||
}); | ||
@@ -428,3 +452,5 @@ selects[selectTableName] = selects[selectTableName].concat(newRows); | ||
Object.entries(fieldData).forEach(([localeKey, localeData])=>{ | ||
if (!locales[localeKey]) locales[localeKey] = {}; | ||
if (!locales[localeKey]) { | ||
locales[localeKey] = {}; | ||
} | ||
valuesToTransform.push({ | ||
@@ -440,3 +466,5 @@ localeKey, | ||
if (forcedLocale) { | ||
if (!locales[forcedLocale]) locales[forcedLocale] = {}; | ||
if (!locales[forcedLocale]) { | ||
locales[forcedLocale] = {}; | ||
} | ||
ref = locales[forcedLocale]; | ||
@@ -443,0 +471,0 @@ } |
@@ -108,3 +108,3 @@ import type { ColumnBaseConfig, ColumnDataType, DrizzleConfig, ExtractTablesWithRelations, Relation, Relations, SQL, TableRelationalConfig } from 'drizzle-orm'; | ||
dropDatabase: DropDatabase; | ||
enums?: Record<string, unknown> | never; | ||
enums?: never | Record<string, unknown>; | ||
execute: Execute<unknown>; | ||
@@ -111,0 +111,0 @@ features: { |
@@ -5,3 +5,3 @@ import toSnakeCase from 'to-snake-case'; | ||
import { upsertRow } from './upsertRow/index.js'; | ||
export const updateOne = async function updateOne({ id, collection: collectionSlug, data, draft, locale, req, where: whereArg }) { | ||
export const updateOne = async function updateOne({ id, collection: collectionSlug, data, draft, joins: joinQuery, locale, req, where: whereArg }) { | ||
const db = this.sessions[await req?.transactionID]?.db || this.drizzle; | ||
@@ -16,3 +16,3 @@ const collection = this.payload.collections[collectionSlug].config; | ||
let idToUpdate = id; | ||
const { joins, selectFields, where } = await buildQuery({ | ||
const { joins, selectFields, where } = buildQuery({ | ||
adapter: this, | ||
@@ -49,2 +49,3 @@ fields: collection.fields, | ||
fields: collection.fields, | ||
joinQuery, | ||
operation: 'update', | ||
@@ -51,0 +52,0 @@ req, |
@@ -14,4 +14,4 @@ import { buildVersionGlobalFields } from 'payload'; | ||
const tableName = this.tableNameMap.get(`_${toSnakeCase(globalConfig.slug)}${this.versionsSuffix}`); | ||
const fields = buildVersionGlobalFields(globalConfig); | ||
const { where } = await buildQuery({ | ||
const fields = buildVersionGlobalFields(this.payload.config, globalConfig); | ||
const { where } = buildQuery({ | ||
adapter: this, | ||
@@ -18,0 +18,0 @@ fields, |
@@ -14,4 +14,4 @@ import { buildVersionCollectionFields } from 'payload'; | ||
const tableName = this.tableNameMap.get(`_${toSnakeCase(collectionConfig.slug)}${this.versionsSuffix}`); | ||
const fields = buildVersionCollectionFields(collectionConfig); | ||
const { where } = await buildQuery({ | ||
const fields = buildVersionCollectionFields(this.payload.config, collectionConfig); | ||
const { where } = buildQuery({ | ||
adapter: this, | ||
@@ -18,0 +18,0 @@ fields, |
@@ -21,3 +21,5 @@ import { and, eq, inArray } from 'drizzle-orm'; | ||
]; | ||
if (pathColumnName) whereConstraints.push(inArray(table[pathColumnName], Array.from(localizedPathsToDelete))); | ||
if (pathColumnName) { | ||
whereConstraints.push(inArray(table[pathColumnName], Array.from(localizedPathsToDelete))); | ||
} | ||
await adapter.deleteWhere({ | ||
@@ -33,3 +35,5 @@ db, | ||
]; | ||
if (pathColumnName) whereConstraints.push(inArray(table[pathColumnName], Array.from(pathsToDelete))); | ||
if (pathColumnName) { | ||
whereConstraints.push(inArray(table[pathColumnName], Array.from(pathsToDelete))); | ||
} | ||
await adapter.deleteWhere({ | ||
@@ -36,0 +40,0 @@ db, |
import type { TypeWithID } from 'payload'; | ||
import type { Args } from './types.js'; | ||
export declare const upsertRow: <T extends Record<string, unknown> | TypeWithID>({ id, adapter, data, db, fields, ignoreResult, operation, path, req, tableName, upsertTarget, where, }: Args) => Promise<T>; | ||
export declare const upsertRow: <T extends Record<string, unknown> | TypeWithID>({ id, adapter, data, db, fields, ignoreResult, joinQuery, operation, path, req, tableName, upsertTarget, where, }: Args) => Promise<T>; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -9,3 +9,3 @@ import { eq } from 'drizzle-orm'; | ||
import { insertArrays } from './insertArrays.js'; | ||
export const upsertRow = async ({ id, adapter, data, db, fields, ignoreResult, operation, path = '', req, tableName, upsertTarget, where })=>{ | ||
export const upsertRow = async ({ id, adapter, data, db, fields, ignoreResult, joinQuery, operation, path = '', req, tableName, upsertTarget, where })=>{ | ||
// Split out the incoming data into the corresponding: | ||
@@ -98,3 +98,5 @@ // base row, locales, relationships, blocks, and arrays | ||
} | ||
if (!selectsToInsert[selectTableName]) selectsToInsert[selectTableName] = []; | ||
if (!selectsToInsert[selectTableName]) { | ||
selectsToInsert[selectTableName] = []; | ||
} | ||
selectsToInsert[selectTableName].push(row); | ||
@@ -109,3 +111,5 @@ }); | ||
blockRow.row._parentID = insertedRow.id; | ||
if (!blocksToInsert[blockName]) blocksToInsert[blockName] = []; | ||
if (!blocksToInsert[blockName]) { | ||
blocksToInsert[blockName] = []; | ||
} | ||
if (blockRow.row.uuid) { | ||
@@ -306,12 +310,44 @@ delete blockRow.row.uuid; | ||
} catch (error) { | ||
throw error.code === '23505' ? new ValidationError({ | ||
errors: [ | ||
{ | ||
field: adapter.fieldConstraints[tableName][error.constraint], | ||
message: req.t('error:valueMustBeUnique') | ||
if (error.code === '23505') { | ||
let fieldName = null; | ||
// We need to try and find the right constraint for the field but if we can't we fallback to a generic message | ||
if (adapter.fieldConstraints?.[tableName]) { | ||
if (adapter.fieldConstraints[tableName]?.[error.constraint]) { | ||
fieldName = adapter.fieldConstraints[tableName]?.[error.constraint]; | ||
} else { | ||
const replacement = `${tableName}_`; | ||
if (error.constraint.includes(replacement)) { | ||
const replacedConstraint = error.constraint.replace(replacement, ''); | ||
if (replacedConstraint && adapter.fieldConstraints[tableName]?.[replacedConstraint]) { | ||
fieldName = adapter.fieldConstraints[tableName][replacedConstraint]; | ||
} | ||
} | ||
} | ||
] | ||
}, req.t) : error; | ||
} | ||
if (!fieldName) { | ||
// Last case scenario we extract the key and value from the detail on the error | ||
const detail = error.detail; | ||
const regex = /Key \(([^)]+)\)=\(([^)]+)\)/; | ||
const match = detail.match(regex); | ||
if (match) { | ||
const key = match[1]; | ||
fieldName = key; | ||
} | ||
} | ||
throw new ValidationError({ | ||
id, | ||
errors: [ | ||
{ | ||
field: fieldName, | ||
message: req.t('error:valueMustBeUnique') | ||
} | ||
] | ||
}, req.t); | ||
} else { | ||
throw error; | ||
} | ||
} | ||
if (ignoreResult) return data; | ||
if (ignoreResult) { | ||
return data; | ||
} | ||
// ////////////////////////////////// | ||
@@ -324,2 +360,3 @@ // RETRIEVE NEWLY UPDATED ROW | ||
fields, | ||
joinQuery, | ||
tableName | ||
@@ -336,3 +373,4 @@ }); | ||
data: doc, | ||
fields | ||
fields, | ||
joinQuery | ||
}); | ||
@@ -339,0 +377,0 @@ return result; |
@@ -1,2 +0,2 @@ | ||
/* eslint-disable no-param-reassign */ export const insertArrays = async ({ adapter, arrays, db, parentRows })=>{ | ||
export const insertArrays = async ({ adapter, arrays, db, parentRows })=>{ | ||
// Maintain a map of flattened rows by table | ||
@@ -29,3 +29,6 @@ const rowsByTable = {}; | ||
if (!arrayRow.row.id) { | ||
arrayRowLocaleData._getParentID = (rows)=>rows[i].id; | ||
arrayRowLocaleData._getParentID = (rows)=>{ | ||
const { id } = rows.find((each)=>each._uuid === arrayRow.row._uuid); | ||
return id; | ||
}; | ||
} | ||
@@ -32,0 +35,0 @@ }); |
import type { SQL } from 'drizzle-orm'; | ||
import type { Field, PayloadRequest } from 'payload'; | ||
import type { Field, JoinQuery, PayloadRequest } from 'payload'; | ||
import type { DrizzleAdapter, DrizzleTransaction, GenericColumn } from '../types.js'; | ||
@@ -14,2 +14,3 @@ type BaseArgs = { | ||
ignoreResult?: boolean; | ||
joinQuery?: JoinQuery; | ||
path?: string; | ||
@@ -19,16 +20,18 @@ req: PayloadRequest; | ||
}; | ||
type CreateArgs = BaseArgs & { | ||
type CreateArgs = { | ||
id?: never; | ||
joinQuery?: never; | ||
operation: 'create'; | ||
upsertTarget?: never; | ||
where?: never; | ||
}; | ||
type UpdateArgs = BaseArgs & { | ||
} & BaseArgs; | ||
type UpdateArgs = { | ||
id?: number | string; | ||
joinQuery?: JoinQuery; | ||
operation: 'update'; | ||
upsertTarget?: GenericColumn; | ||
where?: SQL<unknown>; | ||
}; | ||
} & BaseArgs; | ||
export type Args = CreateArgs | UpdateArgs; | ||
export {}; | ||
//# sourceMappingURL=types.d.ts.map |
@@ -1,2 +0,2 @@ | ||
/* eslint-disable no-param-reassign */ export const createBlocksMap = (data)=>{ | ||
export const createBlocksMap = (data)=>{ | ||
const blocksMap = {}; | ||
@@ -8,3 +8,5 @@ Object.entries(data).forEach(([key, rows])=>{ | ||
if ('_path' in row) { | ||
if (!(row._path in blocksMap)) blocksMap[row._path] = []; | ||
if (!(row._path in blocksMap)) { | ||
blocksMap[row._path] = []; | ||
} | ||
row.blockType = blockType; | ||
@@ -11,0 +13,0 @@ blocksMap[row._path].push(row); |
@@ -11,3 +11,5 @@ // Flatten rows to object with path keys | ||
delete formattedRow.path; | ||
if (!res[row.path]) res[row.path] = []; | ||
if (!res[row.path]) { | ||
res[row.path] = []; | ||
} | ||
res[row.path].push(row); | ||
@@ -14,0 +16,0 @@ return res; |
@@ -5,6 +5,14 @@ import { fieldAffectsData, fieldHasSubFields } from 'payload/shared'; | ||
// arrays always get a separate table | ||
if (field.type === 'array') return false; | ||
if (fieldAffectsData(field) && field.localized) return true; | ||
if (fieldHasSubFields(field)) return hasLocalesTable(field.fields); | ||
if (field.type === 'tabs') return field.tabs.some((tab)=>hasLocalesTable(tab.fields)); | ||
if (field.type === 'array') { | ||
return false; | ||
} | ||
if (fieldAffectsData(field) && field.localized) { | ||
return true; | ||
} | ||
if (fieldHasSubFields(field)) { | ||
return hasLocalesTable(field.fields); | ||
} | ||
if (field.type === 'tabs') { | ||
return field.tabs.some((tab)=>hasLocalesTable(tab.fields)); | ||
} | ||
return false; | ||
@@ -11,0 +19,0 @@ }); |
{ | ||
"name": "@payloadcms/drizzle", | ||
"version": "3.0.0-canary.79e92af", | ||
"version": "3.0.0-canary.81a972d", | ||
"description": "A library of shared functions used by different payload database adapters", | ||
@@ -48,7 +48,7 @@ "homepage": "https://payloadcms.com", | ||
"@types/to-snake-case": "1.0.0", | ||
"@payloadcms/eslint-config": "3.0.0-beta.59", | ||
"payload": "3.0.0-canary.79e92af" | ||
"@payloadcms/eslint-config": "3.0.0-beta.97", | ||
"payload": "3.0.0-canary.81a972d" | ||
}, | ||
"peerDependencies": { | ||
"payload": "3.0.0-canary.79e92af" | ||
"payload": "3.0.0-canary.81a972d" | ||
}, | ||
@@ -59,4 +59,6 @@ "scripts": { | ||
"build:types": "tsc --emitDeclarationOnly --outDir dist", | ||
"clean": "rimraf {dist,*.tsbuildinfo}" | ||
"clean": "rimraf {dist,*.tsbuildinfo}", | ||
"lint": "eslint .", | ||
"lint:fix": "eslint . --fix" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
843648
390
7677