Initial commit: courtlab tactical board with team management and MP4 export

This commit is contained in:
2026-09-08 12:22:20 +09:00
commit d2e39a452e
43 changed files with 7812 additions and 0 deletions
+37
View File
@@ -0,0 +1,37 @@
import { MongoClient } from 'mongodb';
import { loadConfig } from './config.js';
export const DEFAULT_MONGODB_URI = 'mongodb://172.16.0.7:27017';
export const DEFAULT_MONGODB_DB = 'basket_utils';
export async function createMongoStore(options = {}) {
const config = options.config || (options.uri && options.dbName ? null : await loadConfig());
const uri = options.uri || config?.mongodb?.uri || DEFAULT_MONGODB_URI;
const dbName = options.dbName || config?.mongodb?.db || DEFAULT_MONGODB_DB;
const client = options.client || new MongoClient(uri, { maxPoolSize: 10, serverSelectionTimeoutMS: options.serverSelectionTimeoutMS || 5000 });
try { await client.connect(); } catch (error) { if (!options.client) await client.close().catch(() => {}); throw error; }
const database = client.db(dbName);
const users = database.collection('users');
const sessions = database.collection('sessions');
const teams = database.collection('teams');
const teamMembers = database.collection('team_members');
const plays = database.collection('plays');
try {
await Promise.all([
users.createIndex({ email: 1 }, { unique: true }),
sessions.createIndex({ tokenHash: 1 }, { unique: true }),
sessions.createIndex({ expiresAt: 1 }, { expireAfterSeconds: 0 }),
teamMembers.createIndex({ teamId: 1, userId: 1 }, { unique: true }),
teamMembers.createIndex({ userId: 1 }),
plays.createIndex({ teamId: 1, id: 1 }, { unique: true }),
plays.createIndex({ teamId: 1, updatedAt: -1 }),
]);
} catch (error) {
if (!options.client) await client.close().catch(() => {});
throw error;
}
return {
client, database, users, sessions, teams, teamMembers, plays,
async close() { if (!options.client) await client.close(); },
};
}