@payloadcms/drizzle 3.73.0-internal.e61e2ce → 3.73.0-internal.ff401d9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/findDistinct.d.ts.map +1 -1
- package/dist/findDistinct.js +23 -4
- package/dist/findDistinct.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/postgres/createJSONQuery/index.d.ts.map +1 -1
- package/dist/postgres/createJSONQuery/index.js +7 -19
- package/dist/postgres/createJSONQuery/index.js.map +1 -1
- package/dist/queries/parseParams.d.ts.map +1 -1
- package/dist/queries/parseParams.js +4 -5
- package/dist/queries/parseParams.js.map +1 -1
- package/dist/queries/selectDistinct.d.ts +2 -1
- package/dist/queries/selectDistinct.d.ts.map +1 -1
- package/dist/queries/selectDistinct.js +11 -7
- package/dist/queries/selectDistinct.js.map +1 -1
- package/dist/sqlite/createJSONQuery/index.d.ts.map +1 -1
- package/dist/sqlite/createJSONQuery/index.js +1 -2
- package/dist/sqlite/createJSONQuery/index.js.map +1 -1
- package/dist/types.d.ts +0 -34
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utilities/buildCreateMigration.d.ts.map +1 -1
- package/dist/utilities/buildCreateMigration.js +2 -20
- package/dist/utilities/buildCreateMigration.js.map +1 -1
- package/package.json +4 -4
- package/dist/utilities/blocksToJsonMigrator.d.ts +0 -15
- package/dist/utilities/blocksToJsonMigrator.d.ts.map +0 -1
- package/dist/utilities/blocksToJsonMigrator.js +0 -595
- package/dist/utilities/blocksToJsonMigrator.js.map +0 -1
- package/dist/utilities/escapeSQLValue.d.ts +0 -3
- package/dist/utilities/escapeSQLValue.d.ts.map +0 -1
- package/dist/utilities/escapeSQLValue.js +0 -20
- package/dist/utilities/escapeSQLValue.js.map +0 -1
|
@@ -1,595 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { APIError, buildVersionCollectionFields, buildVersionGlobalFields, dynamicImport } from 'payload';
|
|
4
|
-
import { findConfig } from 'payload/node';
|
|
5
|
-
import { fieldShouldBeLocalized } from 'payload/shared';
|
|
6
|
-
import * as ts from 'typescript';
|
|
7
|
-
import { getTransaction } from './getTransaction.js';
|
|
8
|
-
const DEFAULT_BATCH_SIZE = 100;
|
|
9
|
-
const TEMP_FOLDER_NAME = '.payload-blocks-migration';
|
|
10
|
-
const writeEntitiesToTempFile = (entities, tempFolderPath, batchIndex)=>{
|
|
11
|
-
const filePath = path.join(tempFolderPath, `entities-batch-${batchIndex}.json`);
|
|
12
|
-
writeFileSync(filePath, JSON.stringify(entities, null, 2), 'utf-8');
|
|
13
|
-
};
|
|
14
|
-
const acceptDrizzlePrompts = async (callPrompt, { silenceLogs = false } = {})=>{
|
|
15
|
-
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
16
|
-
const write = process.stdout.write;
|
|
17
|
-
if (silenceLogs) {
|
|
18
|
-
process.stdout.write = ()=>true;
|
|
19
|
-
}
|
|
20
|
-
const promise = callPrompt();
|
|
21
|
-
const interval = setInterval(()=>process.stdin.emit('keypress', '\n', {
|
|
22
|
-
name: 'return',
|
|
23
|
-
ctrl: false
|
|
24
|
-
}), 25);
|
|
25
|
-
const res = await promise;
|
|
26
|
-
if (silenceLogs) {
|
|
27
|
-
process.stdout.write = write;
|
|
28
|
-
}
|
|
29
|
-
clearInterval(interval);
|
|
30
|
-
return res;
|
|
31
|
-
};
|
|
32
|
-
const entityHasBlocksField = (entity)=>{
|
|
33
|
-
for (const field of entity.flattenedFields){
|
|
34
|
-
if (field.type === 'blocks') {
|
|
35
|
-
return true;
|
|
36
|
-
}
|
|
37
|
-
if ('flattenedFields' in field && entityHasBlocksField({
|
|
38
|
-
flattenedFields: field.flattenedFields
|
|
39
|
-
})) {
|
|
40
|
-
return true;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
return false;
|
|
44
|
-
};
|
|
45
|
-
const collectBlocksToMigrate = ({ config, data, fields, parentAccessor, parentIsLocalized })=>{
|
|
46
|
-
const result = [];
|
|
47
|
-
for (const field of fields){
|
|
48
|
-
switch(field.type){
|
|
49
|
-
case 'array':
|
|
50
|
-
{
|
|
51
|
-
const arrayData = data[field.name];
|
|
52
|
-
if (!Array.isArray(arrayData)) {
|
|
53
|
-
continue;
|
|
54
|
-
}
|
|
55
|
-
if (config.localization && fieldShouldBeLocalized({
|
|
56
|
-
field,
|
|
57
|
-
parentIsLocalized
|
|
58
|
-
})) {
|
|
59
|
-
result.push(...collectBlocksToMigrate({
|
|
60
|
-
config,
|
|
61
|
-
data: arrayData,
|
|
62
|
-
fields: config.localization.localeCodes.map((code)=>({
|
|
63
|
-
...field,
|
|
64
|
-
name: code,
|
|
65
|
-
localized: false
|
|
66
|
-
})),
|
|
67
|
-
parentAccessor: [
|
|
68
|
-
...parentAccessor,
|
|
69
|
-
field.name
|
|
70
|
-
],
|
|
71
|
-
parentIsLocalized: true
|
|
72
|
-
}));
|
|
73
|
-
continue;
|
|
74
|
-
}
|
|
75
|
-
for (const [index, row] of arrayData.entries()){
|
|
76
|
-
result.push(...collectBlocksToMigrate({
|
|
77
|
-
config,
|
|
78
|
-
data: row,
|
|
79
|
-
fields: field.flattenedFields,
|
|
80
|
-
parentAccessor: [
|
|
81
|
-
...parentAccessor,
|
|
82
|
-
field.name,
|
|
83
|
-
index
|
|
84
|
-
],
|
|
85
|
-
parentIsLocalized
|
|
86
|
-
}));
|
|
87
|
-
}
|
|
88
|
-
break;
|
|
89
|
-
}
|
|
90
|
-
case 'blocks':
|
|
91
|
-
{
|
|
92
|
-
result.push({
|
|
93
|
-
data: data[field.name],
|
|
94
|
-
fieldAccessor: [
|
|
95
|
-
...parentAccessor,
|
|
96
|
-
field.name
|
|
97
|
-
]
|
|
98
|
-
});
|
|
99
|
-
break;
|
|
100
|
-
}
|
|
101
|
-
case 'group':
|
|
102
|
-
case 'tab':
|
|
103
|
-
{
|
|
104
|
-
if (config.localization && fieldShouldBeLocalized({
|
|
105
|
-
field,
|
|
106
|
-
parentIsLocalized
|
|
107
|
-
})) {
|
|
108
|
-
result.push(...collectBlocksToMigrate({
|
|
109
|
-
config,
|
|
110
|
-
data: data[field.name],
|
|
111
|
-
fields: config.localization.localeCodes.map((code)=>({
|
|
112
|
-
...field,
|
|
113
|
-
name: code,
|
|
114
|
-
localized: false
|
|
115
|
-
})),
|
|
116
|
-
parentAccessor: [
|
|
117
|
-
...parentAccessor,
|
|
118
|
-
field.name
|
|
119
|
-
],
|
|
120
|
-
parentIsLocalized: true
|
|
121
|
-
}));
|
|
122
|
-
continue;
|
|
123
|
-
}
|
|
124
|
-
result.push(...collectBlocksToMigrate({
|
|
125
|
-
config,
|
|
126
|
-
data: data[field.name],
|
|
127
|
-
fields: field.flattenedFields,
|
|
128
|
-
parentAccessor: [
|
|
129
|
-
...parentAccessor,
|
|
130
|
-
field.name
|
|
131
|
-
],
|
|
132
|
-
parentIsLocalized
|
|
133
|
-
}));
|
|
134
|
-
break;
|
|
135
|
-
}
|
|
136
|
-
default:
|
|
137
|
-
{
|
|
138
|
-
continue;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
return result;
|
|
143
|
-
};
|
|
144
|
-
class BlocksToJsonMigratorImpl {
|
|
145
|
-
adapter;
|
|
146
|
-
sanitizeStatements;
|
|
147
|
-
executeMethod;
|
|
148
|
-
batchSize;
|
|
149
|
-
tempFolderPath;
|
|
150
|
-
constructor(adapter, sanitizeStatements, executeMethod, batchSize){
|
|
151
|
-
this.adapter = adapter;
|
|
152
|
-
this.sanitizeStatements = sanitizeStatements;
|
|
153
|
-
this.executeMethod = executeMethod;
|
|
154
|
-
this.batchSize = batchSize || DEFAULT_BATCH_SIZE;
|
|
155
|
-
this.tempFolderPath = path.resolve(this.adapter.migrationDir, TEMP_FOLDER_NAME);
|
|
156
|
-
}
|
|
157
|
-
ensureTempFolder() {
|
|
158
|
-
if (!existsSync(this.tempFolderPath)) {
|
|
159
|
-
mkdirSync(this.tempFolderPath, {
|
|
160
|
-
recursive: true
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
*fetchEntitiesFromJsonBatches() {
|
|
165
|
-
if (!existsSync(this.tempFolderPath)) {
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
const files = readdirSync(this.tempFolderPath).filter((file)=>file.startsWith('entities-batch-') && file.endsWith('.json')).sort((a, b)=>{
|
|
169
|
-
const aNum = parseInt(a.match(/\d+/)?.[0] || '0', 10);
|
|
170
|
-
const bNum = parseInt(b.match(/\d+/)?.[0] || '0', 10);
|
|
171
|
-
return aNum - bNum;
|
|
172
|
-
});
|
|
173
|
-
for (const file of files){
|
|
174
|
-
const filePath = path.join(this.tempFolderPath, file);
|
|
175
|
-
const fileContent = readFileSync(filePath, 'utf-8');
|
|
176
|
-
const batchEntities = JSON.parse(fileContent);
|
|
177
|
-
yield batchEntities;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
async migrateEntities(entities, req) {
|
|
181
|
-
this.adapter.blocksAsJSON = true;
|
|
182
|
-
this.resetSchema();
|
|
183
|
-
await this.adapter.init();
|
|
184
|
-
await this.adapter.connect();
|
|
185
|
-
await this.syncTransactionDrizzleInstance(req);
|
|
186
|
-
const totalEntities = entities.length;
|
|
187
|
-
let processed = 0;
|
|
188
|
-
for (const entity of entities){
|
|
189
|
-
switch(entity.type){
|
|
190
|
-
case 'collection':
|
|
191
|
-
{
|
|
192
|
-
await this.adapter.updateOne({
|
|
193
|
-
collection: entity.slug,
|
|
194
|
-
data: entity.originalData,
|
|
195
|
-
joins: false,
|
|
196
|
-
req,
|
|
197
|
-
where: {
|
|
198
|
-
id: {
|
|
199
|
-
equals: entity.id
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
});
|
|
203
|
-
break;
|
|
204
|
-
}
|
|
205
|
-
case 'collectionVersion':
|
|
206
|
-
{
|
|
207
|
-
await this.adapter.updateVersion({
|
|
208
|
-
id: entity.id,
|
|
209
|
-
collection: entity.slug,
|
|
210
|
-
req,
|
|
211
|
-
versionData: entity.originalData
|
|
212
|
-
});
|
|
213
|
-
break;
|
|
214
|
-
}
|
|
215
|
-
case 'global':
|
|
216
|
-
{
|
|
217
|
-
await this.adapter.updateGlobal({
|
|
218
|
-
slug: entity.slug,
|
|
219
|
-
data: entity.originalData,
|
|
220
|
-
req
|
|
221
|
-
});
|
|
222
|
-
break;
|
|
223
|
-
}
|
|
224
|
-
case 'globalVersion':
|
|
225
|
-
{
|
|
226
|
-
await this.adapter.updateGlobalVersion({
|
|
227
|
-
id: entity.id,
|
|
228
|
-
global: entity.slug,
|
|
229
|
-
req,
|
|
230
|
-
versionData: entity.originalData
|
|
231
|
-
});
|
|
232
|
-
break;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
processed++;
|
|
236
|
-
if (processed % this.batchSize === 0 || processed === totalEntities) {
|
|
237
|
-
this.adapter.payload.logger.info(`Migrated ${processed}/${totalEntities} entities (${Math.round(processed / totalEntities * 100)}%)`);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
resetSchema() {
|
|
242
|
-
this.adapter.schema = {};
|
|
243
|
-
this.adapter.tables = {};
|
|
244
|
-
this.adapter.indexes = new Set();
|
|
245
|
-
this.adapter.foreignKeys = new Set();
|
|
246
|
-
this.adapter.relations = {};
|
|
247
|
-
this.adapter.rawTables = {};
|
|
248
|
-
this.adapter.rawRelations = {};
|
|
249
|
-
this.adapter.tableNameMap = new Map();
|
|
250
|
-
}
|
|
251
|
-
async syncTransactionDrizzleInstance(req) {
|
|
252
|
-
const tsx = await getTransaction(this.adapter, req);
|
|
253
|
-
tsx._ = this.adapter.drizzle._;
|
|
254
|
-
tsx.schema = this.adapter.drizzle._;
|
|
255
|
-
tsx.session.schema = this.adapter.drizzle.session.schema;
|
|
256
|
-
}
|
|
257
|
-
cleanupTempFolder() {
|
|
258
|
-
rmSync(this.tempFolderPath, {
|
|
259
|
-
force: true,
|
|
260
|
-
recursive: true
|
|
261
|
-
});
|
|
262
|
-
this.adapter.payload.logger.info(`Cleaned up temp folder at ${this.tempFolderPath}`);
|
|
263
|
-
}
|
|
264
|
-
async collectAndSaveEntitiesToBatches(req, options) {
|
|
265
|
-
const batchSize = options?.batchSize ?? this.batchSize;
|
|
266
|
-
this.cleanupTempFolder();
|
|
267
|
-
this.ensureTempFolder();
|
|
268
|
-
this.adapter.blocksAsJSON = false;
|
|
269
|
-
this.resetSchema();
|
|
270
|
-
await this.adapter.init();
|
|
271
|
-
await this.adapter.connect();
|
|
272
|
-
// Count total entities to migrate
|
|
273
|
-
let totalExpected = 0;
|
|
274
|
-
for (const collection of this.adapter.payload.config.collections.filter(entityHasBlocksField)){
|
|
275
|
-
const { totalDocs } = await this.adapter.count({
|
|
276
|
-
collection: collection.slug
|
|
277
|
-
});
|
|
278
|
-
totalExpected += totalDocs;
|
|
279
|
-
if (collection.versions) {
|
|
280
|
-
const { totalDocs: totalVersions } = await this.adapter.countVersions({
|
|
281
|
-
collection: collection.slug
|
|
282
|
-
});
|
|
283
|
-
totalExpected += totalVersions;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
for (const globalConfig of this.adapter.payload.config.globals.filter(entityHasBlocksField)){
|
|
287
|
-
totalExpected += 1; // Global itself
|
|
288
|
-
if (globalConfig.versions) {
|
|
289
|
-
const { totalDocs: totalGlobalVersions } = await this.adapter.countGlobalVersions({
|
|
290
|
-
global: globalConfig.slug
|
|
291
|
-
});
|
|
292
|
-
totalExpected += totalGlobalVersions;
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
this.adapter.payload.logger.info(`Found ${totalExpected} total entities to collect and save to batches`);
|
|
296
|
-
let batchIndex = 0;
|
|
297
|
-
let currentBatch = [];
|
|
298
|
-
let totalCollected = 0;
|
|
299
|
-
const flushBatch = ()=>{
|
|
300
|
-
if (currentBatch.length > 0) {
|
|
301
|
-
writeEntitiesToTempFile(currentBatch, this.tempFolderPath, batchIndex);
|
|
302
|
-
const percentage = totalExpected > 0 ? Math.round(totalCollected / totalExpected * 100) : 0;
|
|
303
|
-
this.adapter.payload.logger.info(`Saved batch ${batchIndex} with ${currentBatch.length} entities (${totalCollected}/${totalExpected} - ${percentage}%)`);
|
|
304
|
-
batchIndex++;
|
|
305
|
-
currentBatch = [];
|
|
306
|
-
}
|
|
307
|
-
};
|
|
308
|
-
const addEntity = (entity)=>{
|
|
309
|
-
currentBatch.push(entity);
|
|
310
|
-
totalCollected++;
|
|
311
|
-
if (currentBatch.length >= batchSize) {
|
|
312
|
-
flushBatch();
|
|
313
|
-
}
|
|
314
|
-
};
|
|
315
|
-
for (const collection of this.adapter.payload.config.collections.filter(entityHasBlocksField)){
|
|
316
|
-
let page = 1;
|
|
317
|
-
let hasMore = true;
|
|
318
|
-
while(hasMore){
|
|
319
|
-
const { docs, hasNextPage } = await this.adapter.find({
|
|
320
|
-
collection: collection.slug,
|
|
321
|
-
limit: batchSize,
|
|
322
|
-
page
|
|
323
|
-
});
|
|
324
|
-
for (const doc of docs){
|
|
325
|
-
const entity = {
|
|
326
|
-
id: doc.id,
|
|
327
|
-
slug: collection.slug,
|
|
328
|
-
type: 'collection',
|
|
329
|
-
blocks: collectBlocksToMigrate({
|
|
330
|
-
config: this.adapter.payload.config,
|
|
331
|
-
data: doc,
|
|
332
|
-
fields: collection.flattenedFields,
|
|
333
|
-
parentAccessor: [],
|
|
334
|
-
parentIsLocalized: false
|
|
335
|
-
}),
|
|
336
|
-
originalData: doc
|
|
337
|
-
};
|
|
338
|
-
addEntity(entity);
|
|
339
|
-
}
|
|
340
|
-
this.adapter.payload.logger.info(`Collected ${docs.length} entries from ${collection.slug} (page ${page})`);
|
|
341
|
-
hasMore = hasNextPage;
|
|
342
|
-
page++;
|
|
343
|
-
}
|
|
344
|
-
if (collection.versions) {
|
|
345
|
-
let versionPage = 1;
|
|
346
|
-
let hasMoreVersions = true;
|
|
347
|
-
while(hasMoreVersions){
|
|
348
|
-
const { docs: versionDocs, hasNextPage: hasNextVersionPage } = await this.adapter.findVersions({
|
|
349
|
-
collection: collection.slug,
|
|
350
|
-
limit: batchSize,
|
|
351
|
-
page: versionPage
|
|
352
|
-
});
|
|
353
|
-
for (const versionDoc of versionDocs){
|
|
354
|
-
const entity = {
|
|
355
|
-
id: versionDoc.id,
|
|
356
|
-
slug: collection.slug,
|
|
357
|
-
type: 'collectionVersion',
|
|
358
|
-
blocks: collectBlocksToMigrate({
|
|
359
|
-
config: this.adapter.payload.config,
|
|
360
|
-
data: versionDoc,
|
|
361
|
-
fields: buildVersionCollectionFields(this.adapter.payload.config, collection, true),
|
|
362
|
-
parentAccessor: [],
|
|
363
|
-
parentIsLocalized: false
|
|
364
|
-
}),
|
|
365
|
-
originalData: versionDoc
|
|
366
|
-
};
|
|
367
|
-
addEntity(entity);
|
|
368
|
-
}
|
|
369
|
-
this.adapter.payload.logger.info(`Collected ${versionDocs.length} versions from ${collection.slug} (page ${versionPage})`);
|
|
370
|
-
hasMoreVersions = hasNextVersionPage;
|
|
371
|
-
versionPage++;
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
for (const globalConfig of this.adapter.payload.config.globals.filter(entityHasBlocksField)){
|
|
376
|
-
const globalDoc = await this.adapter.findGlobal({
|
|
377
|
-
slug: globalConfig.slug
|
|
378
|
-
});
|
|
379
|
-
const entity = {
|
|
380
|
-
slug: globalConfig.slug,
|
|
381
|
-
type: 'global',
|
|
382
|
-
blocks: collectBlocksToMigrate({
|
|
383
|
-
config: this.adapter.payload.config,
|
|
384
|
-
data: globalDoc,
|
|
385
|
-
fields: globalConfig.flattenedFields,
|
|
386
|
-
parentAccessor: [],
|
|
387
|
-
parentIsLocalized: false
|
|
388
|
-
}),
|
|
389
|
-
originalData: globalDoc
|
|
390
|
-
};
|
|
391
|
-
addEntity(entity);
|
|
392
|
-
this.adapter.payload.logger.info(`Collected global ${globalConfig.slug}`);
|
|
393
|
-
if (globalConfig.versions) {
|
|
394
|
-
let globalVersionPage = 1;
|
|
395
|
-
let hasMoreGlobalVersions = true;
|
|
396
|
-
while(hasMoreGlobalVersions){
|
|
397
|
-
const { docs: globalVersionDocs, hasNextPage: hasNextGlobalVersionPage } = await this.adapter.findGlobalVersions({
|
|
398
|
-
global: globalConfig.slug,
|
|
399
|
-
limit: batchSize,
|
|
400
|
-
page: globalVersionPage
|
|
401
|
-
});
|
|
402
|
-
for (const globalVersionDoc of globalVersionDocs){
|
|
403
|
-
const entity = {
|
|
404
|
-
id: globalVersionDoc.id,
|
|
405
|
-
slug: globalConfig.slug,
|
|
406
|
-
type: 'globalVersion',
|
|
407
|
-
blocks: collectBlocksToMigrate({
|
|
408
|
-
config: this.adapter.payload.config,
|
|
409
|
-
data: globalVersionDoc,
|
|
410
|
-
fields: buildVersionGlobalFields(this.adapter.payload.config, globalConfig, true),
|
|
411
|
-
parentAccessor: [],
|
|
412
|
-
parentIsLocalized: false
|
|
413
|
-
}),
|
|
414
|
-
originalData: globalVersionDoc
|
|
415
|
-
};
|
|
416
|
-
addEntity(entity);
|
|
417
|
-
}
|
|
418
|
-
this.adapter.payload.logger.info(`Collected ${globalVersionDocs.length} versions from global ${globalConfig.slug} (page ${globalVersionPage})`);
|
|
419
|
-
hasMoreGlobalVersions = hasNextGlobalVersionPage;
|
|
420
|
-
globalVersionPage++;
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
flushBatch();
|
|
425
|
-
this.adapter.payload.logger.info(`Collected total of ${totalCollected} entities across ${batchIndex} batches`);
|
|
426
|
-
}
|
|
427
|
-
async getMigrationStatements() {
|
|
428
|
-
const { generateDrizzleJson, generateMigration } = this.adapter.requireDrizzleKit();
|
|
429
|
-
const drizzleJsonBefore = await generateDrizzleJson(this.adapter.schema);
|
|
430
|
-
this.adapter.blocksAsJSON = true;
|
|
431
|
-
this.resetSchema();
|
|
432
|
-
await this.adapter.init();
|
|
433
|
-
const drizzleJsonAfter = await generateDrizzleJson(this.adapter.schema);
|
|
434
|
-
this.adapter.blocksAsJSON = false;
|
|
435
|
-
this.resetSchema();
|
|
436
|
-
await this.adapter.init();
|
|
437
|
-
const statements = await acceptDrizzlePrompts(()=>generateMigration(drizzleJsonBefore, drizzleJsonAfter), {
|
|
438
|
-
silenceLogs: true
|
|
439
|
-
});
|
|
440
|
-
const sqlExecute = `await db.${this.executeMethod}(` + 'sql`';
|
|
441
|
-
return {
|
|
442
|
-
add: this.sanitizeStatements({
|
|
443
|
-
sqlExecute,
|
|
444
|
-
statements: statements.filter((stmt)=>!stmt.startsWith('DROP'))
|
|
445
|
-
}),
|
|
446
|
-
remove: this.sanitizeStatements({
|
|
447
|
-
sqlExecute,
|
|
448
|
-
statements: [
|
|
449
|
-
...statements.filter((stmt)=>stmt.startsWith('DROP'))
|
|
450
|
-
]
|
|
451
|
-
}),
|
|
452
|
-
writeDrizzleSnapshot (filePath) {
|
|
453
|
-
writeFileSync(`${filePath}.json`, JSON.stringify(drizzleJsonAfter, null, 2));
|
|
454
|
-
}
|
|
455
|
-
};
|
|
456
|
-
}
|
|
457
|
-
async migrateEntitiesFromTempFolder(req, options) {
|
|
458
|
-
const clearBatches = options?.clearBatches ?? true;
|
|
459
|
-
let totalEntities = 0;
|
|
460
|
-
let hasEntities = false;
|
|
461
|
-
for (const entities of this.fetchEntitiesFromJsonBatches()){
|
|
462
|
-
hasEntities = true;
|
|
463
|
-
totalEntities += entities.length;
|
|
464
|
-
this.adapter.payload.logger.info(`Migrating batch with ${entities.length} entities (total: ${totalEntities})`);
|
|
465
|
-
await this.migrateEntities(entities, req);
|
|
466
|
-
}
|
|
467
|
-
if (!hasEntities) {
|
|
468
|
-
this.adapter.payload.logger.warn('No entities found in temp folder to migrate');
|
|
469
|
-
return;
|
|
470
|
-
}
|
|
471
|
-
this.adapter.payload.logger.info(`Completed migration of ${totalEntities} entities from temp folder`);
|
|
472
|
-
if (clearBatches) {
|
|
473
|
-
this.cleanupTempFolder();
|
|
474
|
-
} else {
|
|
475
|
-
this.adapter.payload.logger.info(`Temp folder preserved at ${this.tempFolderPath} (clearBatches: false)`);
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
setTempFolder(tempFolderPath) {
|
|
479
|
-
this.tempFolderPath = tempFolderPath;
|
|
480
|
-
}
|
|
481
|
-
async updatePayloadConfigFile() {
|
|
482
|
-
let configPath;
|
|
483
|
-
try {
|
|
484
|
-
configPath = findConfig();
|
|
485
|
-
} catch {
|
|
486
|
-
this.adapter.payload.logger.info('updatePayloadConfigFile failed - could not find the payload config. Please set the blocksAsJSON DB adapter property manually to "true"');
|
|
487
|
-
return;
|
|
488
|
-
}
|
|
489
|
-
const configFile = readFileSync(configPath, 'utf-8');
|
|
490
|
-
const source = ts.createSourceFile(configPath, configFile, ts.ScriptTarget.ESNext);
|
|
491
|
-
let hadChanges = false;
|
|
492
|
-
const result = ts.transform(source, [
|
|
493
|
-
(ctx)=>(sourceFile)=>{
|
|
494
|
-
const factory = ctx.factory;
|
|
495
|
-
const visit = (node)=>{
|
|
496
|
-
if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name) && node.name.text === 'db' && ts.isCallExpression(node.initializer) && node.initializer.arguments.length > 0 && ts.isObjectLiteralExpression(node.initializer.arguments[0])) {
|
|
497
|
-
const call = node.initializer;
|
|
498
|
-
const obj = node.initializer.arguments[0];
|
|
499
|
-
const filteredProps = obj.properties.filter((prop)=>{
|
|
500
|
-
if (!ts.isPropertyAssignment(prop)) {
|
|
501
|
-
return true;
|
|
502
|
-
}
|
|
503
|
-
return !(ts.isIdentifier(prop.name) && prop.name.text === 'blocksAsJSON');
|
|
504
|
-
});
|
|
505
|
-
const newProperty = factory.createPropertyAssignment('blocksAsJSON', factory.createTrue());
|
|
506
|
-
hadChanges = true;
|
|
507
|
-
const newObject = factory.updateObjectLiteralExpression(obj, [
|
|
508
|
-
...filteredProps,
|
|
509
|
-
newProperty
|
|
510
|
-
]);
|
|
511
|
-
const newCall = factory.updateCallExpression(call, call.expression, call.typeArguments, [
|
|
512
|
-
newObject
|
|
513
|
-
]);
|
|
514
|
-
return factory.updatePropertyAssignment(node, node.name, newCall);
|
|
515
|
-
}
|
|
516
|
-
return ts.visitEachChild(node, visit, ctx);
|
|
517
|
-
};
|
|
518
|
-
return ts.visitNode(sourceFile, visit);
|
|
519
|
-
}
|
|
520
|
-
]);
|
|
521
|
-
if (!hadChanges) {
|
|
522
|
-
this.adapter.payload.logger.info('No changes made to payload config. Set blocksAsJSON to true manually.');
|
|
523
|
-
return;
|
|
524
|
-
}
|
|
525
|
-
const printer = ts.createPrinter({
|
|
526
|
-
newLine: ts.NewLineKind.LineFeed
|
|
527
|
-
});
|
|
528
|
-
let output = printer.printFile(result.transformed[0]);
|
|
529
|
-
try {
|
|
530
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
|
531
|
-
const prettier = await dynamicImport('prettier');
|
|
532
|
-
const configPath = await prettier.resolveConfigFile();
|
|
533
|
-
const config = configPath ? await prettier.resolveConfig(configPath) : {};
|
|
534
|
-
output = await prettier.format(output, {
|
|
535
|
-
...config,
|
|
536
|
-
parser: 'typescript'
|
|
537
|
-
});
|
|
538
|
-
} catch (err) {
|
|
539
|
-
this.adapter.payload.logger.error({
|
|
540
|
-
err,
|
|
541
|
-
msg: 'Could not format payload config with Prettier'
|
|
542
|
-
});
|
|
543
|
-
}
|
|
544
|
-
writeFileSync(configPath, output, 'utf-8');
|
|
545
|
-
this.adapter.payload.logger.info(`Updated ${configPath} with blocksAsJSON: true`);
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
export const createBlocksToJsonMigrator = ({ adapter, executeMethod, sanitizeStatements })=>{
|
|
549
|
-
return new BlocksToJsonMigratorImpl(adapter, sanitizeStatements, executeMethod);
|
|
550
|
-
};
|
|
551
|
-
export const getBlocksToJsonMigrator = (payload)=>{
|
|
552
|
-
const migrator = payload.db.blocksToJsonMigrator;
|
|
553
|
-
if (!migrator) {
|
|
554
|
-
throw new APIError(`blocksToJsonMigrator is not defined for ${payload.db.packageName}`);
|
|
555
|
-
}
|
|
556
|
-
return migrator;
|
|
557
|
-
};
|
|
558
|
-
export const buildDynamicPredefinedBlocksToJsonMigration = ({ packageName })=>{
|
|
559
|
-
return async ({ filePath, payload })=>{
|
|
560
|
-
const migrator = getBlocksToJsonMigrator(payload);
|
|
561
|
-
const migrationStatements = await migrator.getMigrationStatements();
|
|
562
|
-
migrationStatements.writeDrizzleSnapshot(filePath);
|
|
563
|
-
await migrator.updatePayloadConfigFile();
|
|
564
|
-
const upSQL = `
|
|
565
|
-
const migrator = getBlocksToJsonMigrator(payload)
|
|
566
|
-
migrator.setTempFolder(TEMP_FOLDER)
|
|
567
|
-
await migrator.collectAndSaveEntitiesToBatches(req, { batchSize: BATCH_SIZE })
|
|
568
|
-
|
|
569
|
-
${migrationStatements.add}
|
|
570
|
-
payload.logger.info("Executed ADD statements for blocks-as-json migration")
|
|
571
|
-
|
|
572
|
-
await migrator.migrateEntitiesFromTempFolder(req, { clearBatches: true })
|
|
573
|
-
|
|
574
|
-
${migrationStatements.remove}
|
|
575
|
-
payload.logger.info("Executed REMOVE statements for blocks-as-json migration")
|
|
576
|
-
`;
|
|
577
|
-
return {
|
|
578
|
-
imports: `
|
|
579
|
-
import { getBlocksToJsonMigrator } from '${packageName}/migration-utils'
|
|
580
|
-
import { fileURLToPath } from 'url'
|
|
581
|
-
import path from 'path'
|
|
582
|
-
|
|
583
|
-
const filename = fileURLToPath(import.meta.url)
|
|
584
|
-
const dirname = path.dirname(filename)
|
|
585
|
-
|
|
586
|
-
// Configure migration options (optional)
|
|
587
|
-
const BATCH_SIZE = 100 // Number of entities to process per batch
|
|
588
|
-
const TEMP_FOLDER = path.resolve(dirname, '${TEMP_FOLDER_NAME}') // Folder path to store migration batch
|
|
589
|
-
`,
|
|
590
|
-
upSQL
|
|
591
|
-
};
|
|
592
|
-
};
|
|
593
|
-
};
|
|
594
|
-
|
|
595
|
-
//# sourceMappingURL=blocksToJsonMigrator.js.map
|