hunk.code_window:   useSensor,
     useSensors,
   } from '@dnd-kit/core';
   import { Workspace } from '@toeverything/infra';
   import { useService } from '@toeverything/infra/di';
   import { useAtom, useAtomValue, useSetAtom } from 'jotai';
   import type { PropsWithChildren, ReactNode } from 'react';
   import { lazy, Suspense, useCallback, useEffect, useState } from 'react';
  
hunk.labels: keep keep keep replace keep keep keep keep
hunk.after_edit: import { PageRecordList, useLiveData, Workspace } from '@toeverything/infra';
  
hunk.file_path: packages/frontend/core/src/layouts/workspace-layout.tsx
hunk.type: replace
file: import { PrismaClient } from '@prisma/client';
  import { applyUpdate, Doc, encodeStateAsUpdate } from 'yjs';
  
  import { DocID } from '../../core/utils/doc';
  
  export class Guid1698398506533 {
    // do the migration
    static async up(db: PrismaClient) {
      let turn = 0;
      let lastTurnCount = 100;
      while (lastTurnCount === 100) {
        const docs = await db.snapshot.findMany({
          select: {
            workspaceId: true,
            id: true,
          },
          skip: turn * 100,
          take: 100,
          orderBy: {
            createdAt: 'asc',
          },
        });
  
        lastTurnCount = docs.length;
        for (const doc of docs) {
          const docId = new DocID(doc.id, doc.workspaceId);
  
          // NOTE:
          // `doc.id` could be 'space:xxx' or 'xxx'
          // `docId.guid` is always 'xxx'
          // what we want achieve is:
          //   if both 'space:xxx' and 'xxx' exist, merge 'space:xxx' to 'xxx' and delete it
          //   else just modify 'space:xxx' to 'xxx'
  
          if (docId && !docId.isWorkspace && docId.guid !== doc.id) {
            const existingUpdate = await db.snapshot.findFirst({
              where: {
                id: docId.guid,
                workspaceId: doc.workspaceId,
              },
              select: {
                blob: true,
              },
            });
  
            // we have missing update with wrong id used before and need to be recovered
            if (existingUpdate) {
              const toBeMergeUpdate = await db.snapshot.findFirst({
                // id 'space:xxx'
                where: {
                  id: doc.id,
                  workspaceId: doc.workspaceId,
                },
                select: {
                  blob: true,
                },
              });
  
              // no conflict
              // actually unreachable path
              if (!toBeMergeUpdate) {
                continue;
              }
  
              // recover
              const yDoc = new Doc();
              applyUpdate(yDoc, toBeMergeUpdate.blob);
              applyUpdate(yDoc, existingUpdate.blob);
              const update = encodeStateAsUpdate(yDoc);
  
              await db.$transaction([
                // we already have 'xxx', delete 'space:xxx'
                db.snapshot.deleteMany({
                  where: {
                    id: doc.id,
                    workspaceId: doc.workspaceId,
                  },
                }),
                db.snapshot.update({
                  where: {
                    id_workspaceId: {
                      id: docId.guid,
                      workspaceId: doc.workspaceId,
                    },
                  },
                  data: {
                    blob: Buffer.from(update),
                  },
                }),
              ]);
            } else {
              // there is no updates need to be merged
              // just modify the id the required one
              await db.snapshot.update({
                where: {
                  id_workspaceId: {
                    id: doc.id,
                    workspaceId: doc.workspaceId,
                  },
                },
                data: {
                  id: docId.guid,
                },
              });
            }
          }
        }
  
        turn++;
      }
    }
  
    // revert the migration
    static async down() {
      //
    }
  }
  