|
1 | 1 | import { Hono } from 'hono' |
2 | 2 | import { zValidator } from '@hono/zod-validator' |
3 | 3 | import { db, vaultKeys, spaces, type NewVaultKey } from '../db' |
4 | | -import { eq, and, sql } from 'drizzle-orm' |
| 4 | +import { eq, and } from 'drizzle-orm' |
5 | 5 | import { vaultKeySchema, updateVaultNameSchema } from './sync.schemas' |
6 | | -import { getPartitionQuotaAsync } from '../services/quota' |
7 | 6 |
|
8 | 7 | const vaultRoutes = new Hono() |
9 | 8 |
|
@@ -294,81 +293,5 @@ vaultRoutes.delete('/vaults', async (c) => { |
294 | 293 | } |
295 | 294 | }) |
296 | 295 |
|
297 | | -/** |
298 | | - * POST /partitions/create |
299 | | - * Create a new sync_changes partition with a server-generated UUID. |
300 | | - * The partition is created and committed before the response is sent, |
301 | | - * ensuring Supabase Realtime can see it when the client subscribes. |
302 | | - * |
303 | | - * Creates a space (type='vault') and a corresponding partition. |
304 | | - * Respects the user's tier limit for max partitions. |
305 | | - */ |
306 | | -vaultRoutes.post('/partitions/create', async (c) => { |
307 | | - const spaceToken = c.get('spaceToken') |
308 | | - if (spaceToken) { |
309 | | - return c.json({ error: 'Space tokens cannot create partitions' }, 403) |
310 | | - } |
311 | | - const user = c.get('user') |
312 | | - |
313 | | - try { |
314 | | - // Check quota |
315 | | - const quota = await getPartitionQuotaAsync(user.userId) |
316 | | - if (!quota.canCreate) { |
317 | | - return c.json({ |
318 | | - error: 'Partition limit reached', |
319 | | - tier: quota.tier, |
320 | | - maxPartitions: quota.maxPartitions, |
321 | | - usedPartitions: quota.usedPartitions, |
322 | | - }, 403) |
323 | | - } |
324 | | - |
325 | | - const partitionId = crypto.randomUUID() |
326 | | - const partitionName = 'sync_changes_' + partitionId.replace(/-/g, '_') |
327 | | - |
328 | | - // Insert space record (type='vault') — trigger creates partition |
329 | | - await db.insert(spaces).values({ |
330 | | - id: partitionId, |
331 | | - type: 'vault', |
332 | | - ownerId: user.userId, |
333 | | - }) |
334 | | - |
335 | | - // Create partition + RLS + replica identity |
336 | | - // DDL statements don't support parameterized values, so we use sql.raw() |
337 | | - // partitionId is crypto.randomUUID() — safe from injection |
338 | | - await db.execute(sql` |
339 | | - CREATE TABLE IF NOT EXISTS ${sql.raw(`public."${partitionName}"`)} |
340 | | - PARTITION OF public.sync_changes FOR VALUES IN (${sql.raw(`'${partitionId}'`)}) |
341 | | - `) |
342 | | - await db.execute(sql` |
343 | | - ALTER TABLE ${sql.raw(`public."${partitionName}"`)} ENABLE ROW LEVEL SECURITY |
344 | | - `) |
345 | | - await db.execute(sql` |
346 | | - CREATE POLICY "Users can only access their own sync changes" |
347 | | - ON ${sql.raw(`public."${partitionName}"`)} FOR SELECT |
348 | | - USING ((select auth.uid()) = user_id) |
349 | | - `) |
350 | | - await db.execute(sql` |
351 | | - CREATE POLICY "Users can only insert their own sync changes" |
352 | | - ON ${sql.raw(`public."${partitionName}"`)} FOR INSERT |
353 | | - WITH CHECK ((select auth.uid()) = user_id) |
354 | | - `) |
355 | | - await db.execute(sql` |
356 | | - ALTER TABLE ${sql.raw(`public."${partitionName}"`)} REPLICA IDENTITY FULL |
357 | | - `) |
358 | | - await db.execute(sql` |
359 | | - ALTER PUBLICATION supabase_realtime ADD TABLE ${sql.raw(`public."${partitionName}"`)} |
360 | | - `) |
361 | | - |
362 | | - console.log(`[Partitions] Created ${partitionName} for user ${user.userId} (${quota.usedPartitions + 1}/${quota.maxPartitions})`) |
363 | | - |
364 | | - return c.json({ partitionId }, 201) |
365 | | - } catch (error: any) { |
366 | | - if (error?.message?.includes('already exists')) { |
367 | | - return c.json({ error: 'Partition already exists' }, 409) |
368 | | - } |
369 | | - console.error('Create partition error:', error) |
370 | | - return c.json({ error: 'Internal server error' }, 500) |
371 | | - } |
372 | | -}) |
373 | 296 |
|
374 | 297 | export default vaultRoutes |
0 commit comments