feat(github): index connections by installation + status mutation
This commit is contained in:
@@ -138,6 +138,32 @@ export const upsertConnectionForUser = internalMutation({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const setConnectionStatusByInstallation = internalMutation({
|
||||||
|
args: {
|
||||||
|
installationId: v.string(),
|
||||||
|
status: v.union(
|
||||||
|
v.literal('active'),
|
||||||
|
v.literal('needs_reauth'),
|
||||||
|
v.literal('revoked'),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
handler: async (ctx, { installationId, status }) => {
|
||||||
|
const connections = await ctx.db
|
||||||
|
.query('gitConnections')
|
||||||
|
.withIndex('by_installation', (q) =>
|
||||||
|
q.eq('installationId', installationId),
|
||||||
|
)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
const now = Date.now();
|
||||||
|
for (const connection of connections) {
|
||||||
|
await ctx.db.patch(connection._id, { status, updatedAt: now });
|
||||||
|
}
|
||||||
|
|
||||||
|
return { updated: connections.length };
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const createForkSpoonRecord = internalMutation({
|
export const createForkSpoonRecord = internalMutation({
|
||||||
args: {
|
args: {
|
||||||
ownerId: v.id('users'),
|
ownerId: v.id('users'),
|
||||||
|
|||||||
@@ -53,7 +53,8 @@ const applicationTables = {
|
|||||||
})
|
})
|
||||||
.index('by_user', ['userId'])
|
.index('by_user', ['userId'])
|
||||||
.index('by_user_provider', ['userId', 'provider'])
|
.index('by_user_provider', ['userId', 'provider'])
|
||||||
.index('by_status', ['status']),
|
.index('by_status', ['status'])
|
||||||
|
.index('by_installation', ['installationId']),
|
||||||
spoons: defineTable({
|
spoons: defineTable({
|
||||||
ownerId: v.id('users'),
|
ownerId: v.id('users'),
|
||||||
name: v.string(),
|
name: v.string(),
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
import { convexTest } from 'convex-test';
|
||||||
|
import { describe, expect, test } from 'vitest';
|
||||||
|
|
||||||
|
import { internal } from '../../convex/_generated/api.js';
|
||||||
|
import schema from '../../convex/schema';
|
||||||
|
|
||||||
|
const modules = import.meta.glob('../../convex/**/*.*s');
|
||||||
|
|
||||||
|
const seedConnection = async (
|
||||||
|
t: ReturnType<typeof convexTest>,
|
||||||
|
installationId: string,
|
||||||
|
) =>
|
||||||
|
await t.run(async (ctx) => {
|
||||||
|
const now = Date.now();
|
||||||
|
const userId = await ctx.db.insert('users', {
|
||||||
|
email: 'a@b.c',
|
||||||
|
name: 'A',
|
||||||
|
});
|
||||||
|
return await ctx.db.insert('gitConnections', {
|
||||||
|
userId,
|
||||||
|
provider: 'github',
|
||||||
|
displayName: `GitHub installation ${installationId}`,
|
||||||
|
installationId,
|
||||||
|
status: 'active',
|
||||||
|
connectedAt: now,
|
||||||
|
updatedAt: now,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('setConnectionStatusByInstallation', () => {
|
||||||
|
test('flips the matching connection status', async () => {
|
||||||
|
const t = convexTest(schema, modules);
|
||||||
|
const connectionId = await seedConnection(t, '42');
|
||||||
|
|
||||||
|
const result = await t.mutation(
|
||||||
|
internal.github.setConnectionStatusByInstallation,
|
||||||
|
{ installationId: '42', status: 'needs_reauth' },
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).toEqual({ updated: 1 });
|
||||||
|
const connection = await t.run(async (ctx) => await ctx.db.get(connectionId));
|
||||||
|
expect(connection?.status).toBe('needs_reauth');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('is a no-op when no connection matches', async () => {
|
||||||
|
const t = convexTest(schema, modules);
|
||||||
|
const connectionId = await seedConnection(t, '42');
|
||||||
|
|
||||||
|
const result = await t.mutation(
|
||||||
|
internal.github.setConnectionStatusByInstallation,
|
||||||
|
{ installationId: '999', status: 'revoked' },
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).toEqual({ updated: 0 });
|
||||||
|
const connection = await t.run(async (ctx) => await ctx.db.get(connectionId));
|
||||||
|
expect(connection?.status).toBe('active');
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user