mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-15 01:21:09 +02:00
- Add uload project with apps/web structure
- Reorganize from flat to monorepo structure
- Remove PocketBase binary and local data
- Update to pnpm and @uload/web namespace
- Add picture project to monorepo
- Remove embedded git repository
- Unify all package names to @{project}/{app} schema:
- @maerchenzauber/* (was @storyteller/*)
- @manacore/* (was manacore-*, manacore)
- @manadeck/* (was web, backend, manadeck)
- @memoro/* (was memoro-web, landing, memoro)
- @picture/* (already unified)
- @uload/web
- Add convenient dev scripts for all apps:
- pnpm dev:{project}:web
- pnpm dev:{project}:landing
- pnpm dev:{project}:mobile
- pnpm dev:{project}:backend
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
157 lines
No EOL
5.1 KiB
JavaScript
157 lines
No EOL
5.1 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Migration script to convert from shared_access to workspace system
|
|
* Run this after deploying the new workspace collections
|
|
*/
|
|
|
|
import PocketBase from 'pocketbase';
|
|
import dotenv from 'dotenv';
|
|
|
|
// Load environment variables
|
|
dotenv.config({ path: '.env.production' });
|
|
|
|
const pb = new PocketBase(process.env.PUBLIC_POCKETBASE_URL || 'https://pb.ulo.ad');
|
|
|
|
async function migrate() {
|
|
console.log('Starting migration to workspace system...');
|
|
|
|
try {
|
|
// Authenticate as admin
|
|
const adminEmail = process.env.ADMIN_EMAIL;
|
|
const adminPassword = process.env.ADMIN_PASSWORD;
|
|
|
|
if (!adminEmail || !adminPassword) {
|
|
console.error('Please set ADMIN_EMAIL and ADMIN_PASSWORD in .env.production');
|
|
process.exit(1);
|
|
}
|
|
|
|
await pb.admins.authWithPassword(adminEmail, adminPassword);
|
|
console.log('✓ Authenticated as admin');
|
|
|
|
// Get all users
|
|
const users = await pb.collection('users').getFullList();
|
|
console.log(`Found ${users.length} users to migrate`);
|
|
|
|
// Create personal workspace for each user
|
|
for (const user of users) {
|
|
try {
|
|
// Check if personal workspace already exists
|
|
const existingWorkspaces = await pb.collection('workspaces').getList(1, 1, {
|
|
filter: `owner="${user.id}" && type="personal"`
|
|
});
|
|
|
|
if (existingWorkspaces.items.length === 0) {
|
|
// Create personal workspace
|
|
const workspace = await pb.collection('workspaces').create({
|
|
name: `${user.name || user.email}'s Workspace`,
|
|
owner: user.id,
|
|
type: 'personal',
|
|
subscription_status: user.subscription_status || 'free',
|
|
description: 'Personal workspace'
|
|
});
|
|
|
|
console.log(`✓ Created personal workspace for ${user.email}`);
|
|
|
|
// Add user as owner in workspace_members
|
|
await pb.collection('workspace_members').create({
|
|
workspace: workspace.id,
|
|
user: user.id,
|
|
role: 'owner',
|
|
invitation_status: 'accepted',
|
|
accepted_at: new Date().toISOString()
|
|
});
|
|
} else {
|
|
console.log(`- Personal workspace already exists for ${user.email}`);
|
|
}
|
|
} catch (error) {
|
|
console.error(`✗ Error creating workspace for ${user.email}:`, error.message);
|
|
}
|
|
}
|
|
|
|
// Migrate shared_access to workspace_members
|
|
console.log('\nMigrating shared access...');
|
|
|
|
try {
|
|
const sharedAccess = await pb.collection('shared_access').getFullList({
|
|
expand: 'owner,user'
|
|
});
|
|
|
|
console.log(`Found ${sharedAccess.length} shared access records`);
|
|
|
|
for (const access of sharedAccess) {
|
|
try {
|
|
// Find or create team workspace for the owner
|
|
let teamWorkspace;
|
|
const existingTeamWorkspaces = await pb.collection('workspaces').getList(1, 1, {
|
|
filter: `owner="${access.owner}" && type="team"`
|
|
});
|
|
|
|
if (existingTeamWorkspaces.items.length === 0) {
|
|
// Create team workspace
|
|
const ownerData = access.expand?.owner;
|
|
teamWorkspace = await pb.collection('workspaces').create({
|
|
name: `${ownerData?.name || ownerData?.email}'s Team`,
|
|
owner: access.owner,
|
|
type: 'team',
|
|
description: 'Team workspace for collaboration'
|
|
});
|
|
|
|
console.log(`✓ Created team workspace for owner ${access.owner}`);
|
|
|
|
// Add owner as owner in workspace_members
|
|
await pb.collection('workspace_members').create({
|
|
workspace: teamWorkspace.id,
|
|
user: access.owner,
|
|
role: 'owner',
|
|
invitation_status: 'accepted',
|
|
accepted_at: new Date().toISOString()
|
|
});
|
|
} else {
|
|
teamWorkspace = existingTeamWorkspaces.items[0];
|
|
}
|
|
|
|
// Check if member already exists
|
|
const existingMembers = await pb.collection('workspace_members').getList(1, 1, {
|
|
filter: `workspace="${teamWorkspace.id}" && user="${access.user}"`
|
|
});
|
|
|
|
if (existingMembers.items.length === 0) {
|
|
// Add team member
|
|
await pb.collection('workspace_members').create({
|
|
workspace: teamWorkspace.id,
|
|
user: access.user,
|
|
role: access.permissions?.manage_team ? 'admin' : 'member',
|
|
permissions: access.permissions,
|
|
invitation_status: access.invitation_status,
|
|
invitation_token: access.invitation_token,
|
|
invited_at: access.invited_at,
|
|
accepted_at: access.accepted_at
|
|
});
|
|
|
|
console.log(`✓ Migrated team member ${access.user} to workspace ${teamWorkspace.id}`);
|
|
} else {
|
|
console.log(`- Team member ${access.user} already exists in workspace`);
|
|
}
|
|
} catch (error) {
|
|
console.error(`✗ Error migrating shared access ${access.id}:`, error.message);
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('✗ Error fetching shared access:', error.message);
|
|
}
|
|
|
|
console.log('\n✅ Migration completed successfully!');
|
|
console.log('\nNext steps:');
|
|
console.log('1. Test the new workspace system');
|
|
console.log('2. Update any links/cards to reference workspace instead of owner');
|
|
console.log('3. Once verified, you can remove the old shared_access collection');
|
|
|
|
} catch (error) {
|
|
console.error('✗ Migration failed:', error);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
// Run migration
|
|
migrate().catch(console.error); |