calabasas 0.1.6 → 0.1.7
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/index.js +96 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2972,6 +2972,14 @@ function generateSchemaFile(sync) {
|
|
|
2972
2972
|
syncedAt: v.number(),
|
|
2973
2973
|
})
|
|
2974
2974
|
.index("by_discord_id", ["discordId"]);`);
|
|
2975
|
+
tables.push(`export const calabasasGuildAdmins = defineTable({
|
|
2976
|
+
guildDiscordId: v.string(),
|
|
2977
|
+
discordUserId: v.string(),
|
|
2978
|
+
syncedAt: v.number(),
|
|
2979
|
+
})
|
|
2980
|
+
.index("by_user", ["discordUserId"])
|
|
2981
|
+
.index("by_guild", ["guildDiscordId"])
|
|
2982
|
+
.index("by_user_guild", ["discordUserId", "guildDiscordId"]);`);
|
|
2975
2983
|
}
|
|
2976
2984
|
if (sync.channels) {
|
|
2977
2985
|
tables.push(`export const calabasasChannels = defineTable({
|
|
@@ -3020,8 +3028,10 @@ function generateSchemaFile(sync) {
|
|
|
3020
3028
|
.index("by_guild", ["guildDiscordId"]);`);
|
|
3021
3029
|
}
|
|
3022
3030
|
const tableNames = [];
|
|
3023
|
-
if (sync.guilds)
|
|
3031
|
+
if (sync.guilds) {
|
|
3024
3032
|
tableNames.push("calabasasGuilds");
|
|
3033
|
+
tableNames.push("calabasasGuildAdmins");
|
|
3034
|
+
}
|
|
3025
3035
|
if (sync.channels)
|
|
3026
3036
|
tableNames.push("calabasasChannels");
|
|
3027
3037
|
if (sync.roles)
|
|
@@ -3139,6 +3149,14 @@ var MEMBER_TYPE = `{
|
|
|
3139
3149
|
roles?: string[];
|
|
3140
3150
|
joinedAt?: string;
|
|
3141
3151
|
}`;
|
|
3152
|
+
var GUILD_ADMIN_VALIDATOR = `v.object({
|
|
3153
|
+
guildId: v.string(),
|
|
3154
|
+
adminUserIds: v.array(v.string()),
|
|
3155
|
+
})`;
|
|
3156
|
+
var GUILD_ADMIN_TYPE = `{
|
|
3157
|
+
guildId: string;
|
|
3158
|
+
adminUserIds: string[];
|
|
3159
|
+
}`;
|
|
3142
3160
|
function generateGuildMutation() {
|
|
3143
3161
|
return `export const syncGuild = internalMutation({
|
|
3144
3162
|
args: {
|
|
@@ -3318,6 +3336,59 @@ function generateMemberMutation() {
|
|
|
3318
3336
|
},
|
|
3319
3337
|
});`;
|
|
3320
3338
|
}
|
|
3339
|
+
function generateGuildAdminMutation() {
|
|
3340
|
+
return `export const _syncGuildAdmins = internalMutation({
|
|
3341
|
+
args: {
|
|
3342
|
+
data: guildAdminValidator,
|
|
3343
|
+
},
|
|
3344
|
+
returns: v.null(),
|
|
3345
|
+
handler: async (ctx, { data }) => {
|
|
3346
|
+
// Delete all existing admin entries for this guild
|
|
3347
|
+
const existing = await ctx.db
|
|
3348
|
+
.query("calabasasGuildAdmins")
|
|
3349
|
+
.withIndex("by_guild", (q) => q.eq("guildDiscordId", data.guildId))
|
|
3350
|
+
.collect();
|
|
3351
|
+
|
|
3352
|
+
await Promise.all(existing.map((entry) => ctx.db.delete(entry._id)));
|
|
3353
|
+
|
|
3354
|
+
// Insert new admin entries
|
|
3355
|
+
const now = Date.now();
|
|
3356
|
+
await Promise.all(
|
|
3357
|
+
data.adminUserIds.map((userId) =>
|
|
3358
|
+
ctx.db.insert("calabasasGuildAdmins", {
|
|
3359
|
+
guildDiscordId: data.guildId,
|
|
3360
|
+
discordUserId: userId,
|
|
3361
|
+
syncedAt: now,
|
|
3362
|
+
})
|
|
3363
|
+
)
|
|
3364
|
+
);
|
|
3365
|
+
|
|
3366
|
+
return null;
|
|
3367
|
+
},
|
|
3368
|
+
});`;
|
|
3369
|
+
}
|
|
3370
|
+
function generateGuildAdminPublicMutation() {
|
|
3371
|
+
return `
|
|
3372
|
+
/**
|
|
3373
|
+
* Public mutation called by Calabasas gateway.
|
|
3374
|
+
* Validates secret and delegates to internal mutation.
|
|
3375
|
+
*/
|
|
3376
|
+
export const syncGuildAdmins = mutation({
|
|
3377
|
+
args: {
|
|
3378
|
+
secret: v.string(),
|
|
3379
|
+
data: guildAdminValidator,
|
|
3380
|
+
},
|
|
3381
|
+
returns: v.null(),
|
|
3382
|
+
handler: async (ctx, { secret, data }) => {
|
|
3383
|
+
const expectedSecret = process.env.CALABASAS_SECRET;
|
|
3384
|
+
if (!expectedSecret || secret !== expectedSecret) {
|
|
3385
|
+
throw new Error("Invalid secret");
|
|
3386
|
+
}
|
|
3387
|
+
await ctx.runMutation(internal.calabasas.sync._syncGuildAdmins, { data });
|
|
3388
|
+
return null;
|
|
3389
|
+
},
|
|
3390
|
+
});`;
|
|
3391
|
+
}
|
|
3321
3392
|
function generatePublicSyncMutation(type) {
|
|
3322
3393
|
const capitalType = type.charAt(0).toUpperCase() + type.slice(1);
|
|
3323
3394
|
return `
|
|
@@ -3353,9 +3424,13 @@ function generateSyncFile(sync) {
|
|
|
3353
3424
|
const enabledTypes = [];
|
|
3354
3425
|
if (sync.guilds) {
|
|
3355
3426
|
validators.push(`const guildValidator = ${GUILD_VALIDATOR};`);
|
|
3427
|
+
validators.push(`const guildAdminValidator = ${GUILD_ADMIN_VALIDATOR};`);
|
|
3356
3428
|
types.push(`export type GuildSync = ${GUILD_TYPE};`);
|
|
3429
|
+
types.push(`export type GuildAdminSync = ${GUILD_ADMIN_TYPE};`);
|
|
3357
3430
|
internalMutations.push(generateInternalSyncMutation("guild", generateGuildMutation()));
|
|
3431
|
+
internalMutations.push(generateGuildAdminMutation());
|
|
3358
3432
|
publicMutations.push(generatePublicSyncMutation("guild"));
|
|
3433
|
+
publicMutations.push(generateGuildAdminPublicMutation());
|
|
3359
3434
|
enabledTypes.push("guild");
|
|
3360
3435
|
}
|
|
3361
3436
|
if (sync.channels) {
|
|
@@ -3870,7 +3945,18 @@ async function generate(options) {
|
|
|
3870
3945
|
console.log(" });");
|
|
3871
3946
|
console.log("");
|
|
3872
3947
|
console.log("2. Re-export sync mutations in convex/discord.ts:");
|
|
3873
|
-
|
|
3948
|
+
const syncExports = [];
|
|
3949
|
+
if (syncConfig.guilds) {
|
|
3950
|
+
syncExports.push("syncGuild");
|
|
3951
|
+
syncExports.push("syncGuildAdmins");
|
|
3952
|
+
}
|
|
3953
|
+
if (syncConfig.channels)
|
|
3954
|
+
syncExports.push("syncChannel");
|
|
3955
|
+
if (syncConfig.roles)
|
|
3956
|
+
syncExports.push("syncRole");
|
|
3957
|
+
if (syncConfig.members)
|
|
3958
|
+
syncExports.push("syncMember");
|
|
3959
|
+
console.log(` export { ${syncExports.join(", ")} } from "./calabasas/sync";`);
|
|
3874
3960
|
console.log("");
|
|
3875
3961
|
console.log("3. Add CALABASAS_SECRET to your Convex environment variables");
|
|
3876
3962
|
console.log("4. Create your event handler in convex/discord.ts");
|
|
@@ -3932,6 +4018,13 @@ When sync is enabled, Discord data is automatically mirrored to Convex:
|
|
|
3932
4018
|
| Channels | \`calabasasChannels\` | Create, update, delete |
|
|
3933
4019
|
| Roles | \`calabasasRoles\` | Create, update, delete |
|
|
3934
4020
|
| Members | \`calabasasMembers\` | Join, update, leave |
|
|
4021
|
+
| Guild Admins | \`calabasasGuildAdmins\` | Guild create (reconnect) |
|
|
4022
|
+
|
|
4023
|
+
#### Guild Admins Table
|
|
4024
|
+
|
|
4025
|
+
\`calabasasGuildAdmins\` is a junction table that maps guild admins (users with ADMINISTRATOR permission or guild owners). Unlike other sync tables that store entity data, this is a many-to-many relationship table with fields: \`guildDiscordId\`, \`discordUserId\`, \`syncedAt\`.
|
|
4026
|
+
|
|
4027
|
+
Indexed by \`by_user\`, \`by_guild\`, and \`by_user_guild\` — use \`by_user\` to find all guilds where a user is admin (e.g., for "mutual servers" queries). Automatically populated when \`sync.guilds\` is enabled; recomputed on every bot connect/reconnect.
|
|
3935
4028
|
|
|
3936
4029
|
### ⚠️ Schema Integration (Required)
|
|
3937
4030
|
|
|
@@ -3952,7 +4045,7 @@ Then re-export the sync mutations so the gateway can call them:
|
|
|
3952
4045
|
|
|
3953
4046
|
\`\`\`typescript
|
|
3954
4047
|
// convex/discord.ts
|
|
3955
|
-
export { syncGuild, syncChannel, syncRole, syncMember } from "./calabasas/sync";
|
|
4048
|
+
export { syncGuild, syncGuildAdmins, syncChannel, syncRole, syncMember } from "./calabasas/sync";
|
|
3956
4049
|
\`\`\`
|
|
3957
4050
|
|
|
3958
4051
|
Without this step, Convex will reject sync operations because the tables are not defined in the schema.
|