Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
339d798a88 | ||
|
|
6580564767 | ||
|
|
d3a36b6103 | ||
|
|
868eaa5e3d | ||
|
|
5743ebc4f8 | ||
|
|
19ec020046 | ||
|
|
8353a24f6b | ||
|
|
670e6675cc | ||
|
|
cdd854bd70 | ||
|
|
cbb1f52467 | ||
|
|
62e2255b5e | ||
|
|
d7d270510f | ||
|
|
a5c297b911 | ||
|
|
0011c9d4e5 | ||
|
|
db0d2cf215 | ||
|
|
ec370a3c17 |
No files matched your search
Binary file not shown.
Executable → Regular
BIN
Binary file not shown.
Whitespace-only changes.
@@ -1,10 +1,11 @@
|
|||||||
|
const { pathsToModuleNameMapper } = require('ts-jest');
|
||||||
|
const { compilerOptions } = require('./tsconfig');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
preset: 'ts-jest',
|
preset: 'ts-jest',
|
||||||
testEnvironment: 'jsdom',
|
testEnvironment: 'jsdom',
|
||||||
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
|
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
|
||||||
moduleNameMapping: {
|
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: '<rootDir>/' }),
|
||||||
'^@/(.*)$': '<rootDir>/src/$1',
|
|
||||||
},
|
|
||||||
testMatch: [
|
testMatch: [
|
||||||
'**/__tests__/**/*.(ts|tsx|js)',
|
'**/__tests__/**/*.(ts|tsx|js)',
|
||||||
'**/*.(test|spec).(ts|tsx|js)',
|
'**/*.(test|spec).(ts|tsx|js)',
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
import '@testing-library/jest-dom'
|
require('@testing-library/jest-dom')
|
||||||
Generated
+1257
-9
File diff suppressed because it is too large.
Load diff
@@ -15,6 +15,7 @@
|
|||||||
"@fitai/database": "file:../../packages/database",
|
"@fitai/database": "file:../../packages/database",
|
||||||
"@fitai/shared": "file:../../packages/shared",
|
"@fitai/shared": "file:../../packages/shared",
|
||||||
"@hookform/resolvers": "^5.2.2",
|
"@hookform/resolvers": "^5.2.2",
|
||||||
|
"@radix-ui/react-dialog": "^1.1.15",
|
||||||
"@radix-ui/react-slot": "^1.2.4",
|
"@radix-ui/react-slot": "^1.2.4",
|
||||||
"@tanstack/react-query": "^5.90.7",
|
"@tanstack/react-query": "^5.90.7",
|
||||||
"@types/bcryptjs": "^3.0.0",
|
"@types/bcryptjs": "^3.0.0",
|
||||||
@@ -26,10 +27,11 @@
|
|||||||
"autoprefixer": "^10.4.16",
|
"autoprefixer": "^10.4.16",
|
||||||
"axios": "^1.13.2",
|
"axios": "^1.13.2",
|
||||||
"bcryptjs": "^3.0.3",
|
"bcryptjs": "^3.0.3",
|
||||||
"better-sqlite3": "^11.10.0",
|
"better-sqlite3": "12.4.1",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
|
"dotenv": "^17.2.3",
|
||||||
"drizzle-orm": "^0.44.7",
|
"drizzle-orm": "^0.44.7",
|
||||||
"lucide-react": "^0.553.0",
|
"lucide-react": "^0.553.0",
|
||||||
"next": "^16.0.1",
|
"next": "^16.0.1",
|
||||||
@@ -49,12 +51,15 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@testing-library/jest-dom": "^6.9.1",
|
"@testing-library/jest-dom": "^6.9.1",
|
||||||
"@testing-library/react": "^16.3.0",
|
"@testing-library/react": "^16.3.0",
|
||||||
|
"@types/jest": "^30.0.0",
|
||||||
"@types/node": "^24.10.0",
|
"@types/node": "^24.10.0",
|
||||||
"@types/react": "19.2.2",
|
"@types/react": "19.2.2",
|
||||||
"@types/react-dom": "^19.2.2",
|
"@types/react-dom": "^19.2.2",
|
||||||
"eslint": "^9.39.1",
|
"eslint": "^9.39.1",
|
||||||
"eslint-config-next": "^16.0.1",
|
"eslint-config-next": "^16.0.1",
|
||||||
"jest": "^30.2.0",
|
"jest": "^30.2.0",
|
||||||
|
"jest-environment-jsdom": "^30.2.0",
|
||||||
|
"ts-jest": "^29.4.6",
|
||||||
"typescript": "^5.9.3"
|
"typescript": "^5.9.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
import { getDatabase } from '../src/lib/database';
|
||||||
|
import { DrizzleDatabase } from '../src/lib/database/drizzle';
|
||||||
|
|
||||||
|
async function checkUserRole() {
|
||||||
|
const db = await getDatabase();
|
||||||
|
const users = await db.getAllUsers();
|
||||||
|
console.log('Users found:', users.length);
|
||||||
|
users.forEach(u => {
|
||||||
|
console.log(`User: ${u.email}, Role: ${u.role}, ID: ${u.id}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
checkUserRole().catch(console.error);
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
import { getDatabase } from '../src/lib/database';
|
||||||
|
|
||||||
|
async function makeAdmin(email: string) {
|
||||||
|
const db = await getDatabase();
|
||||||
|
const user = await db.getUserByEmail(email);
|
||||||
|
if (!user) {
|
||||||
|
console.log('User not found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await db.updateUser(user.id, { role: 'admin' });
|
||||||
|
console.log(`User ${email} updated to admin`);
|
||||||
|
}
|
||||||
|
|
||||||
|
makeAdmin('taratur@gmail.com').catch(console.error);
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
|
||||||
|
import 'dotenv/config';
|
||||||
|
import { getDatabase } from '../src/lib/database';
|
||||||
|
import { clerkClient } from '@clerk/nextjs/server';
|
||||||
|
|
||||||
|
async function syncAllUsers() {
|
||||||
|
console.log('Starting full user sync...');
|
||||||
|
const db = await getDatabase();
|
||||||
|
|
||||||
|
// Fetch all users from Clerk
|
||||||
|
// Note: pagination might be needed for large user bases, but for prototype this is fine.
|
||||||
|
const client = await clerkClient();
|
||||||
|
const response = await client.users.getUserList({ limit: 100 });
|
||||||
|
const clerkUsers = response.data;
|
||||||
|
|
||||||
|
console.log(`Found ${clerkUsers.length} users in Clerk.`);
|
||||||
|
|
||||||
|
for (const clerkUser of clerkUsers) {
|
||||||
|
const userId = clerkUser.id;
|
||||||
|
const email = clerkUser.emailAddresses[0]?.emailAddress;
|
||||||
|
|
||||||
|
if (!email) {
|
||||||
|
console.warn(`User ${userId} has no email, skipping.`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingUser = await db.getUserById(userId);
|
||||||
|
if (existingUser) {
|
||||||
|
console.log(`User ${email} (${userId}) already exists.`);
|
||||||
|
// Optional: Update details if needed
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check by email to handle ID mismatches (e.g. from seeding)
|
||||||
|
const existingByEmail = await db.getUserByEmail(email);
|
||||||
|
if (existingByEmail) {
|
||||||
|
console.log(`User ${email} found with old ID ${existingByEmail.id}. Migrating to ${userId}...`);
|
||||||
|
await db.migrateUserId(existingByEmail.id, userId);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Creating new user ${email} (${userId})...`);
|
||||||
|
await db.createUser({
|
||||||
|
id: userId,
|
||||||
|
email,
|
||||||
|
firstName: clerkUser.firstName || '',
|
||||||
|
lastName: clerkUser.lastName || '',
|
||||||
|
password: '', // Managed by Clerk
|
||||||
|
phone: clerkUser.phoneNumbers[0]?.phoneNumber || undefined,
|
||||||
|
role: (clerkUser.publicMetadata.role as 'admin' | 'client' | 'superAdmin') || 'client'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Sync complete.');
|
||||||
|
}
|
||||||
|
|
||||||
|
syncAllUsers().catch(console.error);
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"extends": "../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "CommonJS",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"noEmit": true
|
||||||
|
},
|
||||||
|
"ts-node": {
|
||||||
|
"transpileOnly": true,
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "CommonJS"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
|
||||||
|
import { getDatabase } from '../src/lib/database/index';
|
||||||
|
|
||||||
|
async function verifyDatabase() {
|
||||||
|
console.log('Starting database verification...');
|
||||||
|
const db = await getDatabase();
|
||||||
|
await db.connect();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. Create User
|
||||||
|
console.log('Creating test user...');
|
||||||
|
const userId = `test-user-${Date.now()}`;
|
||||||
|
const user = await db.createUser({
|
||||||
|
id: userId,
|
||||||
|
email: `test-${Date.now()}@example.com`,
|
||||||
|
firstName: 'Test',
|
||||||
|
lastName: 'User',
|
||||||
|
password: 'password123',
|
||||||
|
role: 'client',
|
||||||
|
phone: '1234567890'
|
||||||
|
});
|
||||||
|
console.log('User created:', user.id);
|
||||||
|
|
||||||
|
// 2. Create Client
|
||||||
|
console.log('Creating test client...');
|
||||||
|
const client = await db.createClient({
|
||||||
|
userId: user.id,
|
||||||
|
membershipType: 'basic',
|
||||||
|
membershipStatus: 'active',
|
||||||
|
joinDate: new Date()
|
||||||
|
});
|
||||||
|
console.log('Client created:', client.id);
|
||||||
|
|
||||||
|
// 3. Create Fitness Profile
|
||||||
|
console.log('Creating fitness profile...');
|
||||||
|
const profile = await db.createFitnessProfile({
|
||||||
|
id: 'test-profile-id',
|
||||||
|
userId: user.id,
|
||||||
|
height: '180',
|
||||||
|
weight: '75',
|
||||||
|
age: '30',
|
||||||
|
gender: 'male',
|
||||||
|
activityLevel: 'moderately_active',
|
||||||
|
fitnessGoals: ['weight_loss'],
|
||||||
|
exerciseHabits: 'None',
|
||||||
|
dietHabits: 'None',
|
||||||
|
medicalConditions: 'None'
|
||||||
|
});
|
||||||
|
console.log('Fitness profile created for:', profile.userId);
|
||||||
|
|
||||||
|
// 4. Attendance Check-in
|
||||||
|
console.log('Checking in...');
|
||||||
|
const checkIn = await db.checkIn(user.id, 'gym', 'Test check-in');
|
||||||
|
console.log('Checked in:', checkIn.id);
|
||||||
|
|
||||||
|
// 5. Verify Active Check-in
|
||||||
|
const activeCheckIn = await db.getActiveCheckIn(user.id);
|
||||||
|
if (!activeCheckIn || activeCheckIn.id !== checkIn.id) {
|
||||||
|
throw new Error('Active check-in verification failed');
|
||||||
|
}
|
||||||
|
console.log('Active check-in verified');
|
||||||
|
|
||||||
|
// 6. Attendance Check-out
|
||||||
|
console.log('Checking out...');
|
||||||
|
const checkOut = await db.checkOut(checkIn.id);
|
||||||
|
console.log('Checked out:', checkOut?.checkOutTime);
|
||||||
|
|
||||||
|
// 7. Cleanup
|
||||||
|
console.log('Cleaning up...');
|
||||||
|
await db.deleteUser(user.id);
|
||||||
|
console.log('Cleanup complete');
|
||||||
|
|
||||||
|
console.log('✅ Verification successful!');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Verification failed:', error);
|
||||||
|
process.exit(1);
|
||||||
|
} finally {
|
||||||
|
await db.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
verifyDatabase();
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
import { NextRequest, NextResponse } from "next/server";
|
|
||||||
import { auth } from "@clerk/nextjs/server";
|
|
||||||
|
|
||||||
export async function GET(req: NextRequest) {
|
|
||||||
try {
|
|
||||||
const { userId } = await auth();
|
|
||||||
if (!userId) {
|
|
||||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
||||||
}
|
|
||||||
|
|
||||||
const { searchParams } = new URL(req.url);
|
|
||||||
const date = searchParams.get("date") || new Date().toISOString().split('T')[0];
|
|
||||||
|
|
||||||
// TODO: Fetch from database when activity_logs methods are added to IDatabase
|
|
||||||
console.log(`Fetching daily activity for user ${userId} on ${date}`);
|
|
||||||
|
|
||||||
// Return mock data for now
|
|
||||||
return NextResponse.json({
|
|
||||||
steps: 0,
|
|
||||||
calories: 0,
|
|
||||||
duration: 0,
|
|
||||||
date
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching daily activity:", error);
|
|
||||||
return NextResponse.json(
|
|
||||||
{ error: "Failed to fetch daily activity" },
|
|
||||||
{ status: 500 }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
import { NextRequest, NextResponse } from "next/server";
|
|
||||||
import { auth } from "@clerk/nextjs/server";
|
|
||||||
|
|
||||||
export async function POST(req: NextRequest) {
|
|
||||||
try {
|
|
||||||
const { userId } = await auth();
|
|
||||||
if (!userId) {
|
|
||||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
||||||
}
|
|
||||||
|
|
||||||
const { steps, timestamp } = await req.json();
|
|
||||||
|
|
||||||
// TODO: Implement database persistence when activity_logs methods are added to IDatabase
|
|
||||||
console.log(`Syncing steps for user ${userId}: ${steps} steps at ${timestamp}`);
|
|
||||||
|
|
||||||
return NextResponse.json({ success: true, steps });
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error syncing steps:", error);
|
|
||||||
return NextResponse.json(
|
|
||||||
{ error: "Failed to sync steps" },
|
|
||||||
{ status: 500 }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import { auth } from '@clerk/nextjs/server'
|
||||||
|
import { NextResponse } from 'next/server'
|
||||||
|
import { getDatabase, DatabaseFactory } from '@/lib/database'
|
||||||
|
import { ensureUserSynced } from '@/lib/sync-user'
|
||||||
|
import fs from 'fs'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
const BACKUP_DIR = path.join(process.cwd(), 'backups')
|
||||||
|
const DB_PATH = path.join(process.cwd(), 'data', 'fitai.db')
|
||||||
|
|
||||||
|
export async function POST(req: Request) {
|
||||||
|
try {
|
||||||
|
const { userId } = await auth()
|
||||||
|
if (!userId) return new NextResponse('Unauthorized', { status: 401 })
|
||||||
|
|
||||||
|
const db = await getDatabase()
|
||||||
|
const user = await ensureUserSynced(userId, db)
|
||||||
|
|
||||||
|
if (!user || (user.role !== 'admin' && user.role !== 'superAdmin')) {
|
||||||
|
return new NextResponse('Forbidden', { status: 403 })
|
||||||
|
}
|
||||||
|
|
||||||
|
const { filename } = await req.json()
|
||||||
|
if (!filename) {
|
||||||
|
return new NextResponse('Filename is required', { status: 400 })
|
||||||
|
}
|
||||||
|
|
||||||
|
const backupPath = path.join(BACKUP_DIR, filename)
|
||||||
|
if (!fs.existsSync(backupPath)) {
|
||||||
|
return new NextResponse('Backup file not found', { status: 404 })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close existing connection
|
||||||
|
await DatabaseFactory.disconnect()
|
||||||
|
|
||||||
|
// Restore file
|
||||||
|
fs.copyFileSync(backupPath, DB_PATH)
|
||||||
|
|
||||||
|
// Re-initialize connection (will happen automatically on next getDatabase call, but good to verify)
|
||||||
|
await getDatabase()
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true })
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Restore backup error:', error)
|
||||||
|
return new NextResponse('Internal Server Error', { status: 500 })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
import { auth } from '@clerk/nextjs/server'
|
||||||
|
import { NextResponse } from 'next/server'
|
||||||
|
import { getDatabase } from '@/lib/database'
|
||||||
|
import { ensureUserSynced } from '@/lib/sync-user'
|
||||||
|
import fs from 'fs'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
const BACKUP_DIR = path.join(process.cwd(), 'backups')
|
||||||
|
const DB_PATH = path.join(process.cwd(), 'data', 'fitai.db')
|
||||||
|
|
||||||
|
export async function GET() {
|
||||||
|
try {
|
||||||
|
const { userId } = await auth()
|
||||||
|
if (!userId) return new NextResponse('Unauthorized', { status: 401 })
|
||||||
|
|
||||||
|
const db = await getDatabase()
|
||||||
|
const user = await ensureUserSynced(userId, db)
|
||||||
|
|
||||||
|
if (!user || (user.role !== 'admin' && user.role !== 'superAdmin')) {
|
||||||
|
return new NextResponse('Forbidden', { status: 403 })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fs.existsSync(BACKUP_DIR)) {
|
||||||
|
fs.mkdirSync(BACKUP_DIR, { recursive: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
const files = fs.readdirSync(BACKUP_DIR)
|
||||||
|
.filter(file => file.endsWith('.db'))
|
||||||
|
.map(file => {
|
||||||
|
const stats = fs.statSync(path.join(BACKUP_DIR, file))
|
||||||
|
return {
|
||||||
|
name: file,
|
||||||
|
size: stats.size,
|
||||||
|
createdAt: stats.birthtime
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())
|
||||||
|
|
||||||
|
return NextResponse.json(files)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('List backups error:', error)
|
||||||
|
return new NextResponse('Internal Server Error', { status: 500 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function POST() {
|
||||||
|
try {
|
||||||
|
const { userId } = await auth()
|
||||||
|
if (!userId) return new NextResponse('Unauthorized', { status: 401 })
|
||||||
|
|
||||||
|
const db = await getDatabase()
|
||||||
|
const user = await ensureUserSynced(userId, db)
|
||||||
|
|
||||||
|
if (!user || (user.role !== 'admin' && user.role !== 'superAdmin')) {
|
||||||
|
return new NextResponse('Forbidden', { status: 403 })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fs.existsSync(BACKUP_DIR)) {
|
||||||
|
fs.mkdirSync(BACKUP_DIR, { recursive: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
const timestamp = new Date().toISOString().replace(/[:.]/g, '-')
|
||||||
|
const backupPath = path.join(BACKUP_DIR, `backup-${timestamp}.db`)
|
||||||
|
|
||||||
|
// Ensure source DB exists
|
||||||
|
if (!fs.existsSync(DB_PATH)) {
|
||||||
|
return new NextResponse('Database file not found', { status: 404 })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy file
|
||||||
|
fs.copyFileSync(DB_PATH, backupPath)
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true, filename: `backup-${timestamp}.db` })
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Create backup error:', error)
|
||||||
|
return new NextResponse('Internal Server Error', { status: 500 })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
import { NextResponse } from "next/server";
|
||||||
|
import { auth } from "@clerk/nextjs/server";
|
||||||
|
import { getDatabase } from "@/lib/database";
|
||||||
|
import { ensureUserSynced } from "@/lib/sync-user";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET /api/admin/clients
|
||||||
|
*
|
||||||
|
* Admin:
|
||||||
|
* - Lists clients scoped to the admin's gym (requires admin.gymId).
|
||||||
|
*
|
||||||
|
* SuperAdmin:
|
||||||
|
* - Optional query param ?gymId=<id> to filter clients by a specific gym.
|
||||||
|
* - If no gymId provided, returns all clients across all gyms.
|
||||||
|
*
|
||||||
|
* Response: Array of client users with minimal fields for listing, including membership data.
|
||||||
|
*/
|
||||||
|
export async function GET(req: Request) {
|
||||||
|
try {
|
||||||
|
const { userId } = await auth();
|
||||||
|
if (!userId) {
|
||||||
|
return new NextResponse("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const db = await getDatabase();
|
||||||
|
const user = await ensureUserSynced(userId, db);
|
||||||
|
|
||||||
|
if (!user || (user.role !== "admin" && user.role !== "superAdmin")) {
|
||||||
|
return new NextResponse("Forbidden", { status: 403 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = new URL(req.url);
|
||||||
|
const requestedGymId = url.searchParams.get("gymId");
|
||||||
|
|
||||||
|
// Admins must have a gymId; scope to their gym
|
||||||
|
let targetGymId: string | null = null;
|
||||||
|
if (user.role === "admin") {
|
||||||
|
if (!user.gymId) {
|
||||||
|
return new NextResponse("Admin gymId not set", { status: 400 });
|
||||||
|
}
|
||||||
|
targetGymId = user.gymId;
|
||||||
|
} else if (user.role === "superAdmin") {
|
||||||
|
targetGymId = requestedGymId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch users and clients
|
||||||
|
const allUsers = await db.getAllUsers();
|
||||||
|
const usersById = new Map(allUsers.map((u) => [u.id, u]));
|
||||||
|
const allClients = await db.getAllClients();
|
||||||
|
|
||||||
|
// Scope clients by gym when provided
|
||||||
|
const scopedClients = targetGymId
|
||||||
|
? allClients.filter((c) => {
|
||||||
|
const u = usersById.get(c.userId);
|
||||||
|
return u?.gymId === targetGymId;
|
||||||
|
})
|
||||||
|
: allClients;
|
||||||
|
|
||||||
|
// Compose payload merging user and client info
|
||||||
|
const payload = scopedClients.map((c) => {
|
||||||
|
const u = usersById.get(c.userId);
|
||||||
|
return {
|
||||||
|
id: c.id,
|
||||||
|
userId: c.userId,
|
||||||
|
email: u?.email ?? null,
|
||||||
|
firstName: u?.firstName ?? null,
|
||||||
|
lastName: u?.lastName ?? null,
|
||||||
|
gymId: u?.gymId ?? null,
|
||||||
|
membershipType: c.membershipType,
|
||||||
|
membershipStatus: c.membershipStatus,
|
||||||
|
joinDate: c.joinDate,
|
||||||
|
lastVisit: c.lastVisit ?? null,
|
||||||
|
emergencyContact: c.emergencyContact ?? null,
|
||||||
|
createdAt: u?.createdAt ?? null,
|
||||||
|
updatedAt: u?.updatedAt ?? null,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return NextResponse.json(payload);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("GET /api/admin/clients error:", error);
|
||||||
|
return new NextResponse("Internal Server Error", { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
import { NextResponse } from "next/server";
|
||||||
|
import { auth, clerkClient } from "@clerk/nextjs/server";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /api/admin/set-user-metadata
|
||||||
|
*
|
||||||
|
* Sets Clerk publicMetadata.role and publicMetadata.gymId for a target user.
|
||||||
|
*
|
||||||
|
* Authorization:
|
||||||
|
* - Caller must be an admin or superAdmin (based on their Clerk publicMetadata.role).
|
||||||
|
*
|
||||||
|
* Request body:
|
||||||
|
* {
|
||||||
|
* "targetUserId": string, // Clerk user ID of the target
|
||||||
|
* "role": "superAdmin" | "admin" | "trainer" | "client" | "generalUser", // optional
|
||||||
|
* "gymId": string | null // optional; null clears gym assignment
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* Behavior:
|
||||||
|
* - If "role" is provided, update the target user's publicMetadata.role.
|
||||||
|
* - If "gymId" is provided (including null), update publicMetadata.gymId.
|
||||||
|
* - Validates inputs and permissions.
|
||||||
|
*
|
||||||
|
* Response:
|
||||||
|
* - 200 with updated minimal user data
|
||||||
|
* - 400/401/403/404/500 on errors
|
||||||
|
*/
|
||||||
|
export async function POST(req: Request) {
|
||||||
|
try {
|
||||||
|
// Authenticate the requester
|
||||||
|
const { userId } = await auth();
|
||||||
|
if (!userId) {
|
||||||
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const client = await clerkClient();
|
||||||
|
|
||||||
|
// Fetch requester from Clerk to verify permissions
|
||||||
|
const requester = await client.users.getUser(userId);
|
||||||
|
const requesterRole =
|
||||||
|
(requester.publicMetadata?.role as
|
||||||
|
| "superAdmin"
|
||||||
|
| "admin"
|
||||||
|
| "trainer"
|
||||||
|
| "client"
|
||||||
|
| "generalUser") ?? "client";
|
||||||
|
|
||||||
|
// Only admin or superAdmin can set metadata
|
||||||
|
if (requesterRole !== "admin" && requesterRole !== "superAdmin") {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Forbidden: admin or superAdmin access required" },
|
||||||
|
{ status: 403 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse body
|
||||||
|
const body = await req.json().catch(() => null);
|
||||||
|
if (!body || typeof body !== "object") {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Invalid JSON body" },
|
||||||
|
{ status: 400 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const targetUserId = typeof body.targetUserId === "string" ? body.targetUserId : null;
|
||||||
|
const role = body.role as
|
||||||
|
| "superAdmin"
|
||||||
|
| "admin"
|
||||||
|
| "trainer"
|
||||||
|
| "client"
|
||||||
|
| "generalUser"
|
||||||
|
| undefined;
|
||||||
|
const gymId =
|
||||||
|
body.gymId === null
|
||||||
|
? null
|
||||||
|
: typeof body.gymId === "string"
|
||||||
|
? body.gymId
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
if (!targetUserId) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Invalid or missing targetUserId" },
|
||||||
|
{ status: 400 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate role if provided
|
||||||
|
const allowedRoles = ["superAdmin", "admin", "trainer", "client", "generalUser"] as const;
|
||||||
|
if (role && !allowedRoles.includes(role)) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Invalid role. Must be one of superAdmin, admin, trainer, client, generalUser" },
|
||||||
|
{ status: 400 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent non-superAdmin from assigning superAdmin
|
||||||
|
if (role === "superAdmin" && requesterRole !== "superAdmin") {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Only superAdmin can assign superAdmin role" },
|
||||||
|
{ status: 403 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch target user to ensure they exist
|
||||||
|
let targetUser;
|
||||||
|
try {
|
||||||
|
targetUser = await client.users.getUser(targetUserId);
|
||||||
|
} catch {
|
||||||
|
return NextResponse.json({ error: "Target user not found" }, { status: 404 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct new metadata by merging with existing
|
||||||
|
const newPublicMetadata: Record<string, unknown> = {
|
||||||
|
...(targetUser.publicMetadata || {}),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (role !== undefined) {
|
||||||
|
newPublicMetadata.role = role;
|
||||||
|
}
|
||||||
|
if (gymId !== undefined) {
|
||||||
|
newPublicMetadata.gymId = gymId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure at least one field to update
|
||||||
|
if (role === undefined && gymId === undefined) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Provide at least one of 'role' or 'gymId' to update" },
|
||||||
|
{ status: 400 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform update on Clerk
|
||||||
|
const updatedUser = await client.users.updateUser(targetUserId, {
|
||||||
|
publicMetadata: newPublicMetadata,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Construct response payload
|
||||||
|
const primaryEmail =
|
||||||
|
updatedUser.emailAddresses?.find(
|
||||||
|
(e) => e.id === updatedUser.primaryEmailAddressId
|
||||||
|
)?.emailAddress || updatedUser.emailAddresses?.[0]?.emailAddress || null;
|
||||||
|
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
success: true,
|
||||||
|
message: "User metadata updated",
|
||||||
|
user: {
|
||||||
|
id: updatedUser.id,
|
||||||
|
email: primaryEmail,
|
||||||
|
firstName: updatedUser.firstName,
|
||||||
|
lastName: updatedUser.lastName,
|
||||||
|
role: updatedUser.publicMetadata?.role ?? null,
|
||||||
|
gymId: updatedUser.publicMetadata?.gymId ?? null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ status: 200 }
|
||||||
|
);
|
||||||
|
} catch (error: any) {
|
||||||
|
const message =
|
||||||
|
error?.errors?.[0]?.message ||
|
||||||
|
error?.message ||
|
||||||
|
"Internal server error";
|
||||||
|
console.error("Error setting user metadata:", error);
|
||||||
|
return NextResponse.json({ error: message }, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,25 +1,59 @@
|
|||||||
import { auth } from '@clerk/nextjs/server'
|
import { auth } from "@clerk/nextjs/server";
|
||||||
import { NextResponse } from 'next/server'
|
import { NextResponse } from "next/server";
|
||||||
import { getDatabase } from '@/lib/database'
|
import { getDatabase } from "@/lib/database";
|
||||||
import { ensureUserSynced } from '@/lib/sync-user'
|
import { ensureUserSynced } from "@/lib/sync-user";
|
||||||
|
|
||||||
export async function GET() {
|
export async function GET(req: Request) {
|
||||||
try {
|
try {
|
||||||
const { userId } = await auth()
|
const { userId } = await auth();
|
||||||
if (!userId) return new NextResponse('Unauthorized', { status: 401 })
|
if (!userId) return new NextResponse("Unauthorized", { status: 401 });
|
||||||
|
|
||||||
const db = await getDatabase()
|
const db = await getDatabase();
|
||||||
const user = await ensureUserSynced(userId, db)
|
const user = await ensureUserSynced(userId, db);
|
||||||
|
|
||||||
if (!user || (user.role !== 'admin' && user.role !== 'superAdmin')) {
|
if (!user || (user.role !== "admin" && user.role !== "superAdmin")) {
|
||||||
return new NextResponse('Forbidden', { status: 403 })
|
return new NextResponse("Forbidden", { status: 403 });
|
||||||
}
|
|
||||||
|
|
||||||
const stats = await db.getDashboardStats()
|
|
||||||
|
|
||||||
return NextResponse.json(stats)
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Dashboard stats error:', error)
|
|
||||||
return new NextResponse('Internal Server Error', { status: 500 })
|
|
||||||
}
|
}
|
||||||
|
if (user.role === "admin" && !user.gymId) {
|
||||||
|
return new NextResponse("Admin gymId not set", { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = new URL(req.url);
|
||||||
|
const searchParams = url.searchParams;
|
||||||
|
|
||||||
|
let targetGymId: string | null = null;
|
||||||
|
if (user.role === "admin") {
|
||||||
|
targetGymId = user.gymId ?? null;
|
||||||
|
} else if (user.role === "superAdmin") {
|
||||||
|
targetGymId = searchParams.get("gymId");
|
||||||
|
}
|
||||||
|
|
||||||
|
const allUsers = await db.getAllUsers();
|
||||||
|
const allClients = await db.getAllClients();
|
||||||
|
|
||||||
|
const usersById = new Map(allUsers.map((u) => [u.id, u]));
|
||||||
|
const filteredUsers = targetGymId
|
||||||
|
? allUsers.filter((u) => u.gymId === targetGymId)
|
||||||
|
: allUsers;
|
||||||
|
const filteredClients = targetGymId
|
||||||
|
? allClients.filter((c) => {
|
||||||
|
const u = usersById.get(c.userId);
|
||||||
|
return u?.gymId === targetGymId;
|
||||||
|
})
|
||||||
|
: allClients;
|
||||||
|
|
||||||
|
const stats = {
|
||||||
|
totalUsers: filteredUsers.length,
|
||||||
|
activeClients: filteredClients.filter(
|
||||||
|
(c) => c.membershipStatus === "active",
|
||||||
|
).length,
|
||||||
|
totalRevenue: 0,
|
||||||
|
revenueGrowth: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
return NextResponse.json(stats);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Dashboard stats error:", error);
|
||||||
|
return new NextResponse("Internal Server Error", { status: 500 });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import { NextResponse } from "next/server";
|
||||||
|
import { auth } from "@clerk/nextjs/server";
|
||||||
|
import { getDatabase } from "@/lib/database";
|
||||||
|
import { ensureUserSynced } from "@/lib/sync-user";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET /api/admin/trainers
|
||||||
|
*
|
||||||
|
* Admin:
|
||||||
|
* - Lists trainers scoped to the admin's gym (requires admin.gymId).
|
||||||
|
*
|
||||||
|
* SuperAdmin:
|
||||||
|
* - Optional query param ?gymId=<id> to filter trainers by a specific gym.
|
||||||
|
* - If no gymId provided, returns all trainers across all gyms.
|
||||||
|
*
|
||||||
|
* Response: Array of trainer users with minimal fields for listing
|
||||||
|
*/
|
||||||
|
export async function GET(req: Request) {
|
||||||
|
try {
|
||||||
|
const { userId } = await auth();
|
||||||
|
if (!userId) {
|
||||||
|
return new NextResponse("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const db = await getDatabase();
|
||||||
|
const user = await ensureUserSynced(userId, db);
|
||||||
|
|
||||||
|
if (!user || (user.role !== "admin" && user.role !== "superAdmin")) {
|
||||||
|
return new NextResponse("Forbidden", { status: 403 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = new URL(req.url);
|
||||||
|
const requestedGymId = url.searchParams.get("gymId");
|
||||||
|
|
||||||
|
// Admins must have a gymId; scope to their gym
|
||||||
|
let targetGymId: string | null = null;
|
||||||
|
if (user.role === "admin") {
|
||||||
|
if (!user.gymId) {
|
||||||
|
return new NextResponse("Admin gymId not set", { status: 400 });
|
||||||
|
}
|
||||||
|
targetGymId = user.gymId as string;
|
||||||
|
} else if (user.role === "superAdmin") {
|
||||||
|
targetGymId = requestedGymId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch all users and filter to trainers
|
||||||
|
const allUsers = await db.getAllUsers();
|
||||||
|
let trainers = allUsers.filter((u) => u.role === "trainer");
|
||||||
|
|
||||||
|
// Scope by gym when required/provided
|
||||||
|
if (targetGymId) {
|
||||||
|
trainers = trainers.filter((t) => t.gymId === targetGymId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minimal payload suitable for listing
|
||||||
|
const payload = trainers.map((t) => ({
|
||||||
|
id: t.id,
|
||||||
|
email: t.email,
|
||||||
|
firstName: t.firstName,
|
||||||
|
lastName: t.lastName,
|
||||||
|
gymId: t.gymId ?? null,
|
||||||
|
createdAt: t.createdAt,
|
||||||
|
updatedAt: t.updatedAt,
|
||||||
|
}));
|
||||||
|
|
||||||
|
return NextResponse.json(payload);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("GET /api/admin/trainers error:", error);
|
||||||
|
return new NextResponse("Internal Server Error", { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
/**
|
||||||
|
* @jest-environment node
|
||||||
|
*/
|
||||||
|
import { POST as checkIn } from '../check-in/route'
|
||||||
|
import { POST as checkOut } from '../check-out/route'
|
||||||
|
import { GET as history } from '../history/route'
|
||||||
|
import { NextRequest } from 'next/server'
|
||||||
|
|
||||||
|
// Mock dependencies
|
||||||
|
jest.mock('@clerk/nextjs/server', () => ({
|
||||||
|
auth: jest.fn(() => Promise.resolve({ userId: 'test_user_id' })),
|
||||||
|
currentUser: jest.fn(() => Promise.resolve({ id: 'test_user_id', emailAddresses: [{ emailAddress: 'test@example.com' }] }))
|
||||||
|
}))
|
||||||
|
|
||||||
|
jest.mock('@/lib/sync-user', () => ({
|
||||||
|
ensureUserSynced: jest.fn()
|
||||||
|
}))
|
||||||
|
|
||||||
|
const mockDb = {
|
||||||
|
checkIn: jest.fn(),
|
||||||
|
checkOut: jest.fn(),
|
||||||
|
getAttendanceHistory: jest.fn(),
|
||||||
|
getActiveCheckIn: jest.fn(),
|
||||||
|
getUserById: jest.fn(),
|
||||||
|
createUser: jest.fn(),
|
||||||
|
getClientByUserId: jest.fn(),
|
||||||
|
createClient: jest.fn(),
|
||||||
|
getFitnessProfileByUserId: jest.fn(),
|
||||||
|
createFitnessProfile: jest.fn(),
|
||||||
|
}
|
||||||
|
|
||||||
|
jest.mock('@/lib/database', () => ({
|
||||||
|
getDatabase: jest.fn(() => Promise.resolve(mockDb))
|
||||||
|
}))
|
||||||
|
|
||||||
|
describe('Attendance API', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('POST /api/attendance/check-in', () => {
|
||||||
|
it('should successfully check in', async () => {
|
||||||
|
mockDb.getUserById.mockResolvedValue({ id: 'test_user_id' })
|
||||||
|
mockDb.getActiveCheckIn.mockResolvedValue(null)
|
||||||
|
mockDb.checkIn.mockResolvedValue({
|
||||||
|
id: 'attendance_id',
|
||||||
|
userId: 'test_user_id',
|
||||||
|
checkInTime: new Date(),
|
||||||
|
type: 'gym'
|
||||||
|
})
|
||||||
|
|
||||||
|
const req = new NextRequest('http://localhost/api/attendance/check-in', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({ type: 'gym', notes: 'Test check-in' })
|
||||||
|
})
|
||||||
|
|
||||||
|
const res = await checkIn(req)
|
||||||
|
const data = await res.json()
|
||||||
|
|
||||||
|
expect(res.status).toBe(200)
|
||||||
|
expect(data.id).toBe('attendance_id')
|
||||||
|
expect(data.userId).toBe('test_user_id')
|
||||||
|
expect(mockDb.checkIn).toHaveBeenCalledWith('test_user_id', 'gym', 'Test check-in')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should fail if already checked in', async () => {
|
||||||
|
mockDb.getUserById.mockResolvedValue({ id: 'test_user_id' })
|
||||||
|
mockDb.getActiveCheckIn.mockResolvedValue({ id: 'existing_id' })
|
||||||
|
|
||||||
|
const req = new NextRequest('http://localhost/api/attendance/check-in', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({ type: 'gym' })
|
||||||
|
})
|
||||||
|
|
||||||
|
const res = await checkIn(req)
|
||||||
|
const text = await res.text()
|
||||||
|
|
||||||
|
expect(res.status).toBe(400)
|
||||||
|
expect(text).toBe('Already checked in')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('POST /api/attendance/check-out', () => {
|
||||||
|
it('should successfully check out', async () => {
|
||||||
|
mockDb.getActiveCheckIn.mockResolvedValue({ id: 'attendance_id' })
|
||||||
|
mockDb.checkOut.mockResolvedValue({
|
||||||
|
id: 'attendance_id',
|
||||||
|
checkOutTime: new Date()
|
||||||
|
})
|
||||||
|
|
||||||
|
const req = new NextRequest('http://localhost/api/attendance/check-out', {
|
||||||
|
method: 'POST'
|
||||||
|
})
|
||||||
|
|
||||||
|
const res = await checkOut(req)
|
||||||
|
const data = await res.json()
|
||||||
|
|
||||||
|
expect(res.status).toBe(200)
|
||||||
|
expect(data.id).toBe('attendance_id')
|
||||||
|
expect(data.checkOutTime).toBeDefined()
|
||||||
|
expect(mockDb.checkOut).toHaveBeenCalledWith('attendance_id')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should fail if not checked in', async () => {
|
||||||
|
mockDb.getActiveCheckIn.mockResolvedValue(null)
|
||||||
|
|
||||||
|
const req = new NextRequest('http://localhost/api/attendance/check-out', {
|
||||||
|
method: 'POST'
|
||||||
|
})
|
||||||
|
|
||||||
|
const res = await checkOut(req)
|
||||||
|
const text = await res.text()
|
||||||
|
|
||||||
|
expect(res.status).toBe(404)
|
||||||
|
expect(text).toBe('No active check-in found')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('GET /api/attendance/history', () => {
|
||||||
|
it('should return attendance history', async () => {
|
||||||
|
const historyData = [
|
||||||
|
{ id: '1', checkInTime: new Date() },
|
||||||
|
{ id: '2', checkInTime: new Date() }
|
||||||
|
]
|
||||||
|
mockDb.getUserById.mockResolvedValue({ id: 'test_user_id' })
|
||||||
|
mockDb.getAttendanceHistory.mockResolvedValue(historyData)
|
||||||
|
|
||||||
|
const req = new NextRequest('http://localhost/api/attendance/history')
|
||||||
|
const res = await history(req)
|
||||||
|
const data = await res.json()
|
||||||
|
|
||||||
|
expect(res.status).toBe(200)
|
||||||
|
expect(data).toEqual(JSON.parse(JSON.stringify(historyData))) // Handle date serialization
|
||||||
|
expect(mockDb.getAttendanceHistory).toHaveBeenCalledWith('test_user_id')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -13,21 +13,8 @@ export async function POST(req: Request) {
|
|||||||
// Ensure user exists in DB (sync from Clerk if needed)
|
// Ensure user exists in DB (sync from Clerk if needed)
|
||||||
await ensureUserSynced(userId, db)
|
await ensureUserSynced(userId, db)
|
||||||
|
|
||||||
let client = await db.getClientByUserId(userId)
|
|
||||||
|
|
||||||
if (!client) {
|
|
||||||
// Auto-create client profile if it doesn't exist
|
|
||||||
console.log('Client profile not found, creating new one for user:', userId)
|
|
||||||
client = await db.createClient({
|
|
||||||
userId,
|
|
||||||
membershipType: 'basic',
|
|
||||||
membershipStatus: 'active',
|
|
||||||
joinDate: new Date()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if already checked in
|
// Check if already checked in
|
||||||
const activeCheckIn = await db.getActiveCheckIn(client.id)
|
const activeCheckIn = await db.getActiveCheckIn(userId)
|
||||||
if (activeCheckIn) {
|
if (activeCheckIn) {
|
||||||
return new NextResponse('Already checked in', { status: 400 })
|
return new NextResponse('Already checked in', { status: 400 })
|
||||||
}
|
}
|
||||||
@@ -35,7 +22,7 @@ export async function POST(req: Request) {
|
|||||||
const body = await req.json()
|
const body = await req.json()
|
||||||
const { type = 'gym', notes } = body
|
const { type = 'gym', notes } = body
|
||||||
|
|
||||||
const attendance = await db.checkIn(client.id, type, notes)
|
const attendance = await db.checkIn(userId, type, notes)
|
||||||
return NextResponse.json(attendance)
|
return NextResponse.json(attendance)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Check-in error:', error)
|
console.error('Check-in error:', error)
|
||||||
|
|||||||
@@ -8,13 +8,8 @@ export async function POST(req: Request) {
|
|||||||
if (!userId) return new NextResponse('Unauthorized', { status: 401 })
|
if (!userId) return new NextResponse('Unauthorized', { status: 401 })
|
||||||
|
|
||||||
const db = await getDatabase()
|
const db = await getDatabase()
|
||||||
const client = await db.getClientByUserId(userId)
|
|
||||||
|
|
||||||
if (!client) {
|
const activeCheckIn = await db.getActiveCheckIn(userId)
|
||||||
return new NextResponse('Client profile not found', { status: 404 })
|
|
||||||
}
|
|
||||||
|
|
||||||
const activeCheckIn = await db.getActiveCheckIn(client.id)
|
|
||||||
if (!activeCheckIn) {
|
if (!activeCheckIn) {
|
||||||
return new NextResponse('No active check-in found', { status: 404 })
|
return new NextResponse('No active check-in found', { status: 404 })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,20 +22,7 @@ export async function GET(req: Request) {
|
|||||||
// Ensure user exists in DB (sync from Clerk if needed)
|
// Ensure user exists in DB (sync from Clerk if needed)
|
||||||
await ensureUserSynced(userId, db)
|
await ensureUserSynced(userId, db)
|
||||||
|
|
||||||
let client = await db.getClientByUserId(userId)
|
const history = await db.getAttendanceHistory(userId)
|
||||||
|
|
||||||
if (!client) {
|
|
||||||
// Auto-create client profile if it doesn't exist
|
|
||||||
console.log('Client profile not found, creating new one for user:', userId)
|
|
||||||
client = await db.createClient({
|
|
||||||
userId,
|
|
||||||
membershipType: 'basic',
|
|
||||||
membershipStatus: 'active',
|
|
||||||
joinDate: new Date()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const history = await db.getAttendanceHistory(client.id)
|
|
||||||
return NextResponse.json(history)
|
return NextResponse.json(history)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('History error:', error)
|
console.error('History error:', error)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { getDatabase } from '@/lib/database';
|
|||||||
// POST - Mark goal as complete
|
// POST - Mark goal as complete
|
||||||
export async function POST(
|
export async function POST(
|
||||||
req: NextRequest,
|
req: NextRequest,
|
||||||
{ params }: { params: { id: string } }
|
{ params }: { params: Promise<{ id: string }> }
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
const { userId } = await auth();
|
const { userId } = await auth();
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { getDatabase } from '@/lib/database';
|
|||||||
// GET - Get specific goal
|
// GET - Get specific goal
|
||||||
export async function GET(
|
export async function GET(
|
||||||
req: NextRequest,
|
req: NextRequest,
|
||||||
{ params }: { params: { id: string } }
|
{ params }: { params: Promise<{ id: string }> }
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
const { userId } = await auth();
|
const { userId } = await auth();
|
||||||
@@ -40,7 +40,7 @@ export async function GET(
|
|||||||
// PUT - Update goal
|
// PUT - Update goal
|
||||||
export async function PUT(
|
export async function PUT(
|
||||||
req: NextRequest,
|
req: NextRequest,
|
||||||
{ params }: { params: { id: string } }
|
{ params }: { params: Promise<{ id: string }> }
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
const { userId } = await auth();
|
const { userId } = await auth();
|
||||||
@@ -82,7 +82,7 @@ export async function PUT(
|
|||||||
// DELETE - Delete goal
|
// DELETE - Delete goal
|
||||||
export async function DELETE(
|
export async function DELETE(
|
||||||
req: NextRequest,
|
req: NextRequest,
|
||||||
{ params }: { params: { id: string } }
|
{ params }: { params: Promise<{ id: string }> }
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
const { userId } = await auth();
|
const { userId } = await auth();
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
import { NextRequest, NextResponse } from "next/server";
|
|
||||||
import { auth } from "@clerk/nextjs/server";
|
|
||||||
import { getDatabase } from "@/lib/database";
|
|
||||||
|
|
||||||
export async function GET(req: NextRequest) {
|
|
||||||
try {
|
|
||||||
const { userId } = await auth();
|
|
||||||
|
|
||||||
// Return empty array if not authenticated (for testing)
|
|
||||||
if (!userId) {
|
|
||||||
return NextResponse.json([]);
|
|
||||||
}
|
|
||||||
|
|
||||||
const db = await getDatabase();
|
|
||||||
|
|
||||||
// Fetch recent fitness goals (last 5)
|
|
||||||
const recentGoals = await db.getFitnessGoalsByUserId(userId);
|
|
||||||
|
|
||||||
// Take only the 5 most recent and transform to format expected by mobile app
|
|
||||||
const activities = recentGoals.slice(0, 5).map((goal) => ({
|
|
||||||
title: goal.title,
|
|
||||||
subtitle: new Date(goal.createdAt).toLocaleDateString('en-US', {
|
|
||||||
month: 'short',
|
|
||||||
day: 'numeric',
|
|
||||||
hour: '2-digit',
|
|
||||||
minute: '2-digit'
|
|
||||||
}),
|
|
||||||
duration: 45, // Mock duration for now
|
|
||||||
icon: goal.goalType === 'strength_milestone' ? 'barbell' :
|
|
||||||
goal.goalType === 'endurance_target' ? 'bicycle' :
|
|
||||||
'fitness',
|
|
||||||
gradient: goal.goalType === 'strength_milestone' ? 'primary' :
|
|
||||||
goal.goalType === 'endurance_target' ? 'success' :
|
|
||||||
'purple',
|
|
||||||
}));
|
|
||||||
|
|
||||||
return NextResponse.json(activities);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching recent activities:", error);
|
|
||||||
return NextResponse.json([], { status: 200 }); // Return empty array on error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
import { NextResponse } from "next/server";
|
||||||
|
import { auth } from "@clerk/nextjs/server";
|
||||||
|
import { eq, sql } from "@fitai/database";
|
||||||
|
import { db, users as usersTable } from "@fitai/database";
|
||||||
|
import { ensureUserSynced } from "@/lib/sync-user";
|
||||||
|
|
||||||
|
async function ensureGymsTable() {
|
||||||
|
await db.run(sql`
|
||||||
|
CREATE TABLE IF NOT EXISTS gyms (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
location TEXT,
|
||||||
|
status TEXT NOT NULL CHECK (status IN ('active','inactive')) DEFAULT 'active',
|
||||||
|
admin_user_id TEXT NOT NULL,
|
||||||
|
created_at INTEGER NOT NULL,
|
||||||
|
updated_at INTEGER NOT NULL
|
||||||
|
)
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /api/gyms
|
||||||
|
// Lists active gyms for selection (grid)
|
||||||
|
export async function GET() {
|
||||||
|
try {
|
||||||
|
await ensureGymsTable();
|
||||||
|
const rows = await db.all(
|
||||||
|
sql`SELECT * FROM gyms WHERE status = 'active' ORDER BY created_at DESC`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return NextResponse.json(rows);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("GET /gyms error:", error);
|
||||||
|
return new NextResponse("Internal Server Error", { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST /api/gyms
|
||||||
|
// Create a gym. Allowed roles: superAdmin, admin.
|
||||||
|
// - admin: can only create gyms for themselves (adminUserId = current user)
|
||||||
|
// - superAdmin: can create for self or specify adminUserId
|
||||||
|
export async function POST(req: Request) {
|
||||||
|
try {
|
||||||
|
await ensureGymsTable();
|
||||||
|
const { userId } = await auth();
|
||||||
|
if (!userId) return new NextResponse("Unauthorized", { status: 401 });
|
||||||
|
|
||||||
|
// Ensure our local DB has the user synced (role, etc.)
|
||||||
|
const currentUser = await ensureUserSynced(userId, {
|
||||||
|
// minimal facade for ensureUserSynced to work: it expects an object implementing part of IDatabase
|
||||||
|
getUserById: async (id: string) => {
|
||||||
|
const row = await db
|
||||||
|
.select()
|
||||||
|
.from(usersTable)
|
||||||
|
.where(eq(usersTable.id, id))
|
||||||
|
.get();
|
||||||
|
return row
|
||||||
|
? {
|
||||||
|
id: row.id,
|
||||||
|
email: row.email,
|
||||||
|
firstName: row.firstName,
|
||||||
|
lastName: row.lastName,
|
||||||
|
password: row.password ?? "",
|
||||||
|
phone: row.phone ?? undefined,
|
||||||
|
role: row.role,
|
||||||
|
imageUrl: undefined,
|
||||||
|
createdAt: new Date(row.createdAt),
|
||||||
|
updatedAt: new Date(row.updatedAt),
|
||||||
|
}
|
||||||
|
: null;
|
||||||
|
},
|
||||||
|
updateUser: async (id: string, updates: any) => {
|
||||||
|
await db
|
||||||
|
.update(usersTable)
|
||||||
|
.set({
|
||||||
|
...updates,
|
||||||
|
updatedAt: new Date(),
|
||||||
|
})
|
||||||
|
.where(eq(usersTable.id, id))
|
||||||
|
.run();
|
||||||
|
const row = await db
|
||||||
|
.select()
|
||||||
|
.from(usersTable)
|
||||||
|
.where(eq(usersTable.id, id))
|
||||||
|
.get();
|
||||||
|
return row
|
||||||
|
? {
|
||||||
|
id: row.id,
|
||||||
|
email: row.email,
|
||||||
|
firstName: row.firstName,
|
||||||
|
lastName: row.lastName,
|
||||||
|
password: row.password ?? "",
|
||||||
|
phone: row.phone ?? undefined,
|
||||||
|
role: row.role,
|
||||||
|
imageUrl: undefined,
|
||||||
|
createdAt: new Date(row.createdAt),
|
||||||
|
updatedAt: new Date(row.updatedAt),
|
||||||
|
}
|
||||||
|
: null;
|
||||||
|
},
|
||||||
|
} as any);
|
||||||
|
|
||||||
|
if (
|
||||||
|
!currentUser ||
|
||||||
|
(currentUser.role !== "admin" && currentUser.role !== "superAdmin")
|
||||||
|
) {
|
||||||
|
return new NextResponse("Forbidden", { status: 403 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const body = await req.json().catch(() => null);
|
||||||
|
if (!body || typeof body !== "object") {
|
||||||
|
return new NextResponse("Invalid JSON body", { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const name = String(body.name ?? "").trim();
|
||||||
|
const location = body.location ? String(body.location).trim() : null;
|
||||||
|
let adminUserId: string | null = body.adminUserId
|
||||||
|
? String(body.adminUserId)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if (!name) {
|
||||||
|
return NextResponse.json({ error: "name is required" }, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enforce admin ownership rules
|
||||||
|
if (currentUser.role === "admin") {
|
||||||
|
adminUserId = currentUser.id;
|
||||||
|
} else if (currentUser.role === "superAdmin") {
|
||||||
|
adminUserId = adminUserId || currentUser.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Basic check that adminUserId exists and is an admin or superAdmin
|
||||||
|
const adminRow = await db
|
||||||
|
.select()
|
||||||
|
.from(usersTable)
|
||||||
|
.where(eq(usersTable.id, adminUserId!))
|
||||||
|
.get();
|
||||||
|
if (
|
||||||
|
!adminRow ||
|
||||||
|
(adminRow.role !== "admin" && adminRow.role !== "superAdmin")
|
||||||
|
) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "adminUserId must reference an admin or superAdmin" },
|
||||||
|
{ status: 400 },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const id = generateId();
|
||||||
|
const nowTs = Date.now();
|
||||||
|
|
||||||
|
await db.run(
|
||||||
|
sql`INSERT INTO gyms (id, name, location, status, admin_user_id, created_at, updated_at)
|
||||||
|
VALUES (${id}, ${name}, ${location ?? null}, 'active', ${adminUserId!}, ${nowTs}, ${nowTs})`,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Assign the admin to this gym immediately after creation
|
||||||
|
await db.run(
|
||||||
|
sql`UPDATE users SET gym_id = ${id}, updated_at = ${nowTs} WHERE id = ${adminUserId!}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
const created = await db.get(sql`SELECT * FROM gyms WHERE id = ${id}`);
|
||||||
|
return NextResponse.json(created, { status: 201 });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("POST /gyms error:", error);
|
||||||
|
return new NextResponse("Internal Server Error", { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateId(): string {
|
||||||
|
// Simple URL-safe id generator
|
||||||
|
return (
|
||||||
|
Math.random().toString(36).slice(2, 10) +
|
||||||
|
Math.random().toString(36).slice(2, 10)
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
import { NextResponse } from "next/server";
|
||||||
|
import { auth, clerkClient } from "@clerk/nextjs/server";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /api/invitations
|
||||||
|
*
|
||||||
|
* Create a Clerk-managed invitation and store role/gym context in publicMetadata.
|
||||||
|
* This endpoint does not implement invitation acceptance; Clerk’s acceptance link flow and webhooks will handle that.
|
||||||
|
*
|
||||||
|
* Body: {
|
||||||
|
* inviteeEmail: string,
|
||||||
|
* roleAssigned: 'trainer' | 'client' | 'admin'
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* Rules:
|
||||||
|
* - admin: can invite trainer or client; the gymId is taken from inviter's publicMetadata or user record.
|
||||||
|
* - trainer: can invite client; the gymId is taken from inviter's publicMetadata or user record.
|
||||||
|
* - superAdmin: can invite admin; requires `gymId` in body, or falls back to inviter's `gymId` if present.
|
||||||
|
*
|
||||||
|
* Returns Clerk invitation payload.
|
||||||
|
*/
|
||||||
|
export async function POST(req: Request) {
|
||||||
|
try {
|
||||||
|
const { userId } = await auth();
|
||||||
|
if (!userId) {
|
||||||
|
return new NextResponse("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const body = await req.json().catch(() => null);
|
||||||
|
if (!body || typeof body !== "object") {
|
||||||
|
return NextResponse.json({ error: "Invalid JSON body" }, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const inviteeEmail = String(body.inviteeEmail ?? "")
|
||||||
|
.trim()
|
||||||
|
.toLowerCase();
|
||||||
|
const roleAssigned = String(body.roleAssigned ?? "").trim() as
|
||||||
|
| "trainer"
|
||||||
|
| "client"
|
||||||
|
| "admin";
|
||||||
|
let requestedGymId: string | null = body.gymId ? String(body.gymId) : null;
|
||||||
|
|
||||||
|
if (!inviteeEmail || !roleAssigned) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "inviteeEmail and roleAssigned are required" },
|
||||||
|
{ status: 400 },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch inviter user from Clerk
|
||||||
|
const client = await clerkClient();
|
||||||
|
const inviter = await client.users.getUser(userId);
|
||||||
|
const inviterRole =
|
||||||
|
(inviter.publicMetadata?.role as
|
||||||
|
| "superAdmin"
|
||||||
|
| "admin"
|
||||||
|
| "trainer"
|
||||||
|
| "client"
|
||||||
|
| "generalUser") ?? "client";
|
||||||
|
const inviterGymId =
|
||||||
|
(inviter.publicMetadata?.gymId as string | undefined) ?? undefined;
|
||||||
|
|
||||||
|
// Enforce role-based rules and resolve target gymId for the invitation
|
||||||
|
let gymIdForInvite: string | null = null;
|
||||||
|
switch (inviterRole) {
|
||||||
|
case "admin": {
|
||||||
|
if (roleAssigned !== "trainer" && roleAssigned !== "client") {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Admin can only invite trainer or client" },
|
||||||
|
{ status: 403 },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!inviterGymId) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Inviter admin must be assigned to a gym" },
|
||||||
|
{ status: 400 },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
gymIdForInvite = inviterGymId;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "trainer": {
|
||||||
|
if (roleAssigned !== "client") {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Trainer can only invite client" },
|
||||||
|
{ status: 403 },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!inviterGymId) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Inviter trainer must be assigned to a gym" },
|
||||||
|
{ status: 400 },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
gymIdForInvite = inviterGymId;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "superAdmin": {
|
||||||
|
if (
|
||||||
|
roleAssigned !== "admin" &&
|
||||||
|
roleAssigned !== "trainer" &&
|
||||||
|
roleAssigned !== "client"
|
||||||
|
) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Invalid roleAssigned for SuperAdmin" },
|
||||||
|
{ status: 400 },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Prefer explicitly provided gymId, otherwise fall back to inviter's gymId if present
|
||||||
|
gymIdForInvite = requestedGymId || inviterGymId || null;
|
||||||
|
if (!gymIdForInvite) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "gymId is required for SuperAdmin when inviting" },
|
||||||
|
{ status: 400 },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Inviter role not permitted to create invitations" },
|
||||||
|
{ status: 403 },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Clerk invitation with metadata needed by webhook to assign role & gym
|
||||||
|
// reuse existing Clerk client instance
|
||||||
|
const invitation = await client.invitations.createInvitation({
|
||||||
|
emailAddress: inviteeEmail,
|
||||||
|
publicMetadata: {
|
||||||
|
roleAssigned,
|
||||||
|
gymId: gymIdForInvite,
|
||||||
|
inviterUserId: inviter.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return NextResponse.json(invitation, { status: 201 });
|
||||||
|
} catch (error: any) {
|
||||||
|
// Surface Clerk errors where possible
|
||||||
|
const message =
|
||||||
|
error?.errors?.[0]?.message ||
|
||||||
|
error?.message ||
|
||||||
|
"Failed to create invitation";
|
||||||
|
console.error("POST /api/invitations error:", error);
|
||||||
|
return NextResponse.json({ error: message }, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -50,12 +50,11 @@ export async function POST(request: NextRequest) {
|
|||||||
|
|
||||||
export async function GET(request: NextRequest) {
|
export async function GET(request: NextRequest) {
|
||||||
try {
|
try {
|
||||||
|
const db = await getDatabase()
|
||||||
const { searchParams } = new URL(request.url)
|
const { searchParams } = new URL(request.url)
|
||||||
const userId = searchParams.get('userId')
|
const userId = searchParams.get('userId')
|
||||||
|
|
||||||
// If userId is provided, get specific profile
|
|
||||||
if (userId) {
|
if (userId) {
|
||||||
const db = await getDatabase()
|
|
||||||
const profile = await db.getFitnessProfileByUserId(userId)
|
const profile = await db.getFitnessProfileByUserId(userId)
|
||||||
if (!profile) {
|
if (!profile) {
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
@@ -63,24 +62,11 @@ export async function GET(request: NextRequest) {
|
|||||||
{ status: 404 }
|
{ status: 404 }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
return NextResponse.json({ profile })
|
||||||
// Return profile with mock activity data for now
|
|
||||||
// TODO: Fetch real activity data from activity_logs table
|
|
||||||
return NextResponse.json({
|
|
||||||
profile,
|
|
||||||
steps: 0,
|
|
||||||
calories: 0,
|
|
||||||
duration: 0
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For mobile app: return activity data without userId param
|
const profiles = await db.getAllFitnessProfiles()
|
||||||
// This is a simplified endpoint for the mobile ActivityWidget
|
return NextResponse.json({ profiles })
|
||||||
return NextResponse.json({
|
|
||||||
steps: 0,
|
|
||||||
calories: 0,
|
|
||||||
duration: 0
|
|
||||||
})
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Get fitness profiles error:', error)
|
console.error('Get fitness profiles error:', error)
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
|
|||||||
@@ -172,9 +172,9 @@ export async function POST(req: Request) {
|
|||||||
const recommendation = await db.createRecommendation({
|
const recommendation = await db.createRecommendation({
|
||||||
id: crypto.randomUUID(),
|
id: crypto.randomUUID(),
|
||||||
userId,
|
userId,
|
||||||
fitnessProfileId: profile.userId,
|
fitnessProfileId: profile.id,
|
||||||
type: 'ai_plan',
|
type: 'ai_plan',
|
||||||
content: parsedResponse.recommendationText,
|
recommendationText: parsedResponse.recommendationText,
|
||||||
activityPlan: parsedResponse.activityPlan,
|
activityPlan: parsedResponse.activityPlan,
|
||||||
dietPlan: parsedResponse.dietPlan,
|
dietPlan: parsedResponse.dietPlan,
|
||||||
status: 'pending'
|
status: 'pending'
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ export async function POST(request: Request) {
|
|||||||
userId,
|
userId,
|
||||||
fitnessProfileId,
|
fitnessProfileId,
|
||||||
type: 'ai_plan',
|
type: 'ai_plan',
|
||||||
content: recommendationText,
|
recommendationText: recommendationText,
|
||||||
activityPlan,
|
activityPlan,
|
||||||
dietPlan,
|
dietPlan,
|
||||||
status: status || 'pending'
|
status: status || 'pending'
|
||||||
@@ -90,7 +90,7 @@ export async function POST(request: Request) {
|
|||||||
id: crypto.randomUUID(),
|
id: crypto.randomUUID(),
|
||||||
userId,
|
userId,
|
||||||
type,
|
type,
|
||||||
content,
|
recommendationText: content,
|
||||||
status: status || 'pending'
|
status: status || 'pending'
|
||||||
})
|
})
|
||||||
return NextResponse.json(recommendation)
|
return NextResponse.json(recommendation)
|
||||||
@@ -122,8 +122,8 @@ export async function PUT(request: Request) {
|
|||||||
|
|
||||||
const updated = await db.updateRecommendation(id, {
|
const updated = await db.updateRecommendation(id, {
|
||||||
...(status && { status }),
|
...(status && { status }),
|
||||||
...(recommendationText && { content: recommendationText }), // Map legacy field
|
...(recommendationText && { recommendationText }),
|
||||||
...(content && { content }),
|
...(content && { recommendationText: content }),
|
||||||
...(activityPlan && { activityPlan }),
|
...(activityPlan && { activityPlan }),
|
||||||
...(dietPlan && { dietPlan })
|
...(dietPlan && { dietPlan })
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
import { NextResponse } from "next/server";
|
||||||
|
import { auth } from "@clerk/nextjs/server";
|
||||||
|
import { db, users as usersTable, eq, sql } from "@fitai/database";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PATCH /api/users/gym
|
||||||
|
* Body: { gymId: string | null }
|
||||||
|
* - Updates the current authenticated user's gym selection.
|
||||||
|
* - gymId can be null to proceed without a gym.
|
||||||
|
* - If gymId is provided, it must exist and be active.
|
||||||
|
*/
|
||||||
|
export async function PATCH(req: Request) {
|
||||||
|
try {
|
||||||
|
const { userId } = await auth();
|
||||||
|
console.log("PATCH /api/users/gym auth userId:", userId);
|
||||||
|
if (!userId) return new NextResponse("Unauthorized", { status: 401 });
|
||||||
|
|
||||||
|
const body = await req.json().catch(() => null);
|
||||||
|
if (!body || typeof body !== "object" || !("gymId" in body)) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "gymId is required in body (can be null)" },
|
||||||
|
{ status: 400 },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const gymId = body.gymId === null ? null : String(body.gymId);
|
||||||
|
console.log("PATCH /api/users/gym parsed gymId from body:", gymId);
|
||||||
|
|
||||||
|
// Ensure user exists
|
||||||
|
console.log("PATCH /api/users/gym fetching user by id:", userId);
|
||||||
|
const user = await db
|
||||||
|
.select()
|
||||||
|
.from(usersTable)
|
||||||
|
.where(eq(usersTable.id, userId))
|
||||||
|
.get();
|
||||||
|
console.log("PATCH /api/users/gym fetched user:", user);
|
||||||
|
if (!user) return new NextResponse("User not found", { status: 404 });
|
||||||
|
|
||||||
|
// Validate gym when provided
|
||||||
|
if (gymId) {
|
||||||
|
console.log("PATCH /api/users/gym validating gym:", gymId);
|
||||||
|
const rows = await db.all(
|
||||||
|
sql`SELECT status FROM gyms WHERE id = ${gymId} LIMIT 1`,
|
||||||
|
);
|
||||||
|
console.log("PATCH /api/users/gym validation query result rows:", rows);
|
||||||
|
const gym = rows?.[0] as { status?: string } | undefined;
|
||||||
|
if (!gym) {
|
||||||
|
console.log("PATCH /api/users/gym validation: gym not found");
|
||||||
|
return NextResponse.json({ error: "Gym not found" }, { status: 404 });
|
||||||
|
}
|
||||||
|
if (gym.status !== "active") {
|
||||||
|
console.log("PATCH /api/users/gym validation: gym not active", gym);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Gym is not active" },
|
||||||
|
{ status: 400 },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update user's gym selection
|
||||||
|
console.log("PATCH /api/users/gym updating user gym_id:", {
|
||||||
|
userId,
|
||||||
|
gymId,
|
||||||
|
});
|
||||||
|
await db.run(
|
||||||
|
sql`UPDATE users SET gym_id = ${gymId ?? null}, updated_at = ${new Date()} WHERE id = ${userId}`,
|
||||||
|
);
|
||||||
|
console.log("PATCH /api/users/gym update completed");
|
||||||
|
|
||||||
|
const updated = await db
|
||||||
|
.select()
|
||||||
|
.from(usersTable)
|
||||||
|
.where(eq(usersTable.id, userId))
|
||||||
|
.get();
|
||||||
|
console.log("PATCH /api/users/gym returning updated user:", updated);
|
||||||
|
return NextResponse.json(updated);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("PATCH /users/gym error:", error);
|
||||||
|
return new NextResponse("Internal Server Error", { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ import { NextRequest, NextResponse } from "next/server";
|
|||||||
import { getDatabase } from "../../../lib/database/index";
|
import { getDatabase } from "../../../lib/database/index";
|
||||||
import bcrypt from "bcryptjs";
|
import bcrypt from "bcryptjs";
|
||||||
import { auth, clerkClient } from "@clerk/nextjs/server";
|
import { auth, clerkClient } from "@clerk/nextjs/server";
|
||||||
|
import { db as rawDb, sql } from "@fitai/database";
|
||||||
|
|
||||||
export async function GET(request: NextRequest) {
|
export async function GET(request: NextRequest) {
|
||||||
try {
|
try {
|
||||||
@@ -11,18 +12,122 @@ export async function GET(request: NextRequest) {
|
|||||||
|
|
||||||
let users = await db.getAllUsers();
|
let users = await db.getAllUsers();
|
||||||
|
|
||||||
|
// Hydrate gymId from raw DB to ensure consistency with writes
|
||||||
|
const rawUserRows = await rawDb.all(sql`SELECT id, gym_id FROM users`);
|
||||||
|
const gymById = new Map<string, string | null>(
|
||||||
|
(rawUserRows || []).map((r: any) => [
|
||||||
|
r.id as string,
|
||||||
|
(r.gym_id as string | null) ?? null,
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Load gym names for mapping gymId -> gymName
|
||||||
|
const gymRows = await rawDb.all(sql`SELECT id, name FROM gyms`);
|
||||||
|
const gymNames = new Map<string, string>(
|
||||||
|
(gymRows || [])
|
||||||
|
.filter((g: any) => !!g && typeof g.id === "string")
|
||||||
|
.map((g: any) => [
|
||||||
|
g.id as string,
|
||||||
|
(g.name as string) || (g.id as string),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
console.log(
|
||||||
|
"GET /api/users: total users fetched from DB:",
|
||||||
|
Array.isArray(users) ? users.length : 0,
|
||||||
|
);
|
||||||
|
|
||||||
if (role) {
|
if (role) {
|
||||||
users = users.filter((user) => user.role === role);
|
users = users.filter((user) => user.role === role);
|
||||||
}
|
}
|
||||||
|
console.log(
|
||||||
|
"GET /api/users: role filter:",
|
||||||
|
role,
|
||||||
|
"users after filter:",
|
||||||
|
Array.isArray(users) ? users.length : 0,
|
||||||
|
"sample:",
|
||||||
|
users && users[0]
|
||||||
|
? {
|
||||||
|
id: users[0].id,
|
||||||
|
role: users[0].role,
|
||||||
|
gymId: (users as any)[0].gymId,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
);
|
||||||
|
|
||||||
const usersWithClients = await Promise.all(
|
const usersWithClients = await Promise.all(
|
||||||
users.map(async (user) => {
|
users.map(async (user) => {
|
||||||
const { password: _, ...userWithoutPassword } = user;
|
const { password: _, ...userWithoutPassword } = user;
|
||||||
const client = await db.getClientByUserId(user.id);
|
const client = await db.getClientByUserId(user.id);
|
||||||
return { ...userWithoutPassword, client };
|
|
||||||
|
// Get active check-in status and statistics for ALL users
|
||||||
|
let isCheckedIn = false;
|
||||||
|
let checkInTime = null;
|
||||||
|
let lastCheckInTime = null;
|
||||||
|
let checkInsThisWeek = 0;
|
||||||
|
let checkInsThisMonth = 0;
|
||||||
|
|
||||||
|
// Query attendance by userId (works for all user types now)
|
||||||
|
const activeCheckIn = await db.getActiveCheckIn(user.id);
|
||||||
|
if (activeCheckIn) {
|
||||||
|
isCheckedIn = true;
|
||||||
|
checkInTime = activeCheckIn.checkInTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get attendance history for statistics
|
||||||
|
const attendanceHistory = await db.getAttendanceHistory(user.id);
|
||||||
|
|
||||||
|
if (attendanceHistory.length > 0) {
|
||||||
|
// Last check-in is the most recent attendance record
|
||||||
|
lastCheckInTime = attendanceHistory[0].checkInTime;
|
||||||
|
|
||||||
|
// Calculate check-ins in last 7 days
|
||||||
|
const weekAgo = new Date();
|
||||||
|
weekAgo.setDate(weekAgo.getDate() - 7);
|
||||||
|
checkInsThisWeek = attendanceHistory.filter(
|
||||||
|
(a) => new Date(a.checkInTime) >= weekAgo,
|
||||||
|
).length;
|
||||||
|
|
||||||
|
// Calculate check-ins in last 30 days
|
||||||
|
const monthAgo = new Date();
|
||||||
|
monthAgo.setDate(monthAgo.getDate() - 30);
|
||||||
|
checkInsThisMonth = attendanceHistory.filter(
|
||||||
|
(a) => new Date(a.checkInTime) >= monthAgo,
|
||||||
|
).length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...userWithoutPassword,
|
||||||
|
// Override gymId from raw DB hydration to avoid undefined from Drizzle mapping
|
||||||
|
gymId: gymById.get(user.id) ?? (user as any).gymId ?? undefined,
|
||||||
|
// Provide gymName mapped from gyms table
|
||||||
|
gymName: (() => {
|
||||||
|
const gid =
|
||||||
|
gymById.get(user.id) ?? (user as any).gymId ?? undefined;
|
||||||
|
if (!gid) return null;
|
||||||
|
return gymNames.get(gid) ?? null;
|
||||||
|
})(),
|
||||||
|
client,
|
||||||
|
isCheckedIn,
|
||||||
|
checkInTime,
|
||||||
|
lastCheckInTime,
|
||||||
|
checkInsThisWeek,
|
||||||
|
checkInsThisMonth,
|
||||||
|
};
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
"GET /api/users: responding users count:",
|
||||||
|
Array.isArray(usersWithClients) ? usersWithClients.length : 0,
|
||||||
|
"sample:",
|
||||||
|
usersWithClients && usersWithClients[0]
|
||||||
|
? {
|
||||||
|
id: usersWithClients[0].id,
|
||||||
|
role: usersWithClients[0].role,
|
||||||
|
gymId: (usersWithClients as any)[0].gymId,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
);
|
||||||
return NextResponse.json({ users: usersWithClients });
|
return NextResponse.json({ users: usersWithClients });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Get users error:", error);
|
console.error("Get users error:", error);
|
||||||
@@ -60,7 +165,10 @@ export async function POST(request: NextRequest) {
|
|||||||
const currentUser = await db.getUserById(clerkUserId);
|
const currentUser = await db.getUserById(clerkUserId);
|
||||||
|
|
||||||
if (!currentUser) {
|
if (!currentUser) {
|
||||||
return NextResponse.json({ error: "Current user not found in database" }, { status: 403 });
|
return NextResponse.json(
|
||||||
|
{ error: "Current user not found in database" },
|
||||||
|
{ status: 403 },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const body = await request.json();
|
const body = await request.json();
|
||||||
@@ -78,14 +186,14 @@ export async function POST(request: NextRequest) {
|
|||||||
superAdmin: ["admin", "trainer", "client"],
|
superAdmin: ["admin", "trainer", "client"],
|
||||||
admin: ["trainer", "client"],
|
admin: ["trainer", "client"],
|
||||||
trainer: ["client"],
|
trainer: ["client"],
|
||||||
client: []
|
client: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const userRole = currentUser.role as keyof typeof allowed;
|
const userRole = currentUser.role as keyof typeof allowed;
|
||||||
if (!allowed[userRole] || !allowed[userRole].includes(role)) {
|
if (!allowed[userRole] || !allowed[userRole].includes(role)) {
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ error: `You are not authorized to create a ${role}` },
|
{ error: `You are not authorized to create a ${role}` },
|
||||||
{ status: 403 }
|
{ status: 403 },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,20 +215,24 @@ export async function POST(request: NextRequest) {
|
|||||||
publicMetadata: {
|
publicMetadata: {
|
||||||
role,
|
role,
|
||||||
},
|
},
|
||||||
ignoreExisting: true // Don't fail if invite exists
|
ignoreExisting: true, // Don't fail if invite exists
|
||||||
});
|
});
|
||||||
} catch (clerkError: any) {
|
} catch (clerkError: any) {
|
||||||
console.error("Clerk invitation error:", clerkError);
|
console.error("Clerk invitation error:", clerkError);
|
||||||
// If user already exists in Clerk, we might want to handle it.
|
// If user already exists in Clerk, we might want to handle it.
|
||||||
// But for now, let's proceed to create local record if invite sent or if they exist.
|
// But for now, let's proceed to create local record if invite sent or if they exist.
|
||||||
if (clerkError.errors?.[0]?.code === 'form_identifier_exists') {
|
if (clerkError.errors?.[0]?.code === "form_identifier_exists") {
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ error: "User already exists in Clerk system" },
|
{ error: "User already exists in Clerk system" },
|
||||||
{ status: 409 },
|
{ status: 409 },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ error: "Failed to send invitation: " + (clerkError.message || "Unknown error") },
|
{
|
||||||
|
error:
|
||||||
|
"Failed to send invitation: " +
|
||||||
|
(clerkError.message || "Unknown error"),
|
||||||
|
},
|
||||||
{ status: 500 },
|
{ status: 500 },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -137,16 +249,19 @@ export async function POST(request: NextRequest) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// If creating a client, create the client record too
|
// If creating a client, create the client record too
|
||||||
if (role === 'client') {
|
if (role === "client") {
|
||||||
await db.createClient({
|
await db.createClient({
|
||||||
userId: newUserId.id,
|
userId: newUserId.id,
|
||||||
membershipType: 'basic',
|
membershipType: "basic",
|
||||||
membershipStatus: 'active',
|
membershipStatus: "active",
|
||||||
joinDate: new Date()
|
joinDate: new Date(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return NextResponse.json({ userId: newUserId.id, message: "Invitation sent" }, { status: 201 });
|
return NextResponse.json(
|
||||||
|
{ userId: newUserId.id, message: "Invitation sent" },
|
||||||
|
{ status: 201 },
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Create user error:", error);
|
console.error("Create user error:", error);
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
@@ -160,7 +275,16 @@ export async function PUT(request: NextRequest) {
|
|||||||
try {
|
try {
|
||||||
const db = await getDatabase();
|
const db = await getDatabase();
|
||||||
const body = await request.json();
|
const body = await request.json();
|
||||||
const { id, email, firstName, lastName, role, phone } = body;
|
const { id, email, firstName, lastName, role, phone, gymId } = body;
|
||||||
|
console.log("PUT /api/users received body:", {
|
||||||
|
id,
|
||||||
|
email,
|
||||||
|
firstName,
|
||||||
|
lastName,
|
||||||
|
role,
|
||||||
|
phone,
|
||||||
|
gymId,
|
||||||
|
});
|
||||||
|
|
||||||
if (!id) {
|
if (!id) {
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
@@ -169,12 +293,43 @@ export async function PUT(request: NextRequest) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get existing user
|
// Authenticate requester
|
||||||
|
const { userId: requesterId } = await auth();
|
||||||
|
if (!requesterId) {
|
||||||
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch requester and target user
|
||||||
|
const requester = await db.getUserById(requesterId);
|
||||||
|
if (!requester) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Requester not found" },
|
||||||
|
{ status: 403 },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const existingUser = await db.getUserById(id);
|
const existingUser = await db.getUserById(id);
|
||||||
if (!existingUser) {
|
if (!existingUser) {
|
||||||
return NextResponse.json({ error: "User not found" }, { status: 404 });
|
return NextResponse.json({ error: "User not found" }, { status: 404 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Authorization: determine allowed role changes
|
||||||
|
const requesterRole = requester.role;
|
||||||
|
const allowedByRole: Record<string, string[]> = {
|
||||||
|
superAdmin: ["superAdmin", "admin", "trainer", "client", "generalUser"],
|
||||||
|
admin: ["admin", "trainer", "client", "generalUser"],
|
||||||
|
trainer: [], // trainers cannot change roles
|
||||||
|
client: [], // clients cannot change roles
|
||||||
|
generalUser: [], // general users cannot change roles
|
||||||
|
};
|
||||||
|
|
||||||
|
if (role && !allowedByRole[requesterRole]?.includes(role)) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: `Not authorized to assign role '${role}'` },
|
||||||
|
{ status: 403 },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Check if email is being changed and if it's already taken
|
// Check if email is being changed and if it's already taken
|
||||||
if (email && email !== existingUser.email) {
|
if (email && email !== existingUser.email) {
|
||||||
const userWithEmail = await db.getUserByEmail(email);
|
const userWithEmail = await db.getUserByEmail(email);
|
||||||
@@ -186,16 +341,86 @@ export async function PUT(request: NextRequest) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update user
|
// Update Clerk publicMetadata (role/gymId) to propagate via webhook
|
||||||
await db.updateUser(id, {
|
// Note: Only update metadata when a change is requested
|
||||||
email: email || existingUser.email,
|
try {
|
||||||
firstName: firstName || existingUser.firstName,
|
const client = await clerkClient();
|
||||||
lastName: lastName || existingUser.lastName,
|
const publicMetadata: Record<string, unknown> = {};
|
||||||
role: role || existingUser.role,
|
console.log("PUT /api/users preparing Clerk metadata update:", {
|
||||||
phone: phone !== undefined ? phone : existingUser.phone,
|
targetUserId: id,
|
||||||
});
|
role,
|
||||||
|
gymId,
|
||||||
|
});
|
||||||
|
|
||||||
return NextResponse.json({ success: true });
|
if (role) {
|
||||||
|
publicMetadata.role = role;
|
||||||
|
}
|
||||||
|
if (gymId !== undefined) {
|
||||||
|
publicMetadata.gymId = gymId === null ? null : String(gymId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.keys(publicMetadata).length > 0) {
|
||||||
|
console.log(
|
||||||
|
"PUT /api/users calling Clerk updateUser with metadata:",
|
||||||
|
publicMetadata,
|
||||||
|
);
|
||||||
|
const clerkResult = await client.users.updateUser(id, {
|
||||||
|
publicMetadata,
|
||||||
|
});
|
||||||
|
console.log("PUT /api/users Clerk updateUser result:", {
|
||||||
|
id: clerkResult.id,
|
||||||
|
role: clerkResult.publicMetadata?.role,
|
||||||
|
gymId: clerkResult.publicMetadata?.gymId,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log("PUT /api/users no Clerk metadata changes requested");
|
||||||
|
}
|
||||||
|
} catch (clerkErr: any) {
|
||||||
|
console.error("Clerk metadata update error:", clerkErr);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Failed to update role/gym in identity provider" },
|
||||||
|
{ status: 500 },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update local DB for immediate UI feedback (webhook will also sync)
|
||||||
|
console.log(
|
||||||
|
"PUT /api/users raw SQL updating local DB user gym_id and fields",
|
||||||
|
);
|
||||||
|
await rawDb.run(
|
||||||
|
sql`UPDATE users
|
||||||
|
SET email = ${email ?? existingUser.email},
|
||||||
|
first_name = ${firstName ?? existingUser.firstName},
|
||||||
|
last_name = ${lastName ?? existingUser.lastName},
|
||||||
|
role = ${role ?? existingUser.role},
|
||||||
|
phone = ${phone !== undefined && typeof phone === "string" ? phone : (existingUser.phone ?? null)},
|
||||||
|
gym_id = ${gymId !== undefined ? gymId : (existingUser.gymId ?? null)},
|
||||||
|
updated_at = ${Date.now()}
|
||||||
|
WHERE id = ${id}`,
|
||||||
|
);
|
||||||
|
// Read back the updated row to surface gym_id and confirm write
|
||||||
|
const updatedRow = await rawDb.get(
|
||||||
|
sql`SELECT id, email, first_name, last_name, role, phone, gym_id, created_at, updated_at FROM users WHERE id = ${id}`,
|
||||||
|
);
|
||||||
|
console.log("PUT /api/users raw DB row after update:", updatedRow);
|
||||||
|
|
||||||
|
const updatedUser = {
|
||||||
|
...existingUser,
|
||||||
|
email: email ?? existingUser.email,
|
||||||
|
firstName: firstName ?? existingUser.firstName,
|
||||||
|
lastName: lastName ?? existingUser.lastName,
|
||||||
|
role: role ?? existingUser.role,
|
||||||
|
phone: phone !== undefined ? phone : existingUser.phone,
|
||||||
|
gymId:
|
||||||
|
updatedRow?.gym_id !== undefined
|
||||||
|
? updatedRow.gym_id
|
||||||
|
: gymId !== undefined
|
||||||
|
? gymId
|
||||||
|
: existingUser.gymId,
|
||||||
|
};
|
||||||
|
console.log("PUT /api/users responding with updated user:", updatedUser);
|
||||||
|
|
||||||
|
return NextResponse.json({ user: updatedUser });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Update user error:", error);
|
console.error("Update user error:", error);
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
|
|||||||
@@ -78,15 +78,31 @@ export async function POST(req: Request) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine role from metadata or default to 'client'
|
// Determine role & gym from metadata
|
||||||
const role =
|
const role =
|
||||||
(public_metadata?.role as "admin" | "trainer" | "client") || "client";
|
(public_metadata?.role as
|
||||||
|
| "superAdmin"
|
||||||
|
| "admin"
|
||||||
|
| "trainer"
|
||||||
|
| "client"
|
||||||
|
| "generalUser") || "client";
|
||||||
|
let gymId = (public_metadata?.gymId as string | null) ?? null;
|
||||||
|
const inviterUserId =
|
||||||
|
(public_metadata?.inviterUserId as string | undefined) ?? undefined;
|
||||||
|
const roleAssigned =
|
||||||
|
(public_metadata?.roleAssigned as
|
||||||
|
| "superAdmin"
|
||||||
|
| "admin"
|
||||||
|
| "trainer"
|
||||||
|
| "client"
|
||||||
|
| "generalUser"
|
||||||
|
| undefined) ?? role;
|
||||||
|
|
||||||
// Insert user into database with Clerk's user ID
|
// Insert user into database with Clerk's user ID
|
||||||
const now = new Date().toISOString();
|
const now = new Date().toISOString();
|
||||||
const stmt = db.prepare(`
|
const stmt = db.prepare(`
|
||||||
INSERT INTO users (id, email, firstName, lastName, password, phone, role, createdAt, updatedAt)
|
INSERT INTO users (id, email, first_name, last_name, password, phone, role, gym_id, created_at, updated_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
`);
|
`);
|
||||||
|
|
||||||
stmt.run(
|
stmt.run(
|
||||||
@@ -97,11 +113,57 @@ export async function POST(req: Request) {
|
|||||||
"", // Clerk handles authentication
|
"", // Clerk handles authentication
|
||||||
null, // phone
|
null, // phone
|
||||||
role,
|
role,
|
||||||
|
gymId,
|
||||||
now,
|
now,
|
||||||
now,
|
now,
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log(`✅ User ${id} created in database`);
|
// If this is a client invited by a trainer, create trainer-client link
|
||||||
|
if (roleAssigned === "client" && inviterUserId && gymId) {
|
||||||
|
const inviterRow = db
|
||||||
|
.prepare("SELECT role FROM users WHERE id = ?")
|
||||||
|
.get(inviterUserId) as { role?: string } | undefined;
|
||||||
|
|
||||||
|
if (inviterRow?.role === "trainer") {
|
||||||
|
const linkId = `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;
|
||||||
|
const linkStmt = db.prepare(`
|
||||||
|
INSERT INTO trainer_clients (id, trainer_user_id, client_user_id, gym_id, created_at)
|
||||||
|
VALUES (?, ?, ?, ?, ?)
|
||||||
|
`);
|
||||||
|
linkStmt.run(
|
||||||
|
linkId,
|
||||||
|
inviterUserId,
|
||||||
|
id,
|
||||||
|
gymId,
|
||||||
|
new Date().toISOString(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is a trainer without a gymId but has an inviter, inherit inviter's gymId
|
||||||
|
if (
|
||||||
|
(roleAssigned === "trainer" || role === "trainer") &&
|
||||||
|
!gymId &&
|
||||||
|
inviterUserId
|
||||||
|
) {
|
||||||
|
const inviterGymRow = db
|
||||||
|
.prepare("SELECT gym_id FROM users WHERE id = ?")
|
||||||
|
.get(inviterUserId) as { gym_id?: string } | undefined;
|
||||||
|
|
||||||
|
if (inviterGymRow?.gym_id) {
|
||||||
|
const inheritStmt = db.prepare(`
|
||||||
|
UPDATE users
|
||||||
|
SET gym_id = ?, updated_at = ?
|
||||||
|
WHERE id = ?
|
||||||
|
`);
|
||||||
|
inheritStmt.run(inviterGymRow.gym_id, new Date().toISOString(), id);
|
||||||
|
gymId = inviterGymRow.gym_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`✅ User ${id} created in database (role=${role}, gymId=${gymId ?? "null"})`,
|
||||||
|
);
|
||||||
db.close();
|
db.close();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -124,15 +186,21 @@ export async function POST(req: Request) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine role from metadata
|
// Determine role & gym from metadata
|
||||||
const role =
|
const role =
|
||||||
(public_metadata?.role as "admin" | "trainer" | "client") || "client";
|
(public_metadata?.role as
|
||||||
|
| "superAdmin"
|
||||||
|
| "admin"
|
||||||
|
| "trainer"
|
||||||
|
| "client"
|
||||||
|
| "generalUser") || "client";
|
||||||
|
let gymId = (public_metadata?.gymId as string | null) ?? null;
|
||||||
|
|
||||||
// Update user in database
|
// Update user in database
|
||||||
const now = new Date().toISOString();
|
const now = new Date().toISOString();
|
||||||
const stmt = db.prepare(`
|
const stmt = db.prepare(`
|
||||||
UPDATE users
|
UPDATE users
|
||||||
SET email = ?, firstName = ?, lastName = ?, role = ?, updatedAt = ?
|
SET email = ?, first_name = ?, last_name = ?, role = ?, gym_id = ?, updated_at = ?
|
||||||
WHERE id = ?
|
WHERE id = ?
|
||||||
`);
|
`);
|
||||||
|
|
||||||
@@ -141,10 +209,33 @@ export async function POST(req: Request) {
|
|||||||
first_name || "",
|
first_name || "",
|
||||||
last_name || "",
|
last_name || "",
|
||||||
role,
|
role,
|
||||||
|
gymId,
|
||||||
now,
|
now,
|
||||||
id,
|
id,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// If user is a trainer and gymId is missing, attempt to inherit from inviter when available
|
||||||
|
if (
|
||||||
|
role === "trainer" &&
|
||||||
|
!gymId &&
|
||||||
|
evt.data.public_metadata?.inviterUserId
|
||||||
|
) {
|
||||||
|
const inviterUserId = String(evt.data.public_metadata.inviterUserId);
|
||||||
|
const inviterGymRow = db
|
||||||
|
.prepare("SELECT gym_id FROM users WHERE id = ?")
|
||||||
|
.get(inviterUserId) as { gym_id?: string } | undefined;
|
||||||
|
|
||||||
|
if (inviterGymRow?.gym_id) {
|
||||||
|
const inheritStmt = db.prepare(`
|
||||||
|
UPDATE users
|
||||||
|
SET gym_id = ?, updated_at = ?
|
||||||
|
WHERE id = ?
|
||||||
|
`);
|
||||||
|
inheritStmt.run(inviterGymRow.gym_id, new Date().toISOString(), id);
|
||||||
|
gymId = inviterGymRow.gym_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
console.log(`✅ User ${id} updated in database`);
|
console.log(`✅ User ${id} updated in database`);
|
||||||
db.close();
|
db.close();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export default function RootLayout({
|
|||||||
<body className={inter.className}>
|
<body className={inter.className}>
|
||||||
<div className="flex min-h-screen bg-slate-50">
|
<div className="flex min-h-screen bg-slate-50">
|
||||||
<Sidebar />
|
<Sidebar />
|
||||||
<main className="flex-1 ml-64 p-8">
|
<main className="flex-1 ml-20 p-8">
|
||||||
{children}
|
{children}
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -87,12 +87,11 @@ export default function Home() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
<div className="flex flex-col gap-8">
|
||||||
<div className="lg:col-span-2 bg-white rounded-xl shadow-sm border border-slate-100 p-6">
|
<div className="bg-white rounded-xl shadow-sm border border-slate-100 p-6">
|
||||||
<h3 className="text-xl font-bold text-slate-900 mb-6">Recent Activity</h3>
|
<h3 className="text-xl font-bold text-slate-900 mb-6">Recent Activity</h3>
|
||||||
<UserManagement />
|
<UserManagement />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="bg-white rounded-xl shadow-sm border border-slate-100 p-6">
|
<div className="bg-white rounded-xl shadow-sm border border-slate-100 p-6">
|
||||||
<h3 className="text-xl font-bold text-slate-900 mb-6">Quick Analytics</h3>
|
<h3 className="text-xl font-bold text-slate-900 mb-6">Quick Analytics</h3>
|
||||||
<AnalyticsDashboard />
|
<AnalyticsDashboard />
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useUser } from "@clerk/nextjs";
|
import { useUser } from "@clerk/nextjs";
|
||||||
import { Button } from "@/components/ui/Button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
|
|
||||||
interface UserProfile {
|
interface UserProfile {
|
||||||
|
|||||||
@@ -219,7 +219,7 @@ export default function RecommendationsPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="space-y-2 text-sm mb-4">
|
<div className="space-y-2 text-sm mb-4">
|
||||||
<div>
|
<div>
|
||||||
<span className="font-semibold">Advice:</span> {rec.content}
|
<span className="font-semibold">Advice:</span> {rec.recommendationText}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span className="font-semibold">Activity:</span> {rec.activityPlan}
|
<span className="font-semibold">Activity:</span> {rec.activityPlan}
|
||||||
|
|||||||
@@ -0,0 +1,486 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import axios from "axios";
|
||||||
|
import {
|
||||||
|
Database,
|
||||||
|
Download,
|
||||||
|
RefreshCw,
|
||||||
|
AlertTriangle,
|
||||||
|
Check,
|
||||||
|
Loader2,
|
||||||
|
} from "lucide-react";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { useUser } from "@clerk/nextjs";
|
||||||
|
|
||||||
|
interface Backup {
|
||||||
|
name: string;
|
||||||
|
size: number;
|
||||||
|
createdAt: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Gym {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
location?: string | null;
|
||||||
|
status: "active" | "inactive";
|
||||||
|
adminUserId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function SettingsPage() {
|
||||||
|
const { user } = useUser();
|
||||||
|
const [backups, setBackups] = useState<Backup[]>([]);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [creatingBackup, setCreatingBackup] = useState(false);
|
||||||
|
const [restoring, setRestoring] = useState<string | null>(null);
|
||||||
|
const [message, setMessage] = useState<{
|
||||||
|
type: "success" | "error";
|
||||||
|
text: string;
|
||||||
|
} | null>(null);
|
||||||
|
|
||||||
|
// Gym picker state
|
||||||
|
const [gyms, setGyms] = useState<Gym[]>([]);
|
||||||
|
const [gymsLoading, setGymsLoading] = useState<boolean>(true);
|
||||||
|
const [gymMessage, setGymMessage] = useState<{
|
||||||
|
type: "success" | "error";
|
||||||
|
text: string;
|
||||||
|
} | null>(null);
|
||||||
|
// Create Gym modal state
|
||||||
|
const [showCreateGym, setShowCreateGym] = useState(false);
|
||||||
|
const [gymName, setGymName] = useState("");
|
||||||
|
const [gymLocation, setGymLocation] = useState("");
|
||||||
|
const [creatingGym, setCreatingGym] = useState(false);
|
||||||
|
|
||||||
|
const fetchBackups = async () => {
|
||||||
|
try {
|
||||||
|
const response = await axios.get("/api/admin/backups");
|
||||||
|
setBackups(response.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to fetch backups:", error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchGyms = async () => {
|
||||||
|
setGymsLoading(true);
|
||||||
|
setGymMessage(null);
|
||||||
|
try {
|
||||||
|
const res = await axios.get("/api/gyms");
|
||||||
|
setGyms(Array.isArray(res.data) ? res.data : []);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to fetch gyms:", error);
|
||||||
|
setGymMessage({ type: "error", text: "Failed to load gyms" });
|
||||||
|
} finally {
|
||||||
|
setGymsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchBackups();
|
||||||
|
fetchGyms();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleCreateBackup = async () => {
|
||||||
|
setCreatingBackup(true);
|
||||||
|
setMessage(null);
|
||||||
|
try {
|
||||||
|
await axios.post("/api/admin/backups");
|
||||||
|
await fetchBackups();
|
||||||
|
setMessage({ type: "success", text: "Backup created successfully" });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to create backup:", error);
|
||||||
|
setMessage({ type: "error", text: "Failed to create backup" });
|
||||||
|
} finally {
|
||||||
|
setCreatingBackup(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRestore = async (filename: string) => {
|
||||||
|
if (
|
||||||
|
!window.confirm(
|
||||||
|
`Are you sure you want to restore from ${filename}? This will overwrite the current database.`,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setRestoring(filename);
|
||||||
|
setMessage(null);
|
||||||
|
try {
|
||||||
|
await axios.post("/api/admin/backups/restore", { filename });
|
||||||
|
setMessage({ type: "success", text: "Database restored successfully" });
|
||||||
|
// Optional: Refresh page or force re-login if session is invalidated
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to restore backup:", error);
|
||||||
|
setMessage({ type: "error", text: "Failed to restore backup" });
|
||||||
|
} finally {
|
||||||
|
setRestoring(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatSize = (bytes: number) => {
|
||||||
|
const units = ["B", "KB", "MB", "GB"];
|
||||||
|
let size = bytes;
|
||||||
|
let unitIndex = 0;
|
||||||
|
while (size >= 1024 && unitIndex < units.length - 1) {
|
||||||
|
size /= 1024;
|
||||||
|
unitIndex++;
|
||||||
|
}
|
||||||
|
return `${size.toFixed(2)} ${units[unitIndex]}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatDate = (dateString: string) => {
|
||||||
|
return new Date(dateString).toLocaleString();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSelectGym = async (gymId: string | null) => {
|
||||||
|
setGymMessage(null);
|
||||||
|
try {
|
||||||
|
// Update current user's gym selection
|
||||||
|
await axios.patch("/api/users/gym", { gymId });
|
||||||
|
setGymMessage({
|
||||||
|
type: "success",
|
||||||
|
text: gymId ? "Gym selected successfully" : "Proceeding without gym",
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to set gym:", error);
|
||||||
|
setGymMessage({ type: "error", text: "Failed to set gym" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-8 p-8">
|
||||||
|
<div>
|
||||||
|
<h2 className="text-3xl font-bold text-slate-900">Settings</h2>
|
||||||
|
<p className="text-slate-500 mt-2">
|
||||||
|
Manage your application settings and database.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Gym Picker */}
|
||||||
|
<div className="bg-white rounded-xl shadow-sm border border-slate-100 p-6">
|
||||||
|
<div className="flex items-center justify-between mb-6">
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<div className="p-2 bg-blue-50 rounded-lg">
|
||||||
|
<Database className="w-6 h-6 text-blue-600" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 className="text-xl font-bold text-slate-900">
|
||||||
|
Gym Selection
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-slate-500">
|
||||||
|
Select your gym or proceed without a gym
|
||||||
|
</p>
|
||||||
|
<p className="text-xs text-blue-600 mt-1">
|
||||||
|
{user ? (
|
||||||
|
<>
|
||||||
|
Current role:{" "}
|
||||||
|
<span className="font-medium">
|
||||||
|
{String(user.publicMetadata?.role ?? "unknown")}
|
||||||
|
</span>
|
||||||
|
{" • "}
|
||||||
|
Gym ID:{" "}
|
||||||
|
<span className="font-medium">
|
||||||
|
{String(user.publicMetadata?.gymId ?? "none")}
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
"Loading user metadata..."
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Button
|
||||||
|
onClick={fetchGyms}
|
||||||
|
disabled={gymsLoading}
|
||||||
|
className="flex items-center gap-2"
|
||||||
|
>
|
||||||
|
{gymsLoading ? (
|
||||||
|
<Loader2 className="w-4 h-4 animate-spin" />
|
||||||
|
) : (
|
||||||
|
<RefreshCw className="w-4 h-4" />
|
||||||
|
)}
|
||||||
|
Refresh Gyms
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={() => setShowCreateGym(true)}
|
||||||
|
className="flex items-center gap-2"
|
||||||
|
>
|
||||||
|
Create Gym
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{gymMessage && (
|
||||||
|
<div
|
||||||
|
className={`p-4 rounded-lg mb-6 flex items-center gap-2 ${gymMessage.type === "success" ? "bg-green-50 text-green-700" : "bg-red-50 text-red-700"}`}
|
||||||
|
>
|
||||||
|
{gymMessage.type === "success" ? (
|
||||||
|
<Check className="w-5 h-5" />
|
||||||
|
) : (
|
||||||
|
<AlertTriangle className="w-5 h-5" />
|
||||||
|
)}
|
||||||
|
{gymMessage.text}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{showCreateGym && (
|
||||||
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
||||||
|
<div className="bg-white p-6 rounded-lg shadow-lg max-w-md w-full">
|
||||||
|
<h3 className="text-lg font-semibold mb-4">Create Gym</h3>
|
||||||
|
<form
|
||||||
|
onSubmit={async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
try {
|
||||||
|
setCreatingGym(true);
|
||||||
|
await axios.post("/api/gyms", {
|
||||||
|
name: gymName.trim(),
|
||||||
|
location: gymLocation.trim() || undefined,
|
||||||
|
});
|
||||||
|
setGymMessage({
|
||||||
|
type: "success",
|
||||||
|
text: "Gym created successfully",
|
||||||
|
});
|
||||||
|
setShowCreateGym(false);
|
||||||
|
setGymName("");
|
||||||
|
setGymLocation("");
|
||||||
|
fetchGyms();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to create gym:", error);
|
||||||
|
setGymMessage({
|
||||||
|
type: "error",
|
||||||
|
text: "Failed to create gym",
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
setCreatingGym(false);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="mb-4">
|
||||||
|
<label className="block text-sm font-medium mb-1">
|
||||||
|
Gym Name
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={gymName}
|
||||||
|
onChange={(e) => setGymName(e.target.value)}
|
||||||
|
className="w-full border border-gray-300 rounded px-3 py-2"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-4">
|
||||||
|
<label className="block text-sm font-medium mb-1">
|
||||||
|
Location (optional)
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={gymLocation}
|
||||||
|
onChange={(e) => setGymLocation(e.target.value)}
|
||||||
|
className="w-full border border-gray-300 rounded px-3 py-2"
|
||||||
|
placeholder="Enter location"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-end gap-2">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => {
|
||||||
|
setShowCreateGym(false);
|
||||||
|
setGymName("");
|
||||||
|
setGymLocation("");
|
||||||
|
}}
|
||||||
|
className="px-4 py-2 bg-gray-300 text-gray-700 rounded hover:bg-gray-400"
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={creatingGym}
|
||||||
|
className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 flex items-center gap-2"
|
||||||
|
>
|
||||||
|
{creatingGym ? (
|
||||||
|
<Loader2 className="w-4 h-4 animate-spin" />
|
||||||
|
) : null}
|
||||||
|
Create
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||||
|
<div className="border rounded-lg p-4 flex flex-col justify-between">
|
||||||
|
<div>
|
||||||
|
<h4 className="font-semibold text-slate-900">
|
||||||
|
Proceed without gym
|
||||||
|
</h4>
|
||||||
|
<p className="text-sm text-slate-600 mt-1">
|
||||||
|
You can select a gym later.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
className="mt-4"
|
||||||
|
onClick={() => handleSelectGym(null)}
|
||||||
|
>
|
||||||
|
Proceed without gym
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{gymsLoading ? (
|
||||||
|
<div className="col-span-full flex items-center justify-center p-8 text-slate-500">
|
||||||
|
<Loader2 className="w-5 h-5 animate-spin mr-2" />
|
||||||
|
Loading gyms...
|
||||||
|
</div>
|
||||||
|
) : gyms.length === 0 ? (
|
||||||
|
<div className="col-span-full p-8 text-center text-slate-500">
|
||||||
|
No active gyms found.
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
gyms.map((gym) => (
|
||||||
|
<div
|
||||||
|
key={gym.id}
|
||||||
|
className="border rounded-lg p-4 flex flex-col justify-between"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<h4 className="font-semibold text-slate-900">{gym.name}</h4>
|
||||||
|
<p className="text-sm text-slate-600 mt-1">
|
||||||
|
{gym.location || "No location provided"}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
variant="default"
|
||||||
|
className="mt-4"
|
||||||
|
onClick={() => handleSelectGym(gym.id)}
|
||||||
|
>
|
||||||
|
Select this gym
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="bg-white rounded-xl shadow-sm border border-slate-100 p-6">
|
||||||
|
<div className="flex items-center justify-between mb-6">
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<div className="p-2 bg-blue-50 rounded-lg">
|
||||||
|
<Database className="w-6 h-6 text-blue-600" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 className="text-xl font-bold text-slate-900">
|
||||||
|
Database Management
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-slate-500">
|
||||||
|
Create backups and restore your database
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
onClick={handleCreateBackup}
|
||||||
|
disabled={creatingBackup}
|
||||||
|
className="flex items-center gap-2"
|
||||||
|
>
|
||||||
|
{creatingBackup ? (
|
||||||
|
<Loader2 className="w-4 h-4 animate-spin" />
|
||||||
|
) : (
|
||||||
|
<Download className="w-4 h-4" />
|
||||||
|
)}
|
||||||
|
Create Backup
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{message && (
|
||||||
|
<div
|
||||||
|
className={`p-4 rounded-lg mb-6 flex items-center gap-2 ${
|
||||||
|
message.type === "success"
|
||||||
|
? "bg-green-50 text-green-700"
|
||||||
|
: "bg-red-50 text-red-700"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{message.type === "success" ? (
|
||||||
|
<Check className="w-5 h-5" />
|
||||||
|
) : (
|
||||||
|
<AlertTriangle className="w-5 h-5" />
|
||||||
|
)}
|
||||||
|
{message.text}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="border rounded-lg overflow-hidden">
|
||||||
|
<table className="w-full text-left text-sm">
|
||||||
|
<thead className="bg-slate-50 border-b">
|
||||||
|
<tr>
|
||||||
|
<th className="px-6 py-4 font-semibold text-slate-900">
|
||||||
|
Filename
|
||||||
|
</th>
|
||||||
|
<th className="px-6 py-4 font-semibold text-slate-900">Size</th>
|
||||||
|
<th className="px-6 py-4 font-semibold text-slate-900">
|
||||||
|
Created At
|
||||||
|
</th>
|
||||||
|
<th className="px-6 py-4 font-semibold text-slate-900 text-right">
|
||||||
|
Actions
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="divide-y">
|
||||||
|
{loading ? (
|
||||||
|
<tr>
|
||||||
|
<td
|
||||||
|
colSpan={4}
|
||||||
|
className="px-6 py-8 text-center text-slate-500"
|
||||||
|
>
|
||||||
|
Loading backups...
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
) : backups.length === 0 ? (
|
||||||
|
<tr>
|
||||||
|
<td
|
||||||
|
colSpan={4}
|
||||||
|
className="px-6 py-8 text-center text-slate-500"
|
||||||
|
>
|
||||||
|
No backups found
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
) : (
|
||||||
|
backups.map((backup) => (
|
||||||
|
<tr
|
||||||
|
key={backup.name}
|
||||||
|
className="hover:bg-slate-50 transition-colors"
|
||||||
|
>
|
||||||
|
<td className="px-6 py-4 font-medium text-slate-900">
|
||||||
|
{backup.name}
|
||||||
|
</td>
|
||||||
|
<td className="px-6 py-4 text-slate-600">
|
||||||
|
{formatSize(backup.size)}
|
||||||
|
</td>
|
||||||
|
<td className="px-6 py-4 text-slate-600">
|
||||||
|
{formatDate(backup.createdAt)}
|
||||||
|
</td>
|
||||||
|
<td className="px-6 py-4 text-right">
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => handleRestore(backup.name)}
|
||||||
|
disabled={!!restoring}
|
||||||
|
className="text-red-600 hover:text-red-700 hover:bg-red-50"
|
||||||
|
>
|
||||||
|
{restoring === backup.name ? (
|
||||||
|
<Loader2 className="w-4 h-4 animate-spin" />
|
||||||
|
) : (
|
||||||
|
<RefreshCw className="w-4 h-4 mr-2" />
|
||||||
|
)}
|
||||||
|
Restore
|
||||||
|
</Button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -3,10 +3,10 @@
|
|||||||
import { type ReactElement } from "react";
|
import { type ReactElement } from "react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { usePathname } from "next/navigation";
|
import { usePathname } from "next/navigation";
|
||||||
import { Home, Users, BarChart3, User, Brain } from "lucide-react";
|
import { Home, Users, BarChart3, User, Brain, Settings } from "lucide-react";
|
||||||
import { SignedIn, UserButton } from "@clerk/nextjs";
|
import { SignedIn, UserButton } from "@clerk/nextjs";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { Button } from "@/components/ui/Button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
|
||||||
interface NavItem {
|
interface NavItem {
|
||||||
href: string;
|
href: string;
|
||||||
@@ -40,6 +40,11 @@ const navItems: NavItem[] = [
|
|||||||
label: "Profile",
|
label: "Profile",
|
||||||
icon: User,
|
icon: User,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
href: "/settings",
|
||||||
|
label: "Settings",
|
||||||
|
icon: Settings,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export function Navigation(): ReactElement {
|
export function Navigation(): ReactElement {
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export function AnalyticsDashboard() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6 w-full">
|
||||||
<h2 className="text-2xl font-bold">Analytics Dashboard</h2>
|
<h2 className="text-2xl font-bold">Analytics Dashboard</h2>
|
||||||
|
|
||||||
{/* Key Metrics */}
|
{/* Key Metrics */}
|
||||||
@@ -132,7 +132,13 @@ export function AnalyticsDashboard() {
|
|||||||
<h3 className="text-lg font-semibold">Monthly Revenue</h3>
|
<h3 className="text-lg font-semibold">Monthly Revenue</h3>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<RevenueChart data={revenueData} />
|
<RevenueChart
|
||||||
|
data={revenueData.map(item => ({
|
||||||
|
category: item.label,
|
||||||
|
value: item.value,
|
||||||
|
color: item.color
|
||||||
|
}))}
|
||||||
|
/>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
|
|
||||||
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
||||||
variant?: 'primary' | 'secondary'
|
|
||||||
children: React.ReactNode
|
|
||||||
}
|
|
||||||
|
|
||||||
export function Button({ variant = 'primary', children, className = '', ...props }: ButtonProps) {
|
|
||||||
const baseClasses = 'px-4 py-2 rounded-md font-medium transition-colors'
|
|
||||||
const variantClasses = {
|
|
||||||
primary: 'bg-blue-600 text-white hover:bg-blue-700',
|
|
||||||
secondary: 'bg-gray-200 text-gray-900 hover:bg-gray-300',
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
className={`${baseClasses} ${variantClasses[variant]} ${className}`}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</button>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
|
|
||||||
interface CardProps {
|
|
||||||
children: React.ReactNode
|
|
||||||
className?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export function Card({ children, className = '' }: CardProps) {
|
|
||||||
return (
|
|
||||||
<div className={`bg-white rounded-lg shadow-md p-6 ${className}`}>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function CardHeader({ children, className = '' }: CardProps) {
|
|
||||||
return (
|
|
||||||
<div className={`mb-4 ${className}`}>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function CardContent({ children, className = '' }: CardProps) {
|
|
||||||
return (
|
|
||||||
<div className={className}>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -65,9 +65,9 @@ export function Sidebar() {
|
|||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<aside className="w-64 bg-slate-900 text-white h-screen fixed left-0 top-0 flex flex-col border-r border-slate-800">
|
<aside className="w-20 hover:w-64 bg-slate-900 text-white h-screen fixed left-0 top-0 flex flex-col border-r border-slate-800 transition-all duration-300 z-50 group overflow-hidden">
|
||||||
<div className="p-6 border-b border-slate-800">
|
<div className="p-6 border-b border-slate-800 flex items-center overflow-hidden whitespace-nowrap">
|
||||||
<h1 className="text-2xl font-bold bg-gradient-to-r from-blue-400 to-indigo-400 bg-clip-text text-transparent">
|
<h1 className="text-2xl font-bold bg-gradient-to-r from-blue-400 to-indigo-400 bg-clip-text text-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300">
|
||||||
FitAI Admin
|
FitAI Admin
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
@@ -81,21 +81,27 @@ export function Sidebar() {
|
|||||||
<Link
|
<Link
|
||||||
key={item.href}
|
key={item.href}
|
||||||
href={item.href}
|
href={item.href}
|
||||||
className={`flex items-center gap-3 px-4 py-3 rounded-lg transition-all duration-200 group ${isActive
|
className={`flex items-center gap-3 px-4 py-3 rounded-lg transition-all duration-200 ${isActive
|
||||||
? "bg-blue-600 text-white shadow-lg shadow-blue-900/20"
|
? "bg-blue-600 text-white shadow-lg shadow-blue-900/20"
|
||||||
: "text-slate-400 hover:bg-slate-800 hover:text-white"}`}
|
: "text-slate-400 hover:bg-slate-800 hover:text-white"}`}
|
||||||
>
|
>
|
||||||
<Icon size={20} className={isActive ? "text-white" : "text-slate-500 group-hover:text-white"} />
|
<div className="min-w-[20px]">
|
||||||
<span className="font-medium">{label}</span>
|
<Icon size={20} className={isActive ? "text-white" : "text-slate-500 group-hover:text-white"} />
|
||||||
|
</div>
|
||||||
|
<span className="font-medium opacity-0 group-hover:opacity-100 transition-opacity duration-300 whitespace-nowrap overflow-hidden">
|
||||||
|
{label}
|
||||||
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div className="p-4 border-t border-slate-800">
|
<div className="p-4 border-t border-slate-800">
|
||||||
<div className="flex items-center gap-3 px-4 py-3 rounded-lg bg-slate-800/50">
|
<div className="flex items-center gap-3 px-2 py-3 rounded-lg bg-slate-800/50 overflow-hidden whitespace-nowrap">
|
||||||
<UserButton afterSignOutUrl="/" />
|
<div className="min-w-[32px]">
|
||||||
<div className="flex-1 min-w-0">
|
<UserButton afterSignOutUrl="/" />
|
||||||
|
</div>
|
||||||
|
<div className="flex-1 min-w-0 opacity-0 group-hover:opacity-100 transition-opacity duration-300">
|
||||||
<p className="text-sm font-medium text-white truncate">
|
<p className="text-sm font-medium text-white truncate">
|
||||||
{user?.fullName || "Admin User"}
|
{user?.fullName || "Admin User"}
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -1,56 +1,49 @@
|
|||||||
import * as React from "react";
|
import React from 'react'
|
||||||
import { Slot } from "@radix-ui/react-slot";
|
import { cn } from '@/lib/utils'
|
||||||
import { cva, type VariantProps } from "class-variance-authority";
|
import { Loader2 } from 'lucide-react'
|
||||||
|
|
||||||
import { cn } from "@/lib/utils";
|
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||||
|
variant?: 'primary' | 'secondary' | 'ghost' | 'destructive' | 'outline' | 'default'
|
||||||
const buttonVariants = cva(
|
size?: 'default' | 'sm' | 'lg' | 'icon'
|
||||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
isLoading?: boolean
|
||||||
{
|
children: React.ReactNode
|
||||||
variants: {
|
|
||||||
variant: {
|
|
||||||
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
||||||
destructive:
|
|
||||||
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
|
||||||
outline:
|
|
||||||
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
|
|
||||||
secondary:
|
|
||||||
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
||||||
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
||||||
link: "text-primary underline-offset-4 hover:underline",
|
|
||||||
},
|
|
||||||
size: {
|
|
||||||
default: "h-10 px-4 py-2",
|
|
||||||
sm: "h-9 rounded-md px-3",
|
|
||||||
lg: "h-11 rounded-md px-8",
|
|
||||||
icon: "h-10 w-10",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
defaultVariants: {
|
|
||||||
variant: "default",
|
|
||||||
size: "default",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
export interface ButtonProps
|
|
||||||
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
||||||
VariantProps<typeof buttonVariants> {
|
|
||||||
asChild?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
export function Button({
|
||||||
({ className, variant, size, asChild = false, ...props }, ref) => {
|
variant = 'primary',
|
||||||
const Comp = asChild ? Slot : "button";
|
size = 'default',
|
||||||
return (
|
isLoading = false,
|
||||||
<Comp
|
children,
|
||||||
className={cn(buttonVariants({ variant, size, className }))}
|
className = '',
|
||||||
ref={ref}
|
disabled,
|
||||||
{...props}
|
...props
|
||||||
/>
|
}: ButtonProps) {
|
||||||
);
|
const baseClasses = 'inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50'
|
||||||
},
|
|
||||||
);
|
|
||||||
Button.displayName = "Button";
|
|
||||||
|
|
||||||
export { Button, buttonVariants };
|
const variantClasses = {
|
||||||
|
primary: 'bg-blue-600 text-white hover:bg-blue-700 shadow hover:bg-blue-700/90',
|
||||||
|
default: 'bg-blue-600 text-white hover:bg-blue-700 shadow hover:bg-blue-700/90',
|
||||||
|
secondary: 'bg-slate-100 text-slate-900 hover:bg-slate-200/80',
|
||||||
|
ghost: 'hover:bg-slate-100 hover:text-slate-900',
|
||||||
|
destructive: 'bg-red-500 text-white hover:bg-red-600/90',
|
||||||
|
outline: 'border border-input bg-transparent shadow-sm hover:bg-slate-100 hover:text-slate-900'
|
||||||
|
}
|
||||||
|
|
||||||
|
const sizeClasses = {
|
||||||
|
default: 'h-9 px-4 py-2',
|
||||||
|
sm: 'h-8 rounded-md px-3 text-xs',
|
||||||
|
lg: 'h-10 rounded-md px-8',
|
||||||
|
icon: 'h-9 w-9'
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
className={cn(baseClasses, variantClasses[variant], sizeClasses[size], className)}
|
||||||
|
disabled={disabled || isLoading}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{isLoading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
|
||||||
|
{children}
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { Button } from "@/components/ui/Button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Card, CardHeader, CardContent } from "@/components/ui/card";
|
import { Card, CardHeader, CardContent } from "@/components/ui/card";
|
||||||
|
|
||||||
interface Recommendation {
|
interface Recommendation {
|
||||||
id: string;
|
id: string;
|
||||||
userId: string;
|
userId: string;
|
||||||
type: "short_term" | "medium_term" | "long_term" | "ai_plan";
|
type: "short_term" | "medium_term" | "long_term" | "ai_plan";
|
||||||
content: string;
|
recommendationText: string;
|
||||||
activityPlan?: string;
|
activityPlan?: string;
|
||||||
dietPlan?: string;
|
dietPlan?: string;
|
||||||
status: "pending" | "completed" | "approved" | "rejected";
|
status: "pending" | "completed" | "approved" | "rejected";
|
||||||
@@ -97,7 +97,7 @@ export function Recommendations({ userId }: RecommendationsProps) {
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<p className="text-sm font-medium">{rec.content}</p>
|
<p className="text-gray-700">{rec.recommendationText}</p>
|
||||||
{rec.type === 'ai_plan' && (
|
{rec.type === 'ai_plan' && (
|
||||||
<div className="mt-2 text-xs text-gray-600 space-y-1">
|
<div className="mt-2 text-xs text-gray-600 space-y-1">
|
||||||
{rec.activityPlan && <p><span className="font-semibold">Activity:</span> {rec.activityPlan}</p>}
|
{rec.activityPlan && <p><span className="font-semibold">Activity:</span> {rec.activityPlan}</p>}
|
||||||
|
|||||||
@@ -9,6 +9,19 @@ import { formatDate } from "@/lib/utils";
|
|||||||
|
|
||||||
ModuleRegistry.registerModules([AllCommunityModule]);
|
ModuleRegistry.registerModules([AllCommunityModule]);
|
||||||
|
|
||||||
|
function getTimeAgo(date: Date): string {
|
||||||
|
const now = new Date();
|
||||||
|
const diffMs = now.getTime() - date.getTime();
|
||||||
|
const diffMins = Math.floor(diffMs / 60000);
|
||||||
|
const diffHours = Math.floor(diffMins / 60);
|
||||||
|
const diffDays = Math.floor(diffHours / 24);
|
||||||
|
|
||||||
|
if (diffMins < 1) return "just now";
|
||||||
|
if (diffMins < 60) return `${diffMins}m ago`;
|
||||||
|
if (diffHours < 24) return `${diffHours}h ago`;
|
||||||
|
return `${diffDays}d ago`;
|
||||||
|
}
|
||||||
|
|
||||||
interface User {
|
interface User {
|
||||||
id: string;
|
id: string;
|
||||||
email: string;
|
email: string;
|
||||||
@@ -16,7 +29,11 @@ interface User {
|
|||||||
lastName: string;
|
lastName: string;
|
||||||
role: string;
|
role: string;
|
||||||
phone?: string;
|
phone?: string;
|
||||||
|
gymId?: string;
|
||||||
|
gymName?: string | null;
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
|
isCheckedIn?: boolean;
|
||||||
|
checkInTime?: Date;
|
||||||
client?: {
|
client?: {
|
||||||
id: string;
|
id: string;
|
||||||
membershipType: string;
|
membershipType: string;
|
||||||
@@ -45,6 +62,31 @@ export function UserGrid({
|
|||||||
}: UserGridProps) {
|
}: UserGridProps) {
|
||||||
const [selectedUsers, setSelectedUsers] = useState<User[]>([]);
|
const [selectedUsers, setSelectedUsers] = useState<User[]>([]);
|
||||||
const [searchQuery, setSearchQuery] = useState<string>("");
|
const [searchQuery, setSearchQuery] = useState<string>("");
|
||||||
|
const [gymNames, setGymNames] = useState<Record<string, string>>({});
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
let isMounted = true;
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
const res = await fetch("/api/gyms");
|
||||||
|
const data = await res.json();
|
||||||
|
if (isMounted && Array.isArray(data)) {
|
||||||
|
const map: Record<string, string> = {};
|
||||||
|
for (const g of data) {
|
||||||
|
if (g && g.id) {
|
||||||
|
map[g.id] = g.name || g.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setGymNames(map);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// silently fail; we'll show gymId if name not available
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
return () => {
|
||||||
|
isMounted = false;
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
const columnDefs: ColDef<User>[] = useMemo(
|
const columnDefs: ColDef<User>[] = useMemo(
|
||||||
() => [
|
() => [
|
||||||
@@ -79,16 +121,36 @@ export function UserGrid({
|
|||||||
roleColors[params.value as keyof typeof roleColors] ||
|
roleColors[params.value as keyof typeof roleColors] ||
|
||||||
"bg-gray-100 text-gray-800";
|
"bg-gray-100 text-gray-800";
|
||||||
|
|
||||||
const label = params.value === 'superAdmin' ? 'Super Admin' : params.value.charAt(0).toUpperCase() + params.value.slice(1);
|
const label =
|
||||||
|
params.value === "superAdmin"
|
||||||
|
? "Super Admin"
|
||||||
|
: params.value.charAt(0).toUpperCase() + params.value.slice(1);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className={`px-2 py-1 rounded-full text-xs font-medium ${colorClass}`}>
|
<span
|
||||||
|
className={`px-2 py-1 rounded-full text-xs font-medium ${colorClass}`}
|
||||||
|
>
|
||||||
{label}
|
{label}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
headerName: "Gym",
|
||||||
|
field: "gymId",
|
||||||
|
filter: "agTextColumnFilter",
|
||||||
|
sortable: true,
|
||||||
|
minWidth: 160,
|
||||||
|
valueFormatter: (params: any) => {
|
||||||
|
const gymId = params.value;
|
||||||
|
const gymName = params.data?.gymName;
|
||||||
|
if (!gymId && !gymName) return "None";
|
||||||
|
if (gymName) return gymName;
|
||||||
|
return gymNames[gymId] || gymId;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
headerName: "Phone",
|
headerName: "Phone",
|
||||||
field: "phone",
|
field: "phone",
|
||||||
@@ -103,7 +165,8 @@ export function UserGrid({
|
|||||||
filter: "agTextColumnFilter",
|
filter: "agTextColumnFilter",
|
||||||
sortable: true,
|
sortable: true,
|
||||||
cellRenderer: (params: any) => {
|
cellRenderer: (params: any) => {
|
||||||
if (!params.value || params.value === "N/A") return <span className="text-gray-400">N/A</span>;
|
if (!params.value || params.value === "N/A")
|
||||||
|
return <span className="text-gray-400">N/A</span>;
|
||||||
|
|
||||||
const membershipColors = {
|
const membershipColors = {
|
||||||
vip: "bg-yellow-100 text-yellow-800 border-yellow-200",
|
vip: "bg-yellow-100 text-yellow-800 border-yellow-200",
|
||||||
@@ -114,10 +177,13 @@ export function UserGrid({
|
|||||||
membershipColors[params.value as keyof typeof membershipColors] ||
|
membershipColors[params.value as keyof typeof membershipColors] ||
|
||||||
"bg-gray-100 text-gray-800";
|
"bg-gray-100 text-gray-800";
|
||||||
|
|
||||||
const label = params.value.charAt(0).toUpperCase() + params.value.slice(1);
|
const label =
|
||||||
|
params.value.charAt(0).toUpperCase() + params.value.slice(1);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className={`px-2 py-1 rounded-full text-xs font-medium border ${colorClass}`}>
|
<span
|
||||||
|
className={`px-2 py-1 rounded-full text-xs font-medium border ${colorClass}`}
|
||||||
|
>
|
||||||
{label}
|
{label}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
@@ -130,7 +196,8 @@ export function UserGrid({
|
|||||||
filter: "agTextColumnFilter",
|
filter: "agTextColumnFilter",
|
||||||
sortable: true,
|
sortable: true,
|
||||||
cellRenderer: (params: any) => {
|
cellRenderer: (params: any) => {
|
||||||
if (!params.value || params.value === "N/A") return <span className="text-gray-400">N/A</span>;
|
if (!params.value || params.value === "N/A")
|
||||||
|
return <span className="text-gray-400">N/A</span>;
|
||||||
|
|
||||||
const statusColors = {
|
const statusColors = {
|
||||||
active: "bg-green-100 text-green-800",
|
active: "bg-green-100 text-green-800",
|
||||||
@@ -142,16 +209,42 @@ export function UserGrid({
|
|||||||
statusColors[params.value as keyof typeof statusColors] ||
|
statusColors[params.value as keyof typeof statusColors] ||
|
||||||
"bg-gray-100 text-gray-800";
|
"bg-gray-100 text-gray-800";
|
||||||
|
|
||||||
const label = params.value.charAt(0).toUpperCase() + params.value.slice(1);
|
const label =
|
||||||
|
params.value.charAt(0).toUpperCase() + params.value.slice(1);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className={`px-2 py-1 rounded-full text-xs font-medium ${colorClass}`}>
|
<span
|
||||||
|
className={`px-2 py-1 rounded-full text-xs font-medium ${colorClass}`}
|
||||||
|
>
|
||||||
{label}
|
{label}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
headerName: "Currently Checked In",
|
||||||
|
valueGetter: (params) => params.data?.isCheckedIn,
|
||||||
|
filter: "agTextColumnFilter",
|
||||||
|
sortable: true,
|
||||||
|
cellRenderer: (params: any) => {
|
||||||
|
if (!params.data?.isCheckedIn) {
|
||||||
|
return <span className="text-gray-400">—</span>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkInTime = params.data.checkInTime
|
||||||
|
? new Date(params.data.checkInTime)
|
||||||
|
: null;
|
||||||
|
const timeAgo = checkInTime ? getTimeAgo(checkInTime) : "";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span className="px-2 py-1 rounded-full text-xs font-medium bg-green-100 text-green-800 border border-green-200">
|
||||||
|
✓ Checked In {timeAgo && `(${timeAgo})`}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
minWidth: 180,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
headerName: "Join Date",
|
headerName: "Join Date",
|
||||||
valueGetter: (params) =>
|
valueGetter: (params) =>
|
||||||
@@ -187,14 +280,16 @@ export function UserGrid({
|
|||||||
const gridRef = React.useRef<AgGridReact<User>>(null);
|
const gridRef = React.useRef<AgGridReact<User>>(null);
|
||||||
|
|
||||||
const gridOptions = {
|
const gridOptions = {
|
||||||
theme: "legacy",
|
theme: "legacy" as const,
|
||||||
columnDefs,
|
columnDefs,
|
||||||
defaultColDef,
|
defaultColDef,
|
||||||
rowData: users,
|
rowData: users,
|
||||||
rowSelection: "multiple",
|
rowSelection: "multiple" as const,
|
||||||
onSelectionChanged: () => {
|
onSelectionChanged: () => {
|
||||||
const selectedNodes = gridRef.current?.api.getSelectedNodes();
|
const selectedNodes = gridRef.current?.api.getSelectedNodes();
|
||||||
const selectedData = selectedNodes?.map((node) => node.data) || [];
|
const selectedData =
|
||||||
|
selectedNodes?.map((node) => node.data).filter((u): u is User => !!u) ||
|
||||||
|
[];
|
||||||
setSelectedUsers(selectedData);
|
setSelectedUsers(selectedData);
|
||||||
if (selectedData.length === 1 && onUserSelect) {
|
if (selectedData.length === 1 && onUserSelect) {
|
||||||
onUserSelect(selectedData[0]);
|
onUserSelect(selectedData[0]);
|
||||||
|
|||||||
@@ -2,8 +2,10 @@
|
|||||||
|
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { UserGrid } from "@/components/users/UserGrid";
|
import { UserGrid } from "@/components/users/UserGrid";
|
||||||
import { Button } from "@/components/ui/Button";
|
// import { Button } from "@/components/ui/button";
|
||||||
import { Card, CardHeader, CardContent } from "@/components/ui/card";
|
import { Card, CardHeader, CardContent } from "@/components/ui/card";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { useUser } from "@clerk/nextjs";
|
||||||
|
|
||||||
interface User {
|
interface User {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -12,7 +14,13 @@ interface User {
|
|||||||
lastName: string;
|
lastName: string;
|
||||||
role: string;
|
role: string;
|
||||||
phone?: string;
|
phone?: string;
|
||||||
|
gymId?: string;
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
|
isCheckedIn?: boolean;
|
||||||
|
checkInTime?: Date;
|
||||||
|
lastCheckInTime?: Date;
|
||||||
|
checkInsThisWeek?: number;
|
||||||
|
checkInsThisMonth?: number;
|
||||||
client?: {
|
client?: {
|
||||||
id: string;
|
id: string;
|
||||||
membershipType: string;
|
membershipType: string;
|
||||||
@@ -23,6 +31,7 @@ interface User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function UserManagement() {
|
export function UserManagement() {
|
||||||
|
const { user } = useUser();
|
||||||
const [users, setUsers] = useState<User[]>([]);
|
const [users, setUsers] = useState<User[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [filter, setFilter] = useState<string>("all");
|
const [filter, setFilter] = useState<string>("all");
|
||||||
@@ -35,8 +44,32 @@ export function UserManagement() {
|
|||||||
email: string;
|
email: string;
|
||||||
role: string;
|
role: string;
|
||||||
phone: string;
|
phone: string;
|
||||||
|
gymId: string;
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
|
|
||||||
|
// Active gyms for dropdown
|
||||||
|
const [gyms, setGyms] = useState<Array<{ id: string; name: string }>>([]);
|
||||||
|
|
||||||
|
// Load gyms when modal opens or refreshes
|
||||||
|
useEffect(() => {
|
||||||
|
if (isEditing) {
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
const res = await fetch("/api/gyms");
|
||||||
|
const data = await res.json();
|
||||||
|
if (Array.isArray(data)) {
|
||||||
|
// map down to id and name to avoid extra payload use here
|
||||||
|
setGyms(data.map((g: any) => ({ id: g.id, name: g.name })));
|
||||||
|
} else {
|
||||||
|
setGyms([]);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
setGyms([]);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}, [isEditing]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchUsers();
|
fetchUsers();
|
||||||
}, [filter]);
|
}, [filter]);
|
||||||
@@ -44,10 +77,33 @@ export function UserManagement() {
|
|||||||
const fetchUsers = async () => {
|
const fetchUsers = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const url = filter === "all" ? "/api/users" : `/api/users?role=${filter}`;
|
const ts = Date.now();
|
||||||
|
const url =
|
||||||
|
filter === "all"
|
||||||
|
? `/api/users?ts=${ts}`
|
||||||
|
: `/api/users?role=${filter}&ts=${ts}`;
|
||||||
|
|
||||||
const response = await fetch(url);
|
console.log("UserManagement.fetchUsers: fetching URL", url);
|
||||||
|
const response = await fetch(url, { cache: "no-store" });
|
||||||
|
console.log(
|
||||||
|
"UserManagement.fetchUsers: response.ok",
|
||||||
|
response.ok,
|
||||||
|
"status",
|
||||||
|
response.status,
|
||||||
|
);
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
console.log(
|
||||||
|
"UserManagement.fetchUsers: received users count",
|
||||||
|
Array.isArray(data.users) ? data.users.length : 0,
|
||||||
|
"sample",
|
||||||
|
data.users && data.users[0]
|
||||||
|
? {
|
||||||
|
id: data.users[0].id,
|
||||||
|
gymId: data.users[0].gymId,
|
||||||
|
role: data.users[0].role,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
);
|
||||||
setUsers(data.users || []);
|
setUsers(data.users || []);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to fetch users:", error);
|
console.error("Failed to fetch users:", error);
|
||||||
@@ -68,6 +124,7 @@ export function UserManagement() {
|
|||||||
email: user.email,
|
email: user.email,
|
||||||
role: user.role,
|
role: user.role,
|
||||||
phone: user.phone || "",
|
phone: user.phone || "",
|
||||||
|
gymId: user.gymId || "",
|
||||||
});
|
});
|
||||||
setIsEditing(true);
|
setIsEditing(true);
|
||||||
};
|
};
|
||||||
@@ -144,24 +201,92 @@ export function UserManagement() {
|
|||||||
try {
|
try {
|
||||||
if (selectedUser) {
|
if (selectedUser) {
|
||||||
// Update existing user
|
// Update existing user
|
||||||
|
console.log(
|
||||||
|
"UserManagement.handleSaveEdit: sending PUT /api/users payload",
|
||||||
|
{
|
||||||
|
id: selectedUser.id,
|
||||||
|
email: editForm.email,
|
||||||
|
firstName: editForm.firstName,
|
||||||
|
lastName: editForm.lastName,
|
||||||
|
role: editForm.role,
|
||||||
|
phone: editForm.phone,
|
||||||
|
gymId: editForm.gymId === "" ? null : editForm.gymId,
|
||||||
|
},
|
||||||
|
);
|
||||||
const response = await fetch("/api/users", {
|
const response = await fetch("/api/users", {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({ id: selectedUser.id, ...editForm }),
|
body: JSON.stringify({
|
||||||
|
id: selectedUser.id,
|
||||||
|
email: editForm.email,
|
||||||
|
firstName: editForm.firstName,
|
||||||
|
lastName: editForm.lastName,
|
||||||
|
role: editForm.role,
|
||||||
|
phone: editForm.phone,
|
||||||
|
gymId: editForm.gymId === "" ? null : editForm.gymId,
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
console.log(
|
||||||
|
"UserManagement.handleSaveEdit: PUT /api/users response.ok",
|
||||||
|
response.ok,
|
||||||
|
"status",
|
||||||
|
response.status,
|
||||||
|
);
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
|
// Optimistically update local state so grid reflects changes immediately
|
||||||
|
setUsers((prev) =>
|
||||||
|
prev.map((u) =>
|
||||||
|
u.id === selectedUser.id
|
||||||
|
? {
|
||||||
|
...u,
|
||||||
|
email: editForm.email,
|
||||||
|
firstName: editForm.firstName,
|
||||||
|
lastName: editForm.lastName,
|
||||||
|
role: editForm.role,
|
||||||
|
phone: editForm.phone || undefined,
|
||||||
|
gymId: editForm.gymId === "" ? undefined : editForm.gymId,
|
||||||
|
}
|
||||||
|
: u,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
setSelectedUser((prev) =>
|
||||||
|
prev
|
||||||
|
? {
|
||||||
|
...prev,
|
||||||
|
email: editForm.email,
|
||||||
|
firstName: editForm.firstName,
|
||||||
|
lastName: editForm.lastName,
|
||||||
|
role: editForm.role,
|
||||||
|
phone: editForm.phone || undefined,
|
||||||
|
gymId: editForm.gymId === "" ? undefined : editForm.gymId,
|
||||||
|
}
|
||||||
|
: prev,
|
||||||
|
);
|
||||||
setIsEditing(false);
|
setIsEditing(false);
|
||||||
setEditForm(null);
|
setEditForm(null);
|
||||||
|
// Still re-fetch from server to ensure consistency
|
||||||
|
console.log(
|
||||||
|
"UserManagement.handleSaveEdit: re-fetching users after successful edit",
|
||||||
|
);
|
||||||
fetchUsers();
|
fetchUsers();
|
||||||
} else {
|
} else {
|
||||||
|
const errText = await response.text().catch(() => "");
|
||||||
|
console.error("UserManagement.handleSaveEdit: update failed", {
|
||||||
|
status: response.status,
|
||||||
|
body: errText,
|
||||||
|
});
|
||||||
alert("Error updating user");
|
alert("Error updating user");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Create (Invite) new user
|
// Create (Invite) new user
|
||||||
const response = await fetch("/api/users", {
|
const response = await fetch("/api/invitations", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify(editForm),
|
body: JSON.stringify({
|
||||||
|
inviteeEmail: editForm.email,
|
||||||
|
roleAssigned: editForm.role,
|
||||||
|
gymId: editForm.gymId || undefined,
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
@@ -205,20 +330,20 @@ export function UserManagement() {
|
|||||||
<h2 className="text-2xl font-bold">User Management</h2>
|
<h2 className="text-2xl font-bold">User Management</h2>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<Button
|
<Button
|
||||||
variant={filter === "all" ? "primary" : "secondary"}
|
variant={filter === "all" ? "default" : "outline"}
|
||||||
onClick={() => setFilter("all")}
|
onClick={() => setFilter("all")}
|
||||||
>
|
>
|
||||||
All Users
|
All Users
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant={filter === "client" ? "default" : "outline"}
|
||||||
onClick={() => selectedUser && handleEditUser(selectedUser)}
|
onClick={() => selectedUser && handleEditUser(selectedUser)}
|
||||||
disabled={!selectedUser}
|
disabled={!selectedUser}
|
||||||
>
|
>
|
||||||
Edit User
|
Edit User
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant={filter === "client" ? "default" : "outline"}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setEditForm({
|
setEditForm({
|
||||||
firstName: "",
|
firstName: "",
|
||||||
@@ -226,6 +351,7 @@ export function UserManagement() {
|
|||||||
email: "",
|
email: "",
|
||||||
role: "client",
|
role: "client",
|
||||||
phone: "",
|
phone: "",
|
||||||
|
gymId: String((user?.publicMetadata as any)?.gymId ?? ""),
|
||||||
});
|
});
|
||||||
setSelectedUser(null);
|
setSelectedUser(null);
|
||||||
setIsEditing(true);
|
setIsEditing(true);
|
||||||
@@ -234,32 +360,32 @@ export function UserManagement() {
|
|||||||
Invite User
|
Invite User
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant={filter === "client" ? "default" : "outline"}
|
||||||
onClick={() => selectedUser && handleDeleteUser(selectedUser)}
|
onClick={() => selectedUser && handleDeleteUser(selectedUser)}
|
||||||
disabled={!selectedUser}
|
disabled={!selectedUser}
|
||||||
>
|
>
|
||||||
Delete User
|
Delete User
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant={filter === "client" ? "primary" : "secondary"}
|
variant={filter === "client" ? "default" : "outline"}
|
||||||
onClick={() => setFilter("client")}
|
onClick={() => setFilter("client")}
|
||||||
>
|
>
|
||||||
Clients
|
Clientsa
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant={filter === "trainer" ? "primary" : "secondary"}
|
variant={filter === "trainer" ? "default" : "outline"}
|
||||||
onClick={() => setFilter("trainer")}
|
onClick={() => setFilter("trainer")}
|
||||||
>
|
>
|
||||||
Trainers
|
Trainers
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant={filter === "admin" ? "primary" : "secondary"}
|
variant={filter === "admin" ? "default" : "outline"}
|
||||||
onClick={() => setFilter("admin")}
|
onClick={() => setFilter("admin")}
|
||||||
>
|
>
|
||||||
Admins
|
Admins
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant={filter === "superAdmin" ? "primary" : "secondary"}
|
variant={filter === "superAdmin" ? "default" : "outline"}
|
||||||
onClick={() => setFilter("superAdmin")}
|
onClick={() => setFilter("superAdmin")}
|
||||||
>
|
>
|
||||||
Super Admins
|
Super Admins
|
||||||
@@ -277,10 +403,10 @@ export function UserManagement() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<Button variant="secondary" onClick={handleRefresh}>
|
<Button variant="default" onClick={handleRefresh}>
|
||||||
Refresh
|
Refresh
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="secondary" onClick={handleExport}>
|
<Button variant="default" onClick={handleExport}>
|
||||||
Export CSV
|
Export CSV
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
@@ -302,7 +428,9 @@ export function UserManagement() {
|
|||||||
{isEditing && editForm && (
|
{isEditing && editForm && (
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
||||||
<div className="bg-white p-6 rounded-lg shadow-lg max-w-md w-full">
|
<div className="bg-white p-6 rounded-lg shadow-lg max-w-md w-full">
|
||||||
<h3 className="text-lg font-semibold mb-4">{selectedUser ? 'Edit User' : 'Invite New User'}</h3>
|
<h3 className="text-lg font-semibold mb-4">
|
||||||
|
{selectedUser ? "Edit User" : "Invite New User"}
|
||||||
|
</h3>
|
||||||
<form
|
<form
|
||||||
onSubmit={(e) => {
|
onSubmit={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -383,6 +511,26 @@ export function UserManagement() {
|
|||||||
className="w-full border border-gray-300 rounded px-3 py-2"
|
className="w-full border border-gray-300 rounded px-3 py-2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="mb-4">
|
||||||
|
<label className="block text-sm font-medium mb-1">Gym</label>
|
||||||
|
<select
|
||||||
|
value={editForm.gymId}
|
||||||
|
onChange={(e) =>
|
||||||
|
setEditForm({ ...editForm, gymId: e.target.value })
|
||||||
|
}
|
||||||
|
className="w-full border border-gray-300 rounded px-3 py-2"
|
||||||
|
>
|
||||||
|
<option value="">Proceed without gym</option>
|
||||||
|
{gyms.map((g) => (
|
||||||
|
<option key={g.id} value={g.id}>
|
||||||
|
{g.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
<p className="text-xs text-gray-500 mt-1">
|
||||||
|
Select an active gym or proceed without a gym.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
<div className="flex justify-end gap-2">
|
<div className="flex justify-end gap-2">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -398,7 +546,7 @@ export function UserManagement() {
|
|||||||
type="submit"
|
type="submit"
|
||||||
className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"
|
className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"
|
||||||
>
|
>
|
||||||
{selectedUser ? 'Save Changes' : 'Send Invitation'}
|
{selectedUser ? "Save Changes" : "Send Invitation"}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@@ -444,7 +592,7 @@ export function UserManagement() {
|
|||||||
</a>
|
</a>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-3 gap-4">
|
||||||
<div>
|
<div>
|
||||||
<h4 className="font-medium mb-2">Basic Information</h4>
|
<h4 className="font-medium mb-2">Basic Information</h4>
|
||||||
<div className="space-y-1 text-sm">
|
<div className="space-y-1 text-sm">
|
||||||
@@ -493,13 +641,33 @@ export function UserManagement() {
|
|||||||
<span className="font-medium">Last Visit:</span>{" "}
|
<span className="font-medium">Last Visit:</span>{" "}
|
||||||
{selectedUser.client.lastVisit
|
{selectedUser.client.lastVisit
|
||||||
? new Date(
|
? new Date(
|
||||||
selectedUser.client.lastVisit,
|
selectedUser.client.lastVisit,
|
||||||
).toLocaleDateString()
|
).toLocaleDateString()
|
||||||
: "Never"}
|
: "Never"}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h4 className="font-medium mb-2">Check-In Statistics</h4>
|
||||||
|
<div className="space-y-1 text-sm">
|
||||||
|
<p>
|
||||||
|
<span className="font-medium">Last Check-In:</span>{" "}
|
||||||
|
{selectedUser.lastCheckInTime
|
||||||
|
? new Date(selectedUser.lastCheckInTime).toLocaleString()
|
||||||
|
: "Never"}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<span className="font-medium">This Week:</span>{" "}
|
||||||
|
{selectedUser.checkInsThisWeek || 0} check-ins
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<span className="font-medium">This Month:</span>{" "}
|
||||||
|
{selectedUser.checkInsThisMonth || 0} check-ins
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -1,17 +1,11 @@
|
|||||||
import { getDatabase } from '@/lib/database';
|
import { getDatabase } from '@/lib/database';
|
||||||
import type { FitnessGoal } from '@/lib/database/types';
|
import type { FitnessGoal, FitnessProfile, Recommendation } from '@/lib/database/types';
|
||||||
|
|
||||||
// Import types from database package
|
|
||||||
import type {
|
|
||||||
FitnessProfile as DBFitnessProfile,
|
|
||||||
Recommendation as DBRecommendation,
|
|
||||||
} from '@fitai/database';
|
|
||||||
|
|
||||||
export interface AIContext {
|
export interface AIContext {
|
||||||
profile: DBFitnessProfile;
|
profile: FitnessProfile;
|
||||||
activeGoals: FitnessGoal[];
|
activeGoals: FitnessGoal[];
|
||||||
completedGoals: FitnessGoal[];
|
completedGoals: FitnessGoal[];
|
||||||
recentRecommendations: DBRecommendation[];
|
recentRecommendations: Recommendation[];
|
||||||
progressSummary: {
|
progressSummary: {
|
||||||
goalsCompleted: number;
|
goalsCompleted: number;
|
||||||
goalsActive: number;
|
goalsActive: number;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export function buildEnhancedPrompt(context: AIContext): string {
|
|||||||
- Weight: ${profile.weight || 'Not specified'} kg
|
- Weight: ${profile.weight || 'Not specified'} kg
|
||||||
- Age: ${profile.age || 'Not specified'}
|
- Age: ${profile.age || 'Not specified'}
|
||||||
- Gender: ${profile.gender || 'Not specified'}
|
- Gender: ${profile.gender || 'Not specified'}
|
||||||
- Primary Goal: ${profile.fitnessGoal || 'General fitness'}
|
- Primary Goal: ${profile.fitnessGoals?.[0] || 'General fitness'}
|
||||||
- Activity Level: ${profile.activityLevel || 'Not specified'}
|
- Activity Level: ${profile.activityLevel || 'Not specified'}
|
||||||
- Medical Conditions: ${profile.medicalConditions || 'None'}
|
- Medical Conditions: ${profile.medicalConditions || 'None'}
|
||||||
- Allergies: ${profile.allergies || 'None'}
|
- Allergies: ${profile.allergies || 'None'}
|
||||||
@@ -77,7 +77,7 @@ Generate a detailed daily recommendation for a user with the following profile:
|
|||||||
- Weight: ${profile.weight} kg
|
- Weight: ${profile.weight} kg
|
||||||
- Age: ${profile.age}
|
- Age: ${profile.age}
|
||||||
- Gender: ${profile.gender}
|
- Gender: ${profile.gender}
|
||||||
- Goal: ${profile.fitnessGoal}
|
- Goal: ${profile.fitnessGoals?.[0]}
|
||||||
- Activity Level: ${profile.activityLevel}
|
- Activity Level: ${profile.activityLevel}
|
||||||
- Medical Conditions: ${profile.medicalConditions || "None"}
|
- Medical Conditions: ${profile.medicalConditions || "None"}
|
||||||
- Injuries: ${profile.injuries || "None"}
|
- Injuries: ${profile.injuries || "None"}
|
||||||
|
|||||||
@@ -0,0 +1,181 @@
|
|||||||
|
/**
|
||||||
|
* @jest-environment node
|
||||||
|
*/
|
||||||
|
import { DrizzleDatabase } from '../drizzle'
|
||||||
|
import { DatabaseConfig } from '../types'
|
||||||
|
import Database from 'better-sqlite3'
|
||||||
|
import { drizzle } from 'drizzle-orm/better-sqlite3'
|
||||||
|
import * as schema from '@fitai/database'
|
||||||
|
|
||||||
|
describe('DrizzleDatabase', () => {
|
||||||
|
let db: DrizzleDatabase
|
||||||
|
let sqlite: Database.Database
|
||||||
|
let drizzleDb: ReturnType<typeof drizzle>
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
// Create in-memory SQLite database
|
||||||
|
sqlite = new Database(':memory:')
|
||||||
|
drizzleDb = drizzle(sqlite, { schema })
|
||||||
|
|
||||||
|
const config: DatabaseConfig = {
|
||||||
|
type: 'sqlite',
|
||||||
|
connection: { filename: ':memory:' },
|
||||||
|
options: { logging: false }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize DrizzleDatabase with the in-memory db
|
||||||
|
db = new DrizzleDatabase(config, drizzleDb as any)
|
||||||
|
await db.connect()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await db.disconnect()
|
||||||
|
sqlite.close()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('User Operations', () => {
|
||||||
|
it('should create and retrieve a user', async () => {
|
||||||
|
const newUser = {
|
||||||
|
email: 'test@example.com',
|
||||||
|
firstName: 'Test',
|
||||||
|
lastName: 'User',
|
||||||
|
password: 'password123',
|
||||||
|
role: 'client' as const
|
||||||
|
}
|
||||||
|
|
||||||
|
const createdUser = await db.createUser(newUser)
|
||||||
|
expect(createdUser).toBeDefined()
|
||||||
|
expect(createdUser.id).toBeDefined()
|
||||||
|
expect(createdUser.email).toBe(newUser.email)
|
||||||
|
|
||||||
|
const fetchedUser = await db.getUserById(createdUser.id)
|
||||||
|
expect(fetchedUser).toBeDefined()
|
||||||
|
expect(fetchedUser?.id).toBe(createdUser.id)
|
||||||
|
expect(fetchedUser?.email).toBe(createdUser.email)
|
||||||
|
// SQLite/Drizzle might truncate ms or handle dates differently in test env
|
||||||
|
expect(new Date(fetchedUser!.createdAt).getTime()).toBeLessThanOrEqual(createdUser.createdAt.getTime())
|
||||||
|
expect(new Date(fetchedUser!.updatedAt).getTime()).toBeLessThanOrEqual(createdUser.updatedAt.getTime())
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should update a user', async () => {
|
||||||
|
const user = await db.createUser({
|
||||||
|
email: 'update@example.com',
|
||||||
|
firstName: 'Update',
|
||||||
|
lastName: 'Me',
|
||||||
|
password: 'password',
|
||||||
|
role: 'client'
|
||||||
|
})
|
||||||
|
|
||||||
|
const updated = await db.updateUser(user.id, { firstName: 'Updated' })
|
||||||
|
expect(updated?.firstName).toBe('Updated')
|
||||||
|
|
||||||
|
const fetched = await db.getUserById(user.id)
|
||||||
|
expect(fetched?.firstName).toBe('Updated')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should delete a user', async () => {
|
||||||
|
const user = await db.createUser({
|
||||||
|
email: 'delete@example.com',
|
||||||
|
firstName: 'Delete',
|
||||||
|
lastName: 'Me',
|
||||||
|
password: 'password',
|
||||||
|
role: 'client'
|
||||||
|
})
|
||||||
|
|
||||||
|
const deleted = await db.deleteUser(user.id)
|
||||||
|
expect(deleted).toBe(true)
|
||||||
|
|
||||||
|
const fetched = await db.getUserById(user.id)
|
||||||
|
expect(fetched).toBeNull()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Client Operations', () => {
|
||||||
|
it('should create and retrieve a client', async () => {
|
||||||
|
const user = await db.createUser({
|
||||||
|
email: 'client@example.com',
|
||||||
|
firstName: 'Client',
|
||||||
|
lastName: 'User',
|
||||||
|
password: 'password',
|
||||||
|
role: 'client'
|
||||||
|
})
|
||||||
|
|
||||||
|
const newClient = {
|
||||||
|
userId: user.id,
|
||||||
|
membershipType: 'basic' as const,
|
||||||
|
membershipStatus: 'active' as const,
|
||||||
|
joinDate: new Date()
|
||||||
|
}
|
||||||
|
|
||||||
|
const createdClient = await db.createClient(newClient)
|
||||||
|
expect(createdClient).toBeDefined()
|
||||||
|
expect(createdClient.userId).toBe(user.id)
|
||||||
|
|
||||||
|
const fetchedClient = await db.getClientById(createdClient.id)
|
||||||
|
expect(fetchedClient).toBeDefined()
|
||||||
|
expect(fetchedClient?.id).toBe(createdClient.id)
|
||||||
|
expect(fetchedClient?.userId).toBe(createdClient.userId)
|
||||||
|
expect(fetchedClient?.membershipType).toBe(createdClient.membershipType)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Fitness Profile Operations', () => {
|
||||||
|
it('should create and retrieve a fitness profile', async () => {
|
||||||
|
const user = await db.createUser({
|
||||||
|
email: 'profile@example.com',
|
||||||
|
firstName: 'Profile',
|
||||||
|
lastName: 'User',
|
||||||
|
password: 'password',
|
||||||
|
role: 'client'
|
||||||
|
})
|
||||||
|
|
||||||
|
const newProfile = {
|
||||||
|
userId: user.id,
|
||||||
|
height: 180,
|
||||||
|
weight: 75,
|
||||||
|
age: 30,
|
||||||
|
gender: 'male' as const,
|
||||||
|
activityLevel: 'moderately_active' as const,
|
||||||
|
fitnessGoals: ['weight_loss'],
|
||||||
|
exerciseHabits: 'None',
|
||||||
|
dietHabits: 'None',
|
||||||
|
medicalConditions: 'None'
|
||||||
|
}
|
||||||
|
|
||||||
|
const createdProfile = await db.createFitnessProfile(newProfile as any)
|
||||||
|
expect(createdProfile).toBeDefined()
|
||||||
|
expect(createdProfile.userId).toBe(user.id)
|
||||||
|
|
||||||
|
const fetchedProfile = await db.getFitnessProfileByUserId(user.id)
|
||||||
|
expect(fetchedProfile).toBeDefined()
|
||||||
|
expect(fetchedProfile?.userId).toBe(user.id)
|
||||||
|
expect(fetchedProfile?.fitnessGoals).toEqual(expect.arrayContaining(['weight_loss']))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Attendance Operations', () => {
|
||||||
|
it('should check in and check out', async () => {
|
||||||
|
const user = await db.createUser({
|
||||||
|
email: 'attendance@example.com',
|
||||||
|
firstName: 'Attendance',
|
||||||
|
lastName: 'User',
|
||||||
|
password: 'password',
|
||||||
|
role: 'client'
|
||||||
|
})
|
||||||
|
|
||||||
|
const checkIn = await db.checkIn(user.id, 'gym')
|
||||||
|
expect(checkIn).toBeDefined()
|
||||||
|
expect(checkIn.checkOutTime).toBeUndefined()
|
||||||
|
|
||||||
|
const activeCheckIn = await db.getActiveCheckIn(user.id)
|
||||||
|
expect(activeCheckIn).toBeDefined()
|
||||||
|
expect(activeCheckIn?.id).toBe(checkIn.id)
|
||||||
|
|
||||||
|
const checkOut = await db.checkOut(checkIn.id)
|
||||||
|
expect(checkOut?.checkOutTime).toBeDefined()
|
||||||
|
|
||||||
|
const activeCheckInAfter = await db.getActiveCheckIn(user.id)
|
||||||
|
expect(activeCheckInAfter).toBeNull()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,720 @@
|
|||||||
|
import {
|
||||||
|
IDatabase,
|
||||||
|
User,
|
||||||
|
Client,
|
||||||
|
FitnessProfile,
|
||||||
|
Attendance,
|
||||||
|
Recommendation,
|
||||||
|
FitnessGoal,
|
||||||
|
DatabaseConfig,
|
||||||
|
} from "./types";
|
||||||
|
import {
|
||||||
|
db as defaultDb,
|
||||||
|
users,
|
||||||
|
clients,
|
||||||
|
fitnessProfiles,
|
||||||
|
attendance,
|
||||||
|
recommendations,
|
||||||
|
fitnessGoals,
|
||||||
|
eq,
|
||||||
|
and,
|
||||||
|
desc,
|
||||||
|
sql,
|
||||||
|
} from "@fitai/database";
|
||||||
|
import { InferSelectModel } from "drizzle-orm";
|
||||||
|
|
||||||
|
export class DrizzleDatabase implements IDatabase {
|
||||||
|
private config: DatabaseConfig;
|
||||||
|
private db: typeof defaultDb;
|
||||||
|
|
||||||
|
constructor(config: DatabaseConfig, db?: typeof defaultDb) {
|
||||||
|
this.config = config;
|
||||||
|
this.db = db || defaultDb;
|
||||||
|
}
|
||||||
|
|
||||||
|
async connect(): Promise<void> {
|
||||||
|
// Drizzle with better-sqlite3 connects synchronously on initialization
|
||||||
|
// We can just log here if needed
|
||||||
|
if (this.config.options?.logging) {
|
||||||
|
console.log("Drizzle database connected");
|
||||||
|
}
|
||||||
|
await this.createTables();
|
||||||
|
}
|
||||||
|
|
||||||
|
async disconnect(): Promise<void> {
|
||||||
|
// better-sqlite3 handle is managed by Drizzle, usually no explicit disconnect needed for connection pooling
|
||||||
|
// but we can close the underlying sqlite instance if we had access to it.
|
||||||
|
// For now, we'll assume it's handled.
|
||||||
|
if (this.config.options?.logging) {
|
||||||
|
console.log("Drizzle database disconnected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async createTables(): Promise<void> {
|
||||||
|
// Users table
|
||||||
|
await this.db.run(sql`
|
||||||
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
email TEXT UNIQUE NOT NULL,
|
||||||
|
first_name TEXT NOT NULL,
|
||||||
|
last_name TEXT NOT NULL,
|
||||||
|
password TEXT,
|
||||||
|
phone TEXT,
|
||||||
|
role TEXT NOT NULL CHECK (role IN ('superAdmin', 'admin', 'trainer', 'client')),
|
||||||
|
gym_id TEXT,
|
||||||
|
created_at INTEGER NOT NULL,
|
||||||
|
updated_at INTEGER NOT NULL
|
||||||
|
)
|
||||||
|
`);
|
||||||
|
|
||||||
|
// Migration: ensure gym_id column exists on users (for existing DBs)
|
||||||
|
const userCols = await this.db.all(sql`PRAGMA table_info('users')`);
|
||||||
|
if (!userCols.some((c: any) => c.name === "gym_id")) {
|
||||||
|
await this.db.run(sql`ALTER TABLE users ADD COLUMN gym_id TEXT`);
|
||||||
|
}
|
||||||
|
// Clients table
|
||||||
|
await this.db.run(sql`
|
||||||
|
CREATE TABLE IF NOT EXISTS clients (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
user_id TEXT NOT NULL,
|
||||||
|
membership_type TEXT NOT NULL CHECK (membership_type IN ('basic', 'premium', 'vip')),
|
||||||
|
membership_status TEXT NOT NULL CHECK (membership_status IN ('active', 'inactive', 'suspended')),
|
||||||
|
join_date INTEGER NOT NULL,
|
||||||
|
last_visit INTEGER,
|
||||||
|
emergency_contact_name TEXT,
|
||||||
|
emergency_contact_phone TEXT,
|
||||||
|
emergency_contact_relationship TEXT,
|
||||||
|
created_at INTEGER NOT NULL,
|
||||||
|
updated_at INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
|
||||||
|
)
|
||||||
|
`);
|
||||||
|
|
||||||
|
// Fitness profiles table
|
||||||
|
await this.db.run(sql`
|
||||||
|
CREATE TABLE IF NOT EXISTS fitness_profiles (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
user_id TEXT NOT NULL UNIQUE,
|
||||||
|
height REAL,
|
||||||
|
weight REAL,
|
||||||
|
age INTEGER,
|
||||||
|
gender TEXT CHECK (gender IN ('male', 'female', 'other', 'prefer_not_to_say')),
|
||||||
|
activity_level TEXT CHECK (activity_level IN ('sedentary', 'lightly_active', 'moderately_active', 'very_active', 'extremely_active')),
|
||||||
|
fitness_goals TEXT,
|
||||||
|
exercise_habits TEXT,
|
||||||
|
diet_habits TEXT,
|
||||||
|
medical_conditions TEXT,
|
||||||
|
allergies TEXT,
|
||||||
|
injuries TEXT,
|
||||||
|
created_at INTEGER NOT NULL,
|
||||||
|
updated_at INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
|
||||||
|
)
|
||||||
|
`);
|
||||||
|
|
||||||
|
// Attendance table
|
||||||
|
await this.db.run(sql`
|
||||||
|
CREATE TABLE IF NOT EXISTS attendance (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
user_id TEXT NOT NULL,
|
||||||
|
check_in_time INTEGER NOT NULL,
|
||||||
|
check_out_time INTEGER,
|
||||||
|
type TEXT NOT NULL CHECK (type IN ('gym', 'class', 'personal_training')),
|
||||||
|
notes TEXT,
|
||||||
|
created_at INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
|
||||||
|
)
|
||||||
|
`);
|
||||||
|
|
||||||
|
// Recommendations table
|
||||||
|
await this.db.run(sql`
|
||||||
|
CREATE TABLE IF NOT EXISTS recommendations (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
user_id TEXT NOT NULL,
|
||||||
|
fitness_profile_id TEXT NOT NULL,
|
||||||
|
recommendation_text TEXT NOT NULL,
|
||||||
|
activity_plan TEXT NOT NULL,
|
||||||
|
diet_plan TEXT NOT NULL,
|
||||||
|
status TEXT NOT NULL CHECK (status IN ('pending', 'approved', 'rejected')) DEFAULT 'pending',
|
||||||
|
generated_at INTEGER NOT NULL,
|
||||||
|
approved_at INTEGER,
|
||||||
|
approved_by TEXT,
|
||||||
|
created_at INTEGER NOT NULL,
|
||||||
|
updated_at INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (fitness_profile_id) REFERENCES fitness_profiles (id) ON DELETE CASCADE
|
||||||
|
)
|
||||||
|
`);
|
||||||
|
|
||||||
|
// Fitness Goals table
|
||||||
|
await this.db.run(sql`
|
||||||
|
CREATE TABLE IF NOT EXISTS fitness_goals (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
user_id TEXT NOT NULL,
|
||||||
|
fitness_profile_id TEXT,
|
||||||
|
goal_type TEXT NOT NULL,
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
target_value REAL,
|
||||||
|
current_value REAL,
|
||||||
|
unit TEXT,
|
||||||
|
start_date INTEGER NOT NULL,
|
||||||
|
target_date INTEGER,
|
||||||
|
completed_date INTEGER,
|
||||||
|
status TEXT NOT NULL DEFAULT 'active',
|
||||||
|
progress REAL DEFAULT 0,
|
||||||
|
priority TEXT DEFAULT 'medium',
|
||||||
|
notes TEXT,
|
||||||
|
created_at INTEGER NOT NULL,
|
||||||
|
updated_at INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (fitness_profile_id) REFERENCES fitness_profiles (id) ON DELETE CASCADE
|
||||||
|
)
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// User operations
|
||||||
|
async createUser(
|
||||||
|
userData: Omit<User, "createdAt" | "updatedAt" | "id"> & { id?: string },
|
||||||
|
): Promise<User> {
|
||||||
|
const id = userData.id || Math.random().toString(36).substr(2, 9);
|
||||||
|
const now = new Date();
|
||||||
|
|
||||||
|
const newUser = {
|
||||||
|
...userData,
|
||||||
|
id,
|
||||||
|
createdAt: now,
|
||||||
|
updatedAt: now,
|
||||||
|
};
|
||||||
|
|
||||||
|
await this.db.insert(users).values(newUser);
|
||||||
|
return newUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getUserById(id: string): Promise<User | null> {
|
||||||
|
const result = await this.db
|
||||||
|
.select()
|
||||||
|
.from(users)
|
||||||
|
.where(eq(users.id, id))
|
||||||
|
.get();
|
||||||
|
return result ? this.mapUser(result) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getUserByEmail(email: string): Promise<User | null> {
|
||||||
|
const result = await this.db
|
||||||
|
.select()
|
||||||
|
.from(users)
|
||||||
|
.where(eq(users.email, email))
|
||||||
|
.get();
|
||||||
|
return result ? this.mapUser(result) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAllUsers(): Promise<User[]> {
|
||||||
|
const results = await this.db
|
||||||
|
.select()
|
||||||
|
.from(users)
|
||||||
|
.orderBy(desc(users.createdAt))
|
||||||
|
.all();
|
||||||
|
return results.map(this.mapUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateUser(id: string, updates: Partial<User>): Promise<User | null> {
|
||||||
|
const { id: _, ...updateData } = updates;
|
||||||
|
if (Object.keys(updateData).length === 0) return this.getUserById(id);
|
||||||
|
|
||||||
|
await this.db
|
||||||
|
.update(users)
|
||||||
|
.set({ ...updateData, updatedAt: new Date() })
|
||||||
|
.where(eq(users.id, id))
|
||||||
|
.run();
|
||||||
|
|
||||||
|
return this.getUserById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteUser(id: string): Promise<boolean> {
|
||||||
|
const result = await this.db.delete(users).where(eq(users.id, id)).run();
|
||||||
|
return result.changes > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
async migrateUserId(oldId: string, newId: string): Promise<void> {
|
||||||
|
await this.db
|
||||||
|
.update(users)
|
||||||
|
.set({ id: newId })
|
||||||
|
.where(eq(users.id, oldId))
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Client operations
|
||||||
|
async createClient(clientData: Omit<Client, "id">): Promise<Client> {
|
||||||
|
const id = Math.random().toString(36).substr(2, 9);
|
||||||
|
const newClient = {
|
||||||
|
id,
|
||||||
|
...clientData,
|
||||||
|
createdAt: new Date(),
|
||||||
|
updatedAt: new Date(),
|
||||||
|
};
|
||||||
|
|
||||||
|
await this.db.insert(clients).values(newClient as any);
|
||||||
|
return this.mapClient(newClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getClientById(id: string): Promise<Client | null> {
|
||||||
|
const result = await this.db
|
||||||
|
.select()
|
||||||
|
.from(clients)
|
||||||
|
.where(eq(clients.id, id))
|
||||||
|
.get();
|
||||||
|
return result ? this.mapClient(result) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getClientByUserId(userId: string): Promise<Client | null> {
|
||||||
|
const result = await this.db
|
||||||
|
.select()
|
||||||
|
.from(clients)
|
||||||
|
.where(eq(clients.userId, userId))
|
||||||
|
.get();
|
||||||
|
return result ? this.mapClient(result) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAllClients(): Promise<Client[]> {
|
||||||
|
const results = await this.db
|
||||||
|
.select()
|
||||||
|
.from(clients)
|
||||||
|
.orderBy(desc(clients.joinDate))
|
||||||
|
.all();
|
||||||
|
return results.map(this.mapClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateClient(
|
||||||
|
id: string,
|
||||||
|
updates: Partial<Client>,
|
||||||
|
): Promise<Client | null> {
|
||||||
|
const { id: _, ...updateData } = updates;
|
||||||
|
if (Object.keys(updateData).length === 0) return this.getClientById(id);
|
||||||
|
|
||||||
|
await this.db
|
||||||
|
.update(clients)
|
||||||
|
.set({ ...updateData, updatedAt: new Date() } as any)
|
||||||
|
.where(eq(clients.id, id))
|
||||||
|
.run();
|
||||||
|
|
||||||
|
return this.getClientById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteClient(id: string): Promise<boolean> {
|
||||||
|
const result = await this.db
|
||||||
|
.delete(clients)
|
||||||
|
.where(eq(clients.id, id))
|
||||||
|
.run();
|
||||||
|
return result.changes > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fitness Profile operations
|
||||||
|
async createFitnessProfile(
|
||||||
|
profileData: Omit<FitnessProfile, "id" | "createdAt" | "updatedAt">,
|
||||||
|
): Promise<FitnessProfile> {
|
||||||
|
const now = new Date();
|
||||||
|
const id = Math.random().toString(36).substr(2, 9);
|
||||||
|
const newProfile = {
|
||||||
|
id,
|
||||||
|
...profileData,
|
||||||
|
createdAt: now,
|
||||||
|
updatedAt: now,
|
||||||
|
};
|
||||||
|
|
||||||
|
await this.db.insert(fitnessProfiles).values(newProfile as any);
|
||||||
|
return { id, ...profileData, createdAt: now, updatedAt: now };
|
||||||
|
}
|
||||||
|
|
||||||
|
async getFitnessProfileByUserId(
|
||||||
|
userId: string,
|
||||||
|
): Promise<FitnessProfile | null> {
|
||||||
|
const result = await this.db
|
||||||
|
.select()
|
||||||
|
.from(fitnessProfiles)
|
||||||
|
.where(eq(fitnessProfiles.userId, userId))
|
||||||
|
.get();
|
||||||
|
return result ? this.mapFitnessProfile(result) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAllFitnessProfiles(): Promise<FitnessProfile[]> {
|
||||||
|
const results = await this.db
|
||||||
|
.select()
|
||||||
|
.from(fitnessProfiles)
|
||||||
|
.orderBy(desc(fitnessProfiles.createdAt))
|
||||||
|
.all();
|
||||||
|
return results.map(this.mapFitnessProfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateFitnessProfile(
|
||||||
|
userId: string,
|
||||||
|
updates: Partial<FitnessProfile>,
|
||||||
|
): Promise<FitnessProfile | null> {
|
||||||
|
const { userId: _, ...updateData } = updates;
|
||||||
|
if (Object.keys(updateData).length === 0)
|
||||||
|
return this.getFitnessProfileByUserId(userId);
|
||||||
|
|
||||||
|
const dbUpdates = { ...updateData } as any;
|
||||||
|
if (updateData.fitnessGoals) {
|
||||||
|
dbUpdates.fitnessGoals = JSON.stringify(updateData.fitnessGoals);
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.db
|
||||||
|
.update(fitnessProfiles)
|
||||||
|
.set({ ...dbUpdates, updatedAt: new Date() })
|
||||||
|
.where(eq(fitnessProfiles.userId, userId))
|
||||||
|
.run();
|
||||||
|
|
||||||
|
return this.getFitnessProfileByUserId(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteFitnessProfile(userId: string): Promise<boolean> {
|
||||||
|
const result = await this.db
|
||||||
|
.delete(fitnessProfiles)
|
||||||
|
.where(eq(fitnessProfiles.userId, userId))
|
||||||
|
.run();
|
||||||
|
return result.changes > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attendance operations
|
||||||
|
async checkIn(
|
||||||
|
userId: string,
|
||||||
|
type: "gym" | "class" | "personal_training",
|
||||||
|
notes?: string,
|
||||||
|
): Promise<Attendance> {
|
||||||
|
const id = Math.random().toString(36).substr(2, 9);
|
||||||
|
const now = new Date();
|
||||||
|
|
||||||
|
const newAttendance = {
|
||||||
|
id,
|
||||||
|
userId,
|
||||||
|
checkInTime: now,
|
||||||
|
type,
|
||||||
|
notes,
|
||||||
|
createdAt: now,
|
||||||
|
};
|
||||||
|
|
||||||
|
await this.db.insert(attendance).values(newAttendance as any);
|
||||||
|
|
||||||
|
// Update client last visit
|
||||||
|
const client = await this.getClientByUserId(userId);
|
||||||
|
if (client) {
|
||||||
|
await this.updateClient(client.id, { lastVisit: now });
|
||||||
|
}
|
||||||
|
|
||||||
|
return newAttendance;
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkOut(attendanceId: string): Promise<Attendance | null> {
|
||||||
|
const now = new Date();
|
||||||
|
await this.db
|
||||||
|
.update(attendance)
|
||||||
|
.set({ checkOutTime: now })
|
||||||
|
.where(eq(attendance.id, attendanceId))
|
||||||
|
.run();
|
||||||
|
|
||||||
|
return this.getAttendanceById(attendanceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAttendanceById(id: string): Promise<Attendance | null> {
|
||||||
|
const result = await this.db
|
||||||
|
.select()
|
||||||
|
.from(attendance)
|
||||||
|
.where(eq(attendance.id, id))
|
||||||
|
.get();
|
||||||
|
return result ? this.mapAttendance(result) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAttendanceHistory(userId: string): Promise<Attendance[]> {
|
||||||
|
const results = await this.db
|
||||||
|
.select()
|
||||||
|
.from(attendance)
|
||||||
|
.where(eq(attendance.userId, userId))
|
||||||
|
.orderBy(desc(attendance.checkInTime))
|
||||||
|
.all();
|
||||||
|
return results.map(this.mapAttendance);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAllAttendance(): Promise<Attendance[]> {
|
||||||
|
const results = await this.db
|
||||||
|
.select()
|
||||||
|
.from(attendance)
|
||||||
|
.orderBy(desc(attendance.checkInTime))
|
||||||
|
.all();
|
||||||
|
return results.map(this.mapAttendance);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getActiveCheckIn(userId: string): Promise<Attendance | null> {
|
||||||
|
// Drizzle doesn't support IS NULL in where directly with simple syntax sometimes, but eq(col, null) works or isNull(col)
|
||||||
|
// We need to check how to filter for null checkOutTime.
|
||||||
|
// In Drizzle, we can filter in JS or use isNull operator if imported.
|
||||||
|
// Let's fetch recent and filter for now to be safe, or use raw sql if needed, but better to use Drizzle operators.
|
||||||
|
// Actually, we can just fetch all for user and filter in memory since it's unlikely to be huge for active checkins,
|
||||||
|
// but correct way is `isNull(attendance.checkOutTime)`.
|
||||||
|
// Since I didn't import `isNull`, I'll fetch recent history and find first active.
|
||||||
|
|
||||||
|
const history = await this.getAttendanceHistory(userId);
|
||||||
|
return history.find((a) => !a.checkOutTime) || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recommendation operations
|
||||||
|
async createRecommendation(
|
||||||
|
data: Omit<Recommendation, "createdAt" | "approvedAt" | "approvedBy">,
|
||||||
|
): Promise<Recommendation> {
|
||||||
|
const now = new Date();
|
||||||
|
const newRec = {
|
||||||
|
...data,
|
||||||
|
createdAt: now,
|
||||||
|
status: data.status || "pending",
|
||||||
|
};
|
||||||
|
|
||||||
|
await this.db.insert(recommendations).values(newRec as any);
|
||||||
|
return newRec as Recommendation;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getRecommendationsByUserId(userId: string): Promise<Recommendation[]> {
|
||||||
|
const results = await this.db
|
||||||
|
.select()
|
||||||
|
.from(recommendations)
|
||||||
|
.where(eq(recommendations.userId, userId))
|
||||||
|
.orderBy(desc(recommendations.createdAt))
|
||||||
|
.all();
|
||||||
|
return results.map(this.mapRecommendation);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAllRecommendations(): Promise<Recommendation[]> {
|
||||||
|
const results = await this.db
|
||||||
|
.select()
|
||||||
|
.from(recommendations)
|
||||||
|
.orderBy(desc(recommendations.createdAt))
|
||||||
|
.all();
|
||||||
|
return results.map(this.mapRecommendation);
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateRecommendation(
|
||||||
|
id: string,
|
||||||
|
updates: Partial<Recommendation>,
|
||||||
|
): Promise<Recommendation | null> {
|
||||||
|
const { id: _, ...updateData } = updates;
|
||||||
|
if (Object.keys(updateData).length === 0)
|
||||||
|
return this.getRecommendationById(id);
|
||||||
|
|
||||||
|
await this.db
|
||||||
|
.update(recommendations)
|
||||||
|
.set(updateData as any)
|
||||||
|
.where(eq(recommendations.id, id))
|
||||||
|
.run();
|
||||||
|
|
||||||
|
return this.getRecommendationById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteRecommendation(id: string): Promise<boolean> {
|
||||||
|
const result = await this.db
|
||||||
|
.delete(recommendations)
|
||||||
|
.where(eq(recommendations.id, id))
|
||||||
|
.run();
|
||||||
|
return result.changes > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getRecommendationById(id: string): Promise<Recommendation | null> {
|
||||||
|
const result = await this.db
|
||||||
|
.select()
|
||||||
|
.from(recommendations)
|
||||||
|
.where(eq(recommendations.id, id))
|
||||||
|
.get();
|
||||||
|
return result ? this.mapRecommendation(result) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fitness Goals operations
|
||||||
|
async createFitnessGoal(
|
||||||
|
goalData: Omit<FitnessGoal, "createdAt" | "updatedAt">,
|
||||||
|
): Promise<FitnessGoal> {
|
||||||
|
const now = new Date();
|
||||||
|
const newGoal = {
|
||||||
|
...goalData,
|
||||||
|
createdAt: now,
|
||||||
|
updatedAt: now,
|
||||||
|
};
|
||||||
|
|
||||||
|
await this.db.insert(fitnessGoals).values(newGoal as any);
|
||||||
|
return newGoal as FitnessGoal;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getFitnessGoalById(id: string): Promise<FitnessGoal | null> {
|
||||||
|
const result = await this.db
|
||||||
|
.select()
|
||||||
|
.from(fitnessGoals)
|
||||||
|
.where(eq(fitnessGoals.id, id))
|
||||||
|
.get();
|
||||||
|
return result ? this.mapFitnessGoal(result) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getFitnessGoalsByUserId(
|
||||||
|
userId: string,
|
||||||
|
status?: string,
|
||||||
|
): Promise<FitnessGoal[]> {
|
||||||
|
let query = this.db
|
||||||
|
.select()
|
||||||
|
.from(fitnessGoals)
|
||||||
|
.where(eq(fitnessGoals.userId, userId));
|
||||||
|
|
||||||
|
if (status) {
|
||||||
|
query = this.db
|
||||||
|
.select()
|
||||||
|
.from(fitnessGoals)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(fitnessGoals.userId, userId),
|
||||||
|
eq(fitnessGoals.status, status as any),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const results = await query.orderBy(desc(fitnessGoals.createdAt)).all();
|
||||||
|
return results.map(this.mapFitnessGoal);
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateFitnessGoal(
|
||||||
|
id: string,
|
||||||
|
updates: Partial<FitnessGoal>,
|
||||||
|
): Promise<FitnessGoal | null> {
|
||||||
|
const { id: _, ...updateData } = updates;
|
||||||
|
if (Object.keys(updateData).length === 0)
|
||||||
|
return this.getFitnessGoalById(id);
|
||||||
|
|
||||||
|
await this.db
|
||||||
|
.update(fitnessGoals)
|
||||||
|
.set({ ...updateData, updatedAt: new Date() } as any)
|
||||||
|
.where(eq(fitnessGoals.id, id))
|
||||||
|
.run();
|
||||||
|
|
||||||
|
return this.getFitnessGoalById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteFitnessGoal(id: string): Promise<boolean> {
|
||||||
|
const result = await this.db
|
||||||
|
.delete(fitnessGoals)
|
||||||
|
.where(eq(fitnessGoals.id, id))
|
||||||
|
.run();
|
||||||
|
return result.changes > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateGoalProgress(
|
||||||
|
id: string,
|
||||||
|
currentValue: number,
|
||||||
|
): Promise<FitnessGoal | null> {
|
||||||
|
const goal = await this.getFitnessGoalById(id);
|
||||||
|
if (!goal) return null;
|
||||||
|
|
||||||
|
let progress = goal.progress;
|
||||||
|
if (goal.targetValue && goal.targetValue > 0) {
|
||||||
|
progress = Math.min(100, (currentValue / goal.targetValue) * 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.db
|
||||||
|
.update(fitnessGoals)
|
||||||
|
.set({ currentValue, progress, updatedAt: new Date() })
|
||||||
|
.where(eq(fitnessGoals.id, id))
|
||||||
|
.run();
|
||||||
|
|
||||||
|
return this.getFitnessGoalById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
async completeGoal(id: string): Promise<FitnessGoal | null> {
|
||||||
|
const now = new Date();
|
||||||
|
await this.db
|
||||||
|
.update(fitnessGoals)
|
||||||
|
.set({
|
||||||
|
status: "completed",
|
||||||
|
progress: 100,
|
||||||
|
completedDate: now,
|
||||||
|
updatedAt: now,
|
||||||
|
})
|
||||||
|
.where(eq(fitnessGoals.id, id))
|
||||||
|
.run();
|
||||||
|
|
||||||
|
return this.getFitnessGoalById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getDashboardStats(): Promise<{
|
||||||
|
totalUsers: number;
|
||||||
|
activeClients: number;
|
||||||
|
totalRevenue: number;
|
||||||
|
revenueGrowth: number;
|
||||||
|
}> {
|
||||||
|
// Placeholder implementation as per original sqlite.ts (which didn't implement this either in the viewed snippet,
|
||||||
|
// but interface requires it. I'll provide a basic implementation or mock).
|
||||||
|
// The original sqlite.ts snippet ended before showing this method, but the interface has it.
|
||||||
|
// I'll implement a basic count.
|
||||||
|
|
||||||
|
const allUsers = await this.db.select().from(users).all();
|
||||||
|
const activeClients = await this.db
|
||||||
|
.select()
|
||||||
|
.from(clients)
|
||||||
|
.where(eq(clients.membershipStatus, "active"))
|
||||||
|
.all();
|
||||||
|
|
||||||
|
return {
|
||||||
|
totalUsers: allUsers.length,
|
||||||
|
activeClients: activeClients.length,
|
||||||
|
totalRevenue: 0, // Not tracking payments yet
|
||||||
|
revenueGrowth: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mappers
|
||||||
|
private mapUser(row: any): User {
|
||||||
|
return {
|
||||||
|
...row,
|
||||||
|
gymId: (row as any).gymId ?? (row as any).gym_id ?? undefined,
|
||||||
|
createdAt: new Date(row.createdAt),
|
||||||
|
updatedAt: new Date(row.updatedAt),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private mapClient(row: any): Client {
|
||||||
|
return {
|
||||||
|
...row,
|
||||||
|
joinDate: new Date(row.joinDate),
|
||||||
|
lastVisit: row.lastVisit ? new Date(row.lastVisit) : undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private mapFitnessProfile(row: any): FitnessProfile {
|
||||||
|
return {
|
||||||
|
...row,
|
||||||
|
createdAt: new Date(row.createdAt),
|
||||||
|
updatedAt: new Date(row.updatedAt),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private mapAttendance(row: any): Attendance {
|
||||||
|
return {
|
||||||
|
...row,
|
||||||
|
checkInTime: new Date(row.checkInTime),
|
||||||
|
checkOutTime: row.checkOutTime ? new Date(row.checkOutTime) : undefined,
|
||||||
|
createdAt: new Date(row.createdAt),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private mapRecommendation(row: any): Recommendation {
|
||||||
|
return {
|
||||||
|
...row,
|
||||||
|
createdAt: new Date(row.createdAt),
|
||||||
|
approvedAt: row.approvedAt ? new Date(row.approvedAt) : undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private mapFitnessGoal(row: any): FitnessGoal {
|
||||||
|
return {
|
||||||
|
...row,
|
||||||
|
startDate: new Date(row.startDate),
|
||||||
|
targetDate: row.targetDate ? new Date(row.targetDate) : undefined,
|
||||||
|
completedDate: row.completedDate
|
||||||
|
? new Date(row.completedDate)
|
||||||
|
: undefined,
|
||||||
|
createdAt: new Date(row.createdAt),
|
||||||
|
updatedAt: new Date(row.updatedAt),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { IDatabase, DatabaseConfig } from './types'
|
import { IDatabase, DatabaseConfig } from './types'
|
||||||
import { SQLiteDatabase } from './sqlite'
|
import { DrizzleDatabase } from './drizzle'
|
||||||
|
|
||||||
// Database factory - creates appropriate database instance based on config
|
// Database factory - creates appropriate database instance based on config
|
||||||
export class DatabaseFactory {
|
export class DatabaseFactory {
|
||||||
@@ -20,7 +20,7 @@ export class DatabaseFactory {
|
|||||||
// Create new database instance based on type
|
// Create new database instance based on type
|
||||||
switch (config.type) {
|
switch (config.type) {
|
||||||
case 'sqlite':
|
case 'sqlite':
|
||||||
this.instance = new SQLiteDatabase(config)
|
this.instance = new DrizzleDatabase(config)
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'postgresql':
|
case 'postgresql':
|
||||||
|
|||||||
@@ -1,823 +0,0 @@
|
|||||||
import Database from 'better-sqlite3'
|
|
||||||
import path from 'path'
|
|
||||||
import fs from 'fs'
|
|
||||||
import { IDatabase, User, Client, FitnessProfile, Attendance, Recommendation, DatabaseConfig } from './types'
|
|
||||||
|
|
||||||
export class SQLiteDatabase implements IDatabase {
|
|
||||||
private db: Database.Database | null = null
|
|
||||||
private config: DatabaseConfig
|
|
||||||
|
|
||||||
constructor(config: DatabaseConfig) {
|
|
||||||
this.config = config
|
|
||||||
}
|
|
||||||
|
|
||||||
async connect(): Promise<void> {
|
|
||||||
try {
|
|
||||||
const dbPath = this.config.connection.filename || path.join(process.cwd(), 'data', 'fitai.db')
|
|
||||||
|
|
||||||
// Ensure data directory exists
|
|
||||||
const dataDir = path.dirname(dbPath)
|
|
||||||
if (!fs.existsSync(dataDir)) {
|
|
||||||
fs.mkdirSync(dataDir, { recursive: true })
|
|
||||||
}
|
|
||||||
|
|
||||||
this.db = new Database(dbPath)
|
|
||||||
|
|
||||||
// Enable foreign keys
|
|
||||||
this.db.exec('PRAGMA foreign_keys = ON')
|
|
||||||
|
|
||||||
// Create tables
|
|
||||||
await this.createTables()
|
|
||||||
|
|
||||||
if (this.config.options?.logging) {
|
|
||||||
console.log('SQLite database connected successfully at:', dbPath)
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to connect to SQLite database:', error)
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async disconnect(): Promise<void> {
|
|
||||||
if (this.db) {
|
|
||||||
this.db.close()
|
|
||||||
this.db = null
|
|
||||||
if (this.config.options?.logging) {
|
|
||||||
console.log('SQLite database disconnected')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async createTables(): Promise<void> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
// Users table
|
|
||||||
this.db.exec(`
|
|
||||||
CREATE TABLE IF NOT EXISTS users (
|
|
||||||
id TEXT PRIMARY KEY,
|
|
||||||
email TEXT UNIQUE NOT NULL,
|
|
||||||
firstName TEXT NOT NULL,
|
|
||||||
lastName TEXT NOT NULL,
|
|
||||||
password TEXT NOT NULL,
|
|
||||||
phone TEXT,
|
|
||||||
role TEXT NOT NULL CHECK (role IN ('superAdmin', 'admin', 'trainer', 'client')),
|
|
||||||
createdAt DATETIME NOT NULL,
|
|
||||||
updatedAt DATETIME NOT NULL
|
|
||||||
)
|
|
||||||
`)
|
|
||||||
|
|
||||||
// Clients table
|
|
||||||
this.db.exec(`
|
|
||||||
CREATE TABLE IF NOT EXISTS clients (
|
|
||||||
id TEXT PRIMARY KEY,
|
|
||||||
userId TEXT NOT NULL,
|
|
||||||
membershipType TEXT NOT NULL CHECK (membershipType IN ('basic', 'premium', 'vip')),
|
|
||||||
membershipStatus TEXT NOT NULL CHECK (membershipStatus IN ('active', 'inactive', 'expired')),
|
|
||||||
joinDate DATETIME NOT NULL,
|
|
||||||
FOREIGN KEY (userId) REFERENCES users (id) ON DELETE CASCADE
|
|
||||||
)
|
|
||||||
`)
|
|
||||||
|
|
||||||
// Fitness profiles table
|
|
||||||
this.db.exec(`
|
|
||||||
CREATE TABLE IF NOT EXISTS fitness_profiles (
|
|
||||||
userId TEXT PRIMARY KEY,
|
|
||||||
height TEXT NOT NULL,
|
|
||||||
weight TEXT NOT NULL,
|
|
||||||
age TEXT NOT NULL,
|
|
||||||
gender TEXT NOT NULL CHECK (gender IN ('male', 'female', 'other')),
|
|
||||||
activityLevel TEXT NOT NULL CHECK (activityLevel IN ('sedentary', 'light', 'moderate', 'active', 'very_active')),
|
|
||||||
fitnessGoals TEXT NOT NULL, -- JSON array
|
|
||||||
exerciseHabits TEXT,
|
|
||||||
dietHabits TEXT,
|
|
||||||
medicalConditions TEXT,
|
|
||||||
allergies TEXT,
|
|
||||||
injuries TEXT,
|
|
||||||
createdAt DATETIME NOT NULL,
|
|
||||||
updatedAt DATETIME NOT NULL,
|
|
||||||
FOREIGN KEY (userId) REFERENCES users (id) ON DELETE CASCADE
|
|
||||||
)
|
|
||||||
`)
|
|
||||||
|
|
||||||
// Create indexes for better performance
|
|
||||||
this.db.exec(`
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_clients_userId ON clients(userId);
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_fitness_profiles_userId ON fitness_profiles(userId);
|
|
||||||
`)
|
|
||||||
|
|
||||||
// Attendance table
|
|
||||||
this.db.exec(`
|
|
||||||
CREATE TABLE IF NOT EXISTS attendance (
|
|
||||||
id TEXT PRIMARY KEY,
|
|
||||||
clientId TEXT NOT NULL,
|
|
||||||
checkInTime DATETIME NOT NULL,
|
|
||||||
checkOutTime DATETIME,
|
|
||||||
type TEXT NOT NULL CHECK (type IN ('gym', 'class', 'personal_training')),
|
|
||||||
notes TEXT,
|
|
||||||
createdAt DATETIME NOT NULL,
|
|
||||||
FOREIGN KEY (clientId) REFERENCES clients (id) ON DELETE CASCADE
|
|
||||||
)
|
|
||||||
`)
|
|
||||||
|
|
||||||
// Recommendations table
|
|
||||||
// Removed DROP TABLE to persist data. Schema is now stable.
|
|
||||||
// this.db.exec(`DROP TABLE IF EXISTS recommendations`)
|
|
||||||
|
|
||||||
this.db.exec(`
|
|
||||||
CREATE TABLE IF NOT EXISTS recommendations (
|
|
||||||
id TEXT PRIMARY KEY,
|
|
||||||
userId TEXT NOT NULL,
|
|
||||||
fitnessProfileId TEXT,
|
|
||||||
type TEXT NOT NULL,
|
|
||||||
content TEXT NOT NULL,
|
|
||||||
activityPlan TEXT,
|
|
||||||
dietPlan TEXT,
|
|
||||||
status TEXT NOT NULL CHECK (status IN ('pending', 'approved', 'rejected', 'completed')),
|
|
||||||
createdAt DATETIME NOT NULL,
|
|
||||||
approvedAt DATETIME,
|
|
||||||
approvedBy TEXT,
|
|
||||||
FOREIGN KEY (userId) REFERENCES users (id) ON DELETE CASCADE,
|
|
||||||
FOREIGN KEY (fitnessProfileId) REFERENCES fitness_profiles (userId)
|
|
||||||
)
|
|
||||||
`)
|
|
||||||
|
|
||||||
this.db.exec(`
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_recommendations_userId ON recommendations(userId);
|
|
||||||
`)
|
|
||||||
|
|
||||||
this.db.exec(`
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_attendance_clientId ON attendance(clientId);
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_attendance_checkInTime ON attendance(checkInTime);
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// User operations
|
|
||||||
async createUser(
|
|
||||||
userData: Omit<User, "createdAt" | "updatedAt" | "id"> & { id?: string },
|
|
||||||
): Promise<User> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const id = userData.id || Math.random().toString(36).substr(2, 9)
|
|
||||||
const now = new Date()
|
|
||||||
|
|
||||||
const user: User = {
|
|
||||||
...userData,
|
|
||||||
id,
|
|
||||||
createdAt: now,
|
|
||||||
updatedAt: now
|
|
||||||
}
|
|
||||||
|
|
||||||
const stmt = this.db.prepare(
|
|
||||||
`INSERT INTO users(id, email, firstName, lastName, password, phone, role, createdAt, updatedAt)
|
|
||||||
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
||||||
)
|
|
||||||
|
|
||||||
stmt.run(
|
|
||||||
user.id, user.email, user.firstName, user.lastName, user.password,
|
|
||||||
user.phone, user.role, user.createdAt.toISOString(), user.updatedAt.toISOString()
|
|
||||||
)
|
|
||||||
|
|
||||||
return user
|
|
||||||
}
|
|
||||||
|
|
||||||
async getUserById(id: string): Promise<User | null> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const stmt = this.db.prepare('SELECT * FROM users WHERE id = ?')
|
|
||||||
const row = stmt.get(id)
|
|
||||||
|
|
||||||
return row ? this.mapRowToUser(row) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
async getUserByEmail(email: string): Promise<User | null> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const stmt = this.db.prepare('SELECT * FROM users WHERE email = ?')
|
|
||||||
const row = stmt.get(email)
|
|
||||||
|
|
||||||
return row ? this.mapRowToUser(row) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
async getAllUsers(): Promise<User[]> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const stmt = this.db.prepare('SELECT * FROM users ORDER BY createdAt DESC')
|
|
||||||
const rows = stmt.all()
|
|
||||||
|
|
||||||
return rows.map(row => this.mapRowToUser(row))
|
|
||||||
}
|
|
||||||
|
|
||||||
async updateUser(id: string, updates: Partial<User>): Promise<User | null> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const fields = Object.keys(updates).filter(key => key !== 'id')
|
|
||||||
if (fields.length === 0) return this.getUserById(id)
|
|
||||||
|
|
||||||
const setClause = fields.map(field => `${field} = ?`).join(', ')
|
|
||||||
const values = fields.map(field => (updates as any)[field])
|
|
||||||
values.push(new Date().toISOString()) // updatedAt
|
|
||||||
values.push(id)
|
|
||||||
|
|
||||||
const stmt = this.db.prepare(`UPDATE users SET ${setClause}, updatedAt = ? WHERE id = ? `)
|
|
||||||
stmt.run(values)
|
|
||||||
|
|
||||||
return this.getUserById(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
async deleteUser(id: string): Promise<boolean> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const stmt = this.db.prepare('DELETE FROM users WHERE id = ?')
|
|
||||||
const result = stmt.run(id)
|
|
||||||
return (result.changes || 0) > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
async migrateUserId(oldId: string, newId: string): Promise<void> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
// We need to disable foreign keys temporarily if we want to update ID without cascade (if cascade isn't set)
|
|
||||||
// But we should try to update and let cascade handle it if possible.
|
|
||||||
// Since we didn't set ON UPDATE CASCADE, we might need to manually update references or use PRAGMA.
|
|
||||||
|
|
||||||
// Simplest way: Update the ID. If it fails due to FK, we have to handle it.
|
|
||||||
// For the Super Admin seed case, there are no dependencies.
|
|
||||||
|
|
||||||
const stmt = this.db.prepare('UPDATE users SET id = ? WHERE id = ?')
|
|
||||||
stmt.run(newId, oldId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Client operations
|
|
||||||
async createClient(clientData: Omit<Client, 'id'>): Promise<Client> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const id = Math.random().toString(36).substr(2, 9)
|
|
||||||
const client: Client = { id, ...clientData }
|
|
||||||
|
|
||||||
const stmt = this.db.prepare(
|
|
||||||
`INSERT INTO clients(id, userId, membershipType, membershipStatus, joinDate)
|
|
||||||
VALUES(?, ?, ?, ?, ?)`
|
|
||||||
)
|
|
||||||
|
|
||||||
stmt.run(
|
|
||||||
client.id, client.userId, client.membershipType,
|
|
||||||
client.membershipStatus, client.joinDate.toISOString()
|
|
||||||
)
|
|
||||||
|
|
||||||
return client
|
|
||||||
}
|
|
||||||
|
|
||||||
async getClientById(id: string): Promise<Client | null> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const stmt = this.db.prepare('SELECT * FROM clients WHERE id = ?')
|
|
||||||
const row = stmt.get(id)
|
|
||||||
return row ? this.mapRowToClient(row) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
async getClientByUserId(userId: string): Promise<Client | null> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const stmt = this.db.prepare('SELECT * FROM clients WHERE userId = ?')
|
|
||||||
const row = stmt.get(userId)
|
|
||||||
return row ? this.mapRowToClient(row) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
async getAllClients(): Promise<Client[]> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const stmt = this.db.prepare('SELECT * FROM clients ORDER BY joinDate DESC')
|
|
||||||
const rows = stmt.all()
|
|
||||||
return rows.map(row => this.mapRowToClient(row))
|
|
||||||
}
|
|
||||||
|
|
||||||
async updateClient(id: string, updates: Partial<Client>): Promise<Client | null> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const fields = Object.keys(updates).filter(key => key !== 'id')
|
|
||||||
if (fields.length === 0) return this.getClientById(id)
|
|
||||||
|
|
||||||
const setClause = fields.map(field => `${field} = ?`).join(', ')
|
|
||||||
const values = fields.map(field => (updates as any)[field])
|
|
||||||
values.push(id)
|
|
||||||
|
|
||||||
const stmt = this.db.prepare(`UPDATE clients SET ${setClause} WHERE id = ? `)
|
|
||||||
stmt.run(values)
|
|
||||||
|
|
||||||
return this.getClientById(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
async deleteClient(id: string): Promise<boolean> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const stmt = this.db.prepare('DELETE FROM clients WHERE id = ?')
|
|
||||||
const result = stmt.run(id)
|
|
||||||
return (result.changes || 0) > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fitness Profile operations
|
|
||||||
async createFitnessProfile(profileData: Omit<FitnessProfile, 'createdAt' | 'updatedAt'>): Promise<FitnessProfile> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const now = new Date()
|
|
||||||
const profile: FitnessProfile = {
|
|
||||||
...profileData,
|
|
||||||
createdAt: now,
|
|
||||||
updatedAt: now
|
|
||||||
}
|
|
||||||
|
|
||||||
const stmt = this.db.prepare(
|
|
||||||
`INSERT INTO fitness_profiles
|
|
||||||
(userId, height, weight, age, gender, activityLevel, fitnessGoals,
|
|
||||||
exerciseHabits, dietHabits, medicalConditions, allergies, injuries, createdAt, updatedAt)
|
|
||||||
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
||||||
)
|
|
||||||
|
|
||||||
stmt.run(
|
|
||||||
profile.userId, profile.height, profile.weight, profile.age, profile.gender,
|
|
||||||
profile.activityLevel, JSON.stringify(profile.fitnessGoals), profile.exerciseHabits,
|
|
||||||
profile.dietHabits, profile.medicalConditions, profile.allergies, profile.injuries,
|
|
||||||
profile.createdAt.toISOString(), profile.updatedAt.toISOString()
|
|
||||||
)
|
|
||||||
|
|
||||||
return profile
|
|
||||||
}
|
|
||||||
|
|
||||||
async getFitnessProfileByUserId(userId: string): Promise<FitnessProfile | null> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const stmt = this.db.prepare('SELECT * FROM fitness_profiles WHERE userId = ?')
|
|
||||||
const row = stmt.get(userId)
|
|
||||||
|
|
||||||
return row ? this.mapRowToFitnessProfile(row) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
async getAllFitnessProfiles(): Promise<FitnessProfile[]> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const stmt = this.db.prepare('SELECT * FROM fitness_profiles ORDER BY createdAt DESC')
|
|
||||||
const rows = stmt.all()
|
|
||||||
return rows.map(row => this.mapRowToFitnessProfile(row))
|
|
||||||
}
|
|
||||||
|
|
||||||
async updateFitnessProfile(userId: string, updates: Partial<FitnessProfile>): Promise<FitnessProfile | null> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const fields = Object.keys(updates).filter(key => key !== 'userId' && key !== 'createdAt')
|
|
||||||
if (fields.length === 0) return this.getFitnessProfileByUserId(userId)
|
|
||||||
|
|
||||||
const setClause = fields.map(field => `${field} = ?`).join(', ')
|
|
||||||
const values = fields.map(field => {
|
|
||||||
const value = (updates as any)[field]
|
|
||||||
return field === 'fitnessGoals' ? JSON.stringify(value) : value
|
|
||||||
})
|
|
||||||
values.push(new Date().toISOString()) // updatedAt
|
|
||||||
values.push(userId)
|
|
||||||
|
|
||||||
const stmt = this.db.prepare(`UPDATE fitness_profiles SET ${setClause}, updatedAt = ? WHERE userId = ? `)
|
|
||||||
stmt.run(values)
|
|
||||||
|
|
||||||
return this.getFitnessProfileByUserId(userId)
|
|
||||||
}
|
|
||||||
|
|
||||||
async deleteFitnessProfile(userId: string): Promise<boolean> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const stmt = this.db.prepare('DELETE FROM fitness_profiles WHERE userId = ?')
|
|
||||||
const result = stmt.run(userId)
|
|
||||||
return (result.changes || 0) > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attendance operations
|
|
||||||
async checkIn(clientId: string, type: 'gym' | 'class' | 'personal_training', notes?: string): Promise<Attendance> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const id = Math.random().toString(36).substr(2, 9)
|
|
||||||
const now = new Date()
|
|
||||||
|
|
||||||
const attendance: Attendance = {
|
|
||||||
id,
|
|
||||||
clientId,
|
|
||||||
checkInTime: now,
|
|
||||||
type,
|
|
||||||
notes,
|
|
||||||
createdAt: now
|
|
||||||
}
|
|
||||||
|
|
||||||
const stmt = this.db.prepare(
|
|
||||||
`INSERT INTO attendance(id, clientId, checkInTime, type, notes, createdAt)
|
|
||||||
VALUES(?, ?, ?, ?, ?, ?)`
|
|
||||||
)
|
|
||||||
|
|
||||||
stmt.run(
|
|
||||||
attendance.id, attendance.clientId, attendance.checkInTime.toISOString(),
|
|
||||||
attendance.type, attendance.notes, attendance.createdAt.toISOString()
|
|
||||||
)
|
|
||||||
|
|
||||||
// Update client last visit
|
|
||||||
this.db.prepare('UPDATE clients SET lastVisit = ? WHERE id = ?').run(
|
|
||||||
now.toISOString(),
|
|
||||||
clientId
|
|
||||||
)
|
|
||||||
|
|
||||||
return attendance
|
|
||||||
}
|
|
||||||
|
|
||||||
async checkOut(attendanceId: string): Promise<Attendance | null> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const now = new Date()
|
|
||||||
const stmt = this.db.prepare('UPDATE attendance SET checkOutTime = ? WHERE id = ?')
|
|
||||||
stmt.run(now.toISOString(), attendanceId)
|
|
||||||
|
|
||||||
return this.getAttendanceById(attendanceId)
|
|
||||||
}
|
|
||||||
|
|
||||||
async getAttendanceById(id: string): Promise<Attendance | null> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
const stmt = this.db.prepare('SELECT * FROM attendance WHERE id = ?')
|
|
||||||
const row = stmt.get(id)
|
|
||||||
return row ? this.mapRowToAttendance(row) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
async getAttendanceHistory(clientId: string): Promise<Attendance[]> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
const stmt = this.db.prepare('SELECT * FROM attendance WHERE clientId = ? ORDER BY checkInTime DESC')
|
|
||||||
const rows = stmt.all(clientId)
|
|
||||||
return rows.map(row => this.mapRowToAttendance(row))
|
|
||||||
}
|
|
||||||
|
|
||||||
async getAllAttendance(): Promise<Attendance[]> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
const stmt = this.db.prepare('SELECT * FROM attendance ORDER BY checkInTime DESC')
|
|
||||||
const rows = stmt.all()
|
|
||||||
return rows.map(row => this.mapRowToAttendance(row))
|
|
||||||
}
|
|
||||||
|
|
||||||
async getActiveCheckIn(clientId: string): Promise<Attendance | null> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
const stmt = this.db.prepare('SELECT * FROM attendance WHERE clientId = ? AND checkOutTime IS NULL ORDER BY checkInTime DESC LIMIT 1')
|
|
||||||
const row = stmt.get(clientId)
|
|
||||||
return row ? this.mapRowToAttendance(row) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper methods to map database rows to entities
|
|
||||||
private mapRowToUser(row: any): User {
|
|
||||||
return {
|
|
||||||
id: row.id,
|
|
||||||
email: row.email,
|
|
||||||
firstName: row.firstName,
|
|
||||||
lastName: row.lastName,
|
|
||||||
password: row.password,
|
|
||||||
phone: row.phone,
|
|
||||||
role: row.role,
|
|
||||||
createdAt: new Date(row.createdAt),
|
|
||||||
updatedAt: new Date(row.updatedAt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private mapRowToClient(row: any): Client {
|
|
||||||
return {
|
|
||||||
id: row.id,
|
|
||||||
userId: row.userId,
|
|
||||||
membershipType: row.membershipType,
|
|
||||||
membershipStatus: row.membershipStatus,
|
|
||||||
joinDate: new Date(row.joinDate),
|
|
||||||
lastVisit: row.lastVisit ? new Date(row.lastVisit) : undefined
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private mapRowToFitnessProfile(row: any): FitnessProfile {
|
|
||||||
return {
|
|
||||||
userId: row.userId,
|
|
||||||
height: row.height,
|
|
||||||
weight: row.weight,
|
|
||||||
age: row.age,
|
|
||||||
gender: row.gender,
|
|
||||||
activityLevel: row.activityLevel,
|
|
||||||
fitnessGoals: JSON.parse(row.fitnessGoals || '[]'),
|
|
||||||
exerciseHabits: row.exerciseHabits,
|
|
||||||
dietHabits: row.dietHabits,
|
|
||||||
medicalConditions: row.medicalConditions,
|
|
||||||
allergies: row.allergies,
|
|
||||||
injuries: row.injuries,
|
|
||||||
createdAt: new Date(row.createdAt),
|
|
||||||
updatedAt: new Date(row.updatedAt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private mapRowToAttendance(row: any): Attendance {
|
|
||||||
return {
|
|
||||||
id: row.id,
|
|
||||||
clientId: row.clientId,
|
|
||||||
checkInTime: new Date(row.checkInTime),
|
|
||||||
checkOutTime: row.checkOutTime ? new Date(row.checkOutTime) : undefined,
|
|
||||||
type: row.type,
|
|
||||||
notes: row.notes,
|
|
||||||
createdAt: new Date(row.createdAt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recommendation operations
|
|
||||||
async createRecommendation(data: Omit<Recommendation, 'createdAt' | 'approvedAt' | 'approvedBy'>): Promise<Recommendation> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const now = new Date()
|
|
||||||
const recommendation: Recommendation = {
|
|
||||||
...data,
|
|
||||||
createdAt: now,
|
|
||||||
status: data.status || 'pending'
|
|
||||||
}
|
|
||||||
|
|
||||||
const stmt = this.db.prepare(
|
|
||||||
`INSERT INTO recommendations (
|
|
||||||
id, userId, fitnessProfileId, type, content,
|
|
||||||
activityPlan, dietPlan, status, createdAt
|
|
||||||
)
|
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
||||||
)
|
|
||||||
|
|
||||||
stmt.run(
|
|
||||||
recommendation.id, recommendation.userId, recommendation.fitnessProfileId,
|
|
||||||
recommendation.type, recommendation.content, recommendation.activityPlan,
|
|
||||||
recommendation.dietPlan, recommendation.status,
|
|
||||||
recommendation.createdAt.toISOString()
|
|
||||||
)
|
|
||||||
|
|
||||||
return recommendation
|
|
||||||
}
|
|
||||||
|
|
||||||
async getRecommendationsByUserId(userId: string): Promise<Recommendation[]> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const stmt = this.db.prepare('SELECT * FROM recommendations WHERE userId = ? ORDER BY createdAt DESC')
|
|
||||||
const rows = stmt.all(userId)
|
|
||||||
|
|
||||||
return rows.map(row => this.mapRowToRecommendation(row))
|
|
||||||
}
|
|
||||||
|
|
||||||
async getAllRecommendations(): Promise<Recommendation[]> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const stmt = this.db.prepare('SELECT * FROM recommendations ORDER BY createdAt DESC')
|
|
||||||
const rows = stmt.all()
|
|
||||||
|
|
||||||
return rows.map(row => this.mapRowToRecommendation(row))
|
|
||||||
}
|
|
||||||
|
|
||||||
async updateRecommendation(id: string, updates: Partial<Recommendation>): Promise<Recommendation | null> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const fields = Object.keys(updates).filter(key => key !== 'id' && key !== 'userId')
|
|
||||||
if (fields.length === 0) {
|
|
||||||
const stmt = this.db.prepare('SELECT * FROM recommendations WHERE id = ?')
|
|
||||||
const row = stmt.get(id)
|
|
||||||
return row ? this.mapRowToRecommendation(row) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
const setClause = fields.map(field => `${field} = ?`).join(', ')
|
|
||||||
const values = fields.map(field => {
|
|
||||||
const val = (updates as any)[field]
|
|
||||||
return val instanceof Date ? val.toISOString() : val
|
|
||||||
})
|
|
||||||
values.push(id)
|
|
||||||
|
|
||||||
const stmt = this.db.prepare(`UPDATE recommendations SET ${setClause} WHERE id = ?`)
|
|
||||||
stmt.run(values)
|
|
||||||
|
|
||||||
const getStmt = this.db.prepare('SELECT * FROM recommendations WHERE id = ?')
|
|
||||||
const row = getStmt.get(id)
|
|
||||||
return row ? this.mapRowToRecommendation(row) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
async deleteRecommendation(id: string): Promise<boolean> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const stmt = this.db.prepare('DELETE FROM recommendations WHERE id = ?')
|
|
||||||
const result = stmt.run(id)
|
|
||||||
return (result.changes || 0) > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
private mapRowToRecommendation(row: any): Recommendation {
|
|
||||||
return {
|
|
||||||
id: row.id,
|
|
||||||
userId: row.userId,
|
|
||||||
fitnessProfileId: row.fitnessProfileId,
|
|
||||||
type: row.type,
|
|
||||||
content: row.content,
|
|
||||||
activityPlan: row.activityPlan,
|
|
||||||
dietPlan: row.dietPlan,
|
|
||||||
status: row.status,
|
|
||||||
createdAt: new Date(row.createdAt),
|
|
||||||
approvedAt: row.approvedAt ? new Date(row.approvedAt) : undefined,
|
|
||||||
approvedBy: row.approvedBy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fitness Goals operations
|
|
||||||
async createFitnessGoal(goalData: Omit<import('./types').FitnessGoal, 'createdAt' | 'updatedAt'>): Promise<import('./types').FitnessGoal> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const now = new Date()
|
|
||||||
const goal: import('./types').FitnessGoal = {
|
|
||||||
...goalData,
|
|
||||||
createdAt: now,
|
|
||||||
updatedAt: now
|
|
||||||
}
|
|
||||||
|
|
||||||
const stmt = this.db.prepare(
|
|
||||||
`INSERT INTO fitness_goals (
|
|
||||||
id, user_id, fitness_profile_id, goal_type, title, description,
|
|
||||||
target_value, current_value, unit, start_date, target_date,
|
|
||||||
completed_date, status, progress, priority, notes, created_at, updated_at
|
|
||||||
)
|
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
||||||
)
|
|
||||||
|
|
||||||
stmt.run(
|
|
||||||
goal.id,
|
|
||||||
goal.userId,
|
|
||||||
goal.fitnessProfileId || null,
|
|
||||||
goal.goalType,
|
|
||||||
goal.title,
|
|
||||||
goal.description || null,
|
|
||||||
goal.targetValue || null,
|
|
||||||
goal.currentValue || null,
|
|
||||||
goal.unit || null,
|
|
||||||
goal.startDate.toISOString(),
|
|
||||||
goal.targetDate ? goal.targetDate.toISOString() : null,
|
|
||||||
goal.completedDate ? goal.completedDate.toISOString() : null,
|
|
||||||
goal.status,
|
|
||||||
goal.progress,
|
|
||||||
goal.priority,
|
|
||||||
goal.notes || null,
|
|
||||||
goal.createdAt.toISOString(),
|
|
||||||
goal.updatedAt.toISOString()
|
|
||||||
)
|
|
||||||
|
|
||||||
return goal
|
|
||||||
}
|
|
||||||
|
|
||||||
async getFitnessGoalById(id: string): Promise<import('./types').FitnessGoal | null> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const stmt = this.db.prepare('SELECT * FROM fitness_goals WHERE id = ?')
|
|
||||||
const row = stmt.get(id)
|
|
||||||
|
|
||||||
return row ? this.mapRowToFitnessGoal(row) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
async getFitnessGoalsByUserId(userId: string, status?: string): Promise<import('./types').FitnessGoal[]> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
let query = 'SELECT * FROM fitness_goals WHERE user_id = ?'
|
|
||||||
const params: any[] = [userId]
|
|
||||||
|
|
||||||
if (status) {
|
|
||||||
query += ' AND status = ?'
|
|
||||||
params.push(status)
|
|
||||||
}
|
|
||||||
|
|
||||||
query += ' ORDER BY created_at DESC'
|
|
||||||
|
|
||||||
const stmt = this.db.prepare(query)
|
|
||||||
const rows = stmt.all(...params)
|
|
||||||
|
|
||||||
return rows.map(row => this.mapRowToFitnessGoal(row))
|
|
||||||
}
|
|
||||||
|
|
||||||
async updateFitnessGoal(id: string, updates: Partial<import('./types').FitnessGoal>): Promise<import('./types').FitnessGoal | null> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const fields = Object.keys(updates).filter(key => key !== 'id' && key !== 'createdAt')
|
|
||||||
if (fields.length === 0) return this.getFitnessGoalById(id)
|
|
||||||
|
|
||||||
// Map camelCase to snake_case for database columns
|
|
||||||
const columnMap: Record<string, string> = {
|
|
||||||
userId: 'user_id',
|
|
||||||
fitnessProfileId: 'fitness_profile_id',
|
|
||||||
goalType: 'goal_type',
|
|
||||||
targetValue: 'target_value',
|
|
||||||
currentValue: 'current_value',
|
|
||||||
startDate: 'start_date',
|
|
||||||
targetDate: 'target_date',
|
|
||||||
completedDate: 'completed_date',
|
|
||||||
updatedAt: 'updated_at'
|
|
||||||
}
|
|
||||||
|
|
||||||
const setClause = fields.map(field => `${columnMap[field] || field} = ?`).join(', ')
|
|
||||||
const values = fields.map(field => {
|
|
||||||
const val = (updates as any)[field]
|
|
||||||
return val instanceof Date ? val.toISOString() : val
|
|
||||||
})
|
|
||||||
values.push(new Date().toISOString()) // updatedAt
|
|
||||||
values.push(id)
|
|
||||||
|
|
||||||
const stmt = this.db.prepare(`UPDATE fitness_goals SET ${setClause}, updated_at = ? WHERE id = ?`)
|
|
||||||
stmt.run(values)
|
|
||||||
|
|
||||||
return this.getFitnessGoalById(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
async deleteFitnessGoal(id: string): Promise<boolean> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const stmt = this.db.prepare('DELETE FROM fitness_goals WHERE id = ?')
|
|
||||||
const result = stmt.run(id)
|
|
||||||
return (result.changes || 0) > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
async updateGoalProgress(id: string, currentValue: number): Promise<import('./types').FitnessGoal | null> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
// Get the goal to calculate progress
|
|
||||||
const goal = await this.getFitnessGoalById(id)
|
|
||||||
if (!goal) return null
|
|
||||||
|
|
||||||
let progress = goal.progress
|
|
||||||
if (goal.targetValue && goal.targetValue > 0) {
|
|
||||||
progress = Math.min(100, (currentValue / goal.targetValue) * 100)
|
|
||||||
}
|
|
||||||
|
|
||||||
const stmt = this.db.prepare(
|
|
||||||
'UPDATE fitness_goals SET current_value = ?, progress = ?, updated_at = ? WHERE id = ?'
|
|
||||||
)
|
|
||||||
stmt.run(currentValue, progress, new Date().toISOString(), id)
|
|
||||||
|
|
||||||
return this.getFitnessGoalById(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
async completeGoal(id: string): Promise<import('./types').FitnessGoal | null> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
const now = new Date()
|
|
||||||
const stmt = this.db.prepare(
|
|
||||||
'UPDATE fitness_goals SET status = ?, progress = ?, completed_date = ?, updated_at = ? WHERE id = ?'
|
|
||||||
)
|
|
||||||
stmt.run('completed', 100, now.toISOString(), now.toISOString(), id)
|
|
||||||
|
|
||||||
return this.getFitnessGoalById(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
private mapRowToFitnessGoal(row: any): import('./types').FitnessGoal {
|
|
||||||
return {
|
|
||||||
id: row.id,
|
|
||||||
userId: row.user_id,
|
|
||||||
fitnessProfileId: row.fitness_profile_id,
|
|
||||||
goalType: row.goal_type,
|
|
||||||
title: row.title,
|
|
||||||
description: row.description,
|
|
||||||
targetValue: row.target_value,
|
|
||||||
currentValue: row.current_value,
|
|
||||||
unit: row.unit,
|
|
||||||
startDate: new Date(row.start_date),
|
|
||||||
targetDate: row.target_date ? new Date(row.target_date) : undefined,
|
|
||||||
completedDate: row.completed_date ? new Date(row.completed_date) : undefined,
|
|
||||||
status: row.status,
|
|
||||||
progress: row.progress,
|
|
||||||
priority: row.priority,
|
|
||||||
notes: row.notes,
|
|
||||||
createdAt: new Date(row.created_at),
|
|
||||||
updatedAt: new Date(row.updated_at)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getDashboardStats(): Promise<{
|
|
||||||
totalUsers: number;
|
|
||||||
activeClients: number;
|
|
||||||
totalRevenue: number;
|
|
||||||
revenueGrowth: number;
|
|
||||||
}> {
|
|
||||||
if (!this.db) throw new Error('Database not connected')
|
|
||||||
|
|
||||||
// Total Users
|
|
||||||
const userCountStmt = this.db.prepare('SELECT COUNT(*) as count FROM users')
|
|
||||||
const userCount = (userCountStmt.get() as any).count
|
|
||||||
|
|
||||||
// Active Clients
|
|
||||||
const activeClientCountStmt = this.db.prepare("SELECT COUNT(*) as count FROM clients WHERE membershipStatus = 'active'")
|
|
||||||
const activeClientCount = (activeClientCountStmt.get() as any).count
|
|
||||||
|
|
||||||
// Total Revenue (assuming payments table exists, handling if it's empty)
|
|
||||||
// Note: We need to create the payments table first if it doesn't exist in createTables
|
|
||||||
// For now, returning 0 if table doesn't exist or is empty
|
|
||||||
let totalRevenue = 0
|
|
||||||
let revenueGrowth = 0
|
|
||||||
|
|
||||||
try {
|
|
||||||
const revenueStmt = this.db.prepare('SELECT SUM(amount) as total FROM payments WHERE status = "completed"')
|
|
||||||
const revenueResult = revenueStmt.get() as any
|
|
||||||
totalRevenue = revenueResult?.total || 0
|
|
||||||
} catch (e) {
|
|
||||||
// Table might not exist yet
|
|
||||||
console.warn('Payments table query failed, returning 0 revenue')
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
totalUsers: userCount,
|
|
||||||
activeClients: activeClientCount,
|
|
||||||
totalRevenue,
|
|
||||||
revenueGrowth
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,86 +1,20 @@
|
|||||||
|
import {
|
||||||
|
User as SharedUser,
|
||||||
|
Client,
|
||||||
|
FitnessProfile,
|
||||||
|
Attendance,
|
||||||
|
Recommendation,
|
||||||
|
FitnessGoal,
|
||||||
|
} from "@fitai/shared";
|
||||||
|
|
||||||
// Database Entity Types
|
// Database Entity Types
|
||||||
export interface User {
|
export interface User extends SharedUser {
|
||||||
id: string;
|
// Explicitly include gymId so server imports can rely on it even if shared types lag behind build
|
||||||
email: string;
|
gymId?: string;
|
||||||
firstName: string;
|
|
||||||
lastName: string;
|
|
||||||
password: string;
|
password: string;
|
||||||
phone?: string;
|
|
||||||
role: "superAdmin" | "admin" | "trainer" | "client";
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Client {
|
export type { Client, FitnessProfile, Attendance, Recommendation, FitnessGoal };
|
||||||
id: string;
|
|
||||||
userId: string;
|
|
||||||
membershipType: "basic" | "premium" | "vip";
|
|
||||||
membershipStatus: "active" | "inactive" | "expired";
|
|
||||||
joinDate: Date;
|
|
||||||
lastVisit?: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FitnessProfile {
|
|
||||||
userId: string;
|
|
||||||
height: string;
|
|
||||||
weight: string;
|
|
||||||
age: string;
|
|
||||||
gender: "male" | "female" | "other";
|
|
||||||
activityLevel: "sedentary" | "light" | "moderate" | "active" | "very_active";
|
|
||||||
fitnessGoals: string[];
|
|
||||||
exerciseHabits: string;
|
|
||||||
dietHabits: string;
|
|
||||||
medicalConditions: string;
|
|
||||||
allergies?: string;
|
|
||||||
injuries?: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Attendance {
|
|
||||||
id: string;
|
|
||||||
clientId: string;
|
|
||||||
checkInTime: Date;
|
|
||||||
checkOutTime?: Date;
|
|
||||||
type: "gym" | "class" | "personal_training";
|
|
||||||
notes?: string;
|
|
||||||
createdAt: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Recommendation {
|
|
||||||
id: string;
|
|
||||||
userId: string;
|
|
||||||
fitnessProfileId?: string;
|
|
||||||
type: "short_term" | "medium_term" | "long_term" | "ai_plan";
|
|
||||||
content: string;
|
|
||||||
activityPlan?: string;
|
|
||||||
dietPlan?: string;
|
|
||||||
status: "pending" | "approved" | "rejected" | "completed";
|
|
||||||
createdAt: Date;
|
|
||||||
approvedAt?: Date;
|
|
||||||
approvedBy?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FitnessGoal {
|
|
||||||
id: string;
|
|
||||||
userId: string;
|
|
||||||
fitnessProfileId?: string;
|
|
||||||
goalType: "weight_target" | "strength_milestone" | "endurance_target" | "flexibility_goal" | "habit_building" | "custom";
|
|
||||||
title: string;
|
|
||||||
description?: string;
|
|
||||||
targetValue?: number;
|
|
||||||
currentValue?: number;
|
|
||||||
unit?: string;
|
|
||||||
startDate: Date;
|
|
||||||
targetDate?: Date;
|
|
||||||
completedDate?: Date;
|
|
||||||
status: "active" | "completed" | "abandoned" | "paused";
|
|
||||||
progress: number;
|
|
||||||
priority: "low" | "medium" | "high";
|
|
||||||
notes?: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Database Interface - allows us to swap implementations
|
// Database Interface - allows us to swap implementations
|
||||||
export interface IDatabase {
|
export interface IDatabase {
|
||||||
@@ -121,18 +55,21 @@ export interface IDatabase {
|
|||||||
|
|
||||||
// Attendance operations
|
// Attendance operations
|
||||||
checkIn(
|
checkIn(
|
||||||
clientId: string,
|
userId: string,
|
||||||
type: "gym" | "class" | "personal_training",
|
type: "gym" | "class" | "personal_training",
|
||||||
notes?: string,
|
notes?: string,
|
||||||
): Promise<Attendance>;
|
): Promise<Attendance>;
|
||||||
checkOut(attendanceId: string): Promise<Attendance | null>;
|
checkOut(attendanceId: string): Promise<Attendance | null>;
|
||||||
getAttendanceHistory(clientId: string): Promise<Attendance[]>;
|
getAttendanceHistory(userId: string): Promise<Attendance[]>;
|
||||||
getAllAttendance(): Promise<Attendance[]>;
|
getAllAttendance(): Promise<Attendance[]>;
|
||||||
getActiveCheckIn(clientId: string): Promise<Attendance | null>;
|
getActiveCheckIn(userId: string): Promise<Attendance | null>;
|
||||||
|
|
||||||
// Recommendation operations
|
// Recommendation operations
|
||||||
createRecommendation(
|
createRecommendation(
|
||||||
recommendation: Omit<Recommendation, "createdAt" | "approvedAt" | "approvedBy">,
|
recommendation: Omit<
|
||||||
|
Recommendation,
|
||||||
|
"createdAt" | "approvedAt" | "approvedBy"
|
||||||
|
>,
|
||||||
): Promise<Recommendation>;
|
): Promise<Recommendation>;
|
||||||
getRecommendationsByUserId(userId: string): Promise<Recommendation[]>;
|
getRecommendationsByUserId(userId: string): Promise<Recommendation[]>;
|
||||||
getAllRecommendations(): Promise<Recommendation[]>;
|
getAllRecommendations(): Promise<Recommendation[]>;
|
||||||
@@ -144,16 +81,22 @@ export interface IDatabase {
|
|||||||
|
|
||||||
// Fitness Goals operations
|
// Fitness Goals operations
|
||||||
createFitnessGoal(
|
createFitnessGoal(
|
||||||
goal: Omit<FitnessGoal, "createdAt" | "updatedAt">
|
goal: Omit<FitnessGoal, "createdAt" | "updatedAt">,
|
||||||
): Promise<FitnessGoal>;
|
): Promise<FitnessGoal>;
|
||||||
getFitnessGoalById(id: string): Promise<FitnessGoal | null>;
|
getFitnessGoalById(id: string): Promise<FitnessGoal | null>;
|
||||||
getFitnessGoalsByUserId(userId: string, status?: string): Promise<FitnessGoal[]>;
|
getFitnessGoalsByUserId(
|
||||||
|
userId: string,
|
||||||
|
status?: string,
|
||||||
|
): Promise<FitnessGoal[]>;
|
||||||
updateFitnessGoal(
|
updateFitnessGoal(
|
||||||
id: string,
|
id: string,
|
||||||
updates: Partial<FitnessGoal>
|
updates: Partial<FitnessGoal>,
|
||||||
): Promise<FitnessGoal | null>;
|
): Promise<FitnessGoal | null>;
|
||||||
deleteFitnessGoal(id: string): Promise<boolean>;
|
deleteFitnessGoal(id: string): Promise<boolean>;
|
||||||
updateGoalProgress(id: string, currentValue: number): Promise<FitnessGoal | null>;
|
updateGoalProgress(
|
||||||
|
id: string,
|
||||||
|
currentValue: number,
|
||||||
|
): Promise<FitnessGoal | null>;
|
||||||
completeGoal(id: string): Promise<FitnessGoal | null>;
|
completeGoal(id: string): Promise<FitnessGoal | null>;
|
||||||
|
|
||||||
// Dashboard operations
|
// Dashboard operations
|
||||||
|
|||||||
@@ -1,62 +1,72 @@
|
|||||||
import { currentUser } from '@clerk/nextjs/server'
|
import { currentUser } from "@clerk/nextjs/server";
|
||||||
import { IDatabase } from './database/types'
|
import type { IDatabase, User } from "./database/types";
|
||||||
|
|
||||||
export async function ensureUserSynced(userId: string, db: IDatabase) {
|
export async function ensureUserSynced(
|
||||||
const existingUser = await db.getUserById(userId)
|
userId: string,
|
||||||
if (existingUser) return existingUser
|
db: IDatabase,
|
||||||
|
): Promise<User | null> {
|
||||||
|
const existingUser = await db.getUserById(userId);
|
||||||
|
if (existingUser) return existingUser;
|
||||||
|
|
||||||
console.log('User not found in DB by ID, checking Clerk:', userId)
|
console.log("User not found in DB by ID, checking Clerk:", userId);
|
||||||
const clerkUser = await currentUser()
|
const clerkUser = await currentUser();
|
||||||
|
|
||||||
if (!clerkUser || clerkUser.id !== userId) {
|
if (!clerkUser || clerkUser.id !== userId) {
|
||||||
// If we can't get the user from Clerk (e.g. running locally without full auth sync),
|
// If we can't get the user from Clerk (e.g. running locally without full auth sync),
|
||||||
// we might want to fail gracefully or throw.
|
// we might want to fail gracefully or throw.
|
||||||
// For now, throw to be safe.
|
// For now, throw to be safe.
|
||||||
throw new Error('Could not fetch Clerk user details')
|
throw new Error("Could not fetch Clerk user details");
|
||||||
}
|
}
|
||||||
|
|
||||||
const email = clerkUser.emailAddresses[0]?.emailAddress
|
const email = clerkUser.emailAddresses[0]?.emailAddress;
|
||||||
if (!email) throw new Error('User has no email')
|
if (!email) throw new Error("User has no email");
|
||||||
|
|
||||||
// Check if user exists by email (e.g. seeded user)
|
// Check if user exists by email (e.g. seeded user)
|
||||||
const existingByEmail = await db.getUserByEmail(email)
|
const existingByEmail = await db.getUserByEmail(email);
|
||||||
if (existingByEmail) {
|
if (existingByEmail) {
|
||||||
console.log('User found by email but ID mismatch. Migrating ID...', {
|
console.log("User found by email but ID mismatch. Migrating ID...", {
|
||||||
oldId: existingByEmail.id,
|
oldId: existingByEmail.id,
|
||||||
newId: userId
|
newId: userId,
|
||||||
})
|
});
|
||||||
|
|
||||||
// Update the ID to match Clerk ID
|
// Update the ID to match Clerk ID
|
||||||
// We need to do this manually via SQL because IDatabase interface might not expose a direct ID update method easily
|
// We need to do this manually via SQL because IDatabase interface might not expose a direct ID update method easily
|
||||||
// But we can use a raw query if we had access, or add a method.
|
// But we can use a raw query if we had access, or add a method.
|
||||||
// Since we don't have direct access to `db.db` here (it's hidden behind IDatabase),
|
// Since we don't have direct access to `db.db` here (it's hidden behind IDatabase),
|
||||||
// we should add a method to IDatabase or use a workaround.
|
// we should add a method to IDatabase or use a workaround.
|
||||||
// Actually, `SQLiteDatabase` is what we have at runtime.
|
// Actually, `SQLiteDatabase` is what we have at runtime.
|
||||||
// Let's assume we can cast it or add `updateUserId` to the interface.
|
// Let's assume we can cast it or add `updateUserId` to the interface.
|
||||||
|
|
||||||
// For now, let's try to update it using `updateUser` but `updateUser` usually updates fields based on ID.
|
// For now, let's try to update it using `updateUser` but `updateUser` usually updates fields based on ID.
|
||||||
// We can't update the ID itself using `updateUser(id, { id: newId })` because `updateUser` implementation filters out `id` from updates.
|
// We can't update the ID itself using `updateUser(id, { id: newId })` because `updateUser` implementation filters out `id` from updates.
|
||||||
|
|
||||||
// We need to add a method to migrate user ID in IDatabase.
|
// We need to add a method to migrate user ID in IDatabase.
|
||||||
// Or, strictly for this prototype, we can delete the old user and create a new one (DATA LOSS RISK).
|
// Or, strictly for this prototype, we can delete the old user and create a new one (DATA LOSS RISK).
|
||||||
// But since it's a seeded super admin with no data, it's fine.
|
// But since it's a seeded super admin with no data, it's fine.
|
||||||
// However, if they had clients, we'd lose the link.
|
// However, if they had clients, we'd lose the link.
|
||||||
|
|
||||||
// Let's add `migrateUserId(oldId, newId)` to IDatabase.
|
// Let's add `migrateUserId(oldId, newId)` to IDatabase.
|
||||||
await db.migrateUserId(existingByEmail.id, userId)
|
await db.migrateUserId(existingByEmail.id, userId);
|
||||||
return db.getUserById(userId)
|
return db.getUserById(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Creating new user from Clerk data:', userId)
|
console.log("Creating new user from Clerk data:", userId);
|
||||||
const user = await db.createUser({
|
const user = await db.createUser({
|
||||||
id: userId,
|
id: userId,
|
||||||
email,
|
email,
|
||||||
firstName: clerkUser.firstName || '',
|
firstName: clerkUser.firstName || "",
|
||||||
lastName: clerkUser.lastName || '',
|
lastName: clerkUser.lastName || "",
|
||||||
password: '', // Managed by Clerk
|
password: "", // Managed by Clerk
|
||||||
phone: clerkUser.phoneNumbers[0]?.phoneNumber || undefined,
|
phone: clerkUser.phoneNumbers[0]?.phoneNumber || undefined,
|
||||||
role: (clerkUser.publicMetadata.role as 'admin' | 'client' | 'superAdmin') || 'client'
|
gymId: (clerkUser.publicMetadata.gymId as string | undefined) || undefined,
|
||||||
})
|
role: ((): any => {
|
||||||
|
const r = clerkUser.publicMetadata.role as string | undefined;
|
||||||
|
return r &&
|
||||||
|
["superAdmin", "admin", "trainer", "client", "generalUser"].includes(r)
|
||||||
|
? r
|
||||||
|
: "client";
|
||||||
|
})(),
|
||||||
|
});
|
||||||
|
|
||||||
return user
|
return user;
|
||||||
}
|
}
|
||||||
@@ -1,14 +1 @@
|
|||||||
import { type ClassValue, clsx } from "clsx"
|
export { cn, formatDate } from "@fitai/shared"
|
||||||
import { twMerge } from "tailwind-merge"
|
|
||||||
|
|
||||||
export function cn(...inputs: ClassValue[]) {
|
|
||||||
return twMerge(clsx(inputs))
|
|
||||||
}
|
|
||||||
|
|
||||||
export function formatDate(date: string | Date) {
|
|
||||||
return new Date(date).toLocaleDateString("en-US", {
|
|
||||||
month: "long",
|
|
||||||
day: "numeric",
|
|
||||||
year: "numeric",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
# OSX
|
|
||||||
#
|
|
||||||
.DS_Store
|
|
||||||
|
|
||||||
# Android/IntelliJ
|
|
||||||
#
|
|
||||||
build/
|
|
||||||
.idea
|
|
||||||
.gradle
|
|
||||||
local.properties
|
|
||||||
*.iml
|
|
||||||
*.hprof
|
|
||||||
.cxx/
|
|
||||||
|
|
||||||
# Bundle artifacts
|
|
||||||
*.jsbundle
|
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# Values used to calculate the hash in this folder name.
|
||||||
|
# Should not depend on the absolute path of the project itself.
|
||||||
|
# - AGP: 8.11.0.
|
||||||
|
# - $NDK is the path to NDK 27.1.12297006.
|
||||||
|
# - $PROJECT is the path to the parent folder of the root Gradle build file.
|
||||||
|
# - $ABI is the ABI to be built with. The specific value doesn't contribute to the value of the hash.
|
||||||
|
# - $HASH is the hash value computed from this text.
|
||||||
|
# - $CMAKE is the path to CMake 3.22.1.
|
||||||
|
# - $NINJA is the path to Ninja.
|
||||||
|
-H/home/echo/dev/prototype/apps/mobile/node_modules/react-native/ReactAndroid/cmake-utils/default-app-setup
|
||||||
|
-DCMAKE_SYSTEM_NAME=Android
|
||||||
|
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
||||||
|
-DCMAKE_SYSTEM_VERSION=26
|
||||||
|
-DANDROID_PLATFORM=android-26
|
||||||
|
-DANDROID_ABI=$ABI
|
||||||
|
-DCMAKE_ANDROID_ARCH_ABI=$ABI
|
||||||
|
-DANDROID_NDK=$NDK
|
||||||
|
-DCMAKE_ANDROID_NDK=$NDK
|
||||||
|
-DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake
|
||||||
|
-DCMAKE_MAKE_PROGRAM=$NINJA
|
||||||
|
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=$PROJECT/app/build/intermediates/cxx/Debug/$HASH/obj/$ABI
|
||||||
|
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=$PROJECT/app/build/intermediates/cxx/Debug/$HASH/obj/$ABI
|
||||||
|
-DCMAKE_BUILD_TYPE=Debug
|
||||||
|
-DCMAKE_FIND_ROOT_PATH=$PROJECT/app/.cxx/Debug/$HASH/prefab/$ABI/prefab
|
||||||
|
-B$PROJECT/app/.cxx/Debug/$HASH/$ABI
|
||||||
|
-GNinja
|
||||||
|
-DPROJECT_BUILD_DIR=$PROJECT/app/build
|
||||||
|
-DPROJECT_ROOT_DIR=$PROJECT
|
||||||
|
-DREACT_ANDROID_DIR=/home/echo/dev/prototype/apps/mobile/node_modules/react-native/ReactAndroid
|
||||||
|
-DANDROID_STL=c++_shared
|
||||||
|
-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
if(NOT TARGET ReactAndroid::hermestooling)
|
||||||
|
add_library(ReactAndroid::hermestooling SHARED IMPORTED)
|
||||||
|
set_target_properties(ReactAndroid::hermestooling PROPERTIES
|
||||||
|
IMPORTED_LOCATION "/home/echo/.gradle/caches/8.14.3/transforms/e5d515112484fe4dddc05785469cc380/transformed/react-android-0.81.5-debug/prefab/modules/hermestooling/libs/android.x86/libhermestooling.so"
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "/home/echo/.gradle/caches/8.14.3/transforms/e5d515112484fe4dddc05785469cc380/transformed/react-android-0.81.5-debug/prefab/modules/hermestooling/include"
|
||||||
|
INTERFACE_LINK_LIBRARIES ""
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT TARGET ReactAndroid::jsi)
|
||||||
|
add_library(ReactAndroid::jsi SHARED IMPORTED)
|
||||||
|
set_target_properties(ReactAndroid::jsi PROPERTIES
|
||||||
|
IMPORTED_LOCATION "/home/echo/.gradle/caches/8.14.3/transforms/e5d515112484fe4dddc05785469cc380/transformed/react-android-0.81.5-debug/prefab/modules/jsi/libs/android.x86/libjsi.so"
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "/home/echo/.gradle/caches/8.14.3/transforms/e5d515112484fe4dddc05785469cc380/transformed/react-android-0.81.5-debug/prefab/modules/jsi/include"
|
||||||
|
INTERFACE_LINK_LIBRARIES ""
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT TARGET ReactAndroid::reactnative)
|
||||||
|
add_library(ReactAndroid::reactnative SHARED IMPORTED)
|
||||||
|
set_target_properties(ReactAndroid::reactnative PROPERTIES
|
||||||
|
IMPORTED_LOCATION "/home/echo/.gradle/caches/8.14.3/transforms/e5d515112484fe4dddc05785469cc380/transformed/react-android-0.81.5-debug/prefab/modules/reactnative/libs/android.x86/libreactnative.so"
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "/home/echo/.gradle/caches/8.14.3/transforms/e5d515112484fe4dddc05785469cc380/transformed/react-android-0.81.5-debug/prefab/modules/reactnative/include"
|
||||||
|
INTERFACE_LINK_LIBRARIES ""
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
set(PACKAGE_VERSION 0.81.5)
|
||||||
|
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
|
||||||
|
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
||||||
|
else()
|
||||||
|
set(PACKAGE_VERSION_COMPATIBLE TRUE)
|
||||||
|
if("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
|
||||||
|
set(PACKAGE_VERSION_EXACT TRUE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
if(NOT TARGET fbjni::fbjni)
|
||||||
|
add_library(fbjni::fbjni SHARED IMPORTED)
|
||||||
|
set_target_properties(fbjni::fbjni PROPERTIES
|
||||||
|
IMPORTED_LOCATION "/home/echo/.gradle/caches/8.14.3/transforms/488fe6e480efb97ec75859f6e274282f/transformed/fbjni-0.7.0/prefab/modules/fbjni/libs/android.x86/libfbjni.so"
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "/home/echo/.gradle/caches/8.14.3/transforms/488fe6e480efb97ec75859f6e274282f/transformed/fbjni-0.7.0/prefab/modules/fbjni/include"
|
||||||
|
INTERFACE_LINK_LIBRARIES ""
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
set(PACKAGE_VERSION 3.22.1)
|
||||||
|
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
|
||||||
|
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
||||||
|
else()
|
||||||
|
set(PACKAGE_VERSION_COMPATIBLE TRUE)
|
||||||
|
if("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
|
||||||
|
set(PACKAGE_VERSION_EXACT TRUE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
if(NOT TARGET hermes-engine::libhermes)
|
||||||
|
add_library(hermes-engine::libhermes SHARED IMPORTED)
|
||||||
|
set_target_properties(hermes-engine::libhermes PROPERTIES
|
||||||
|
IMPORTED_LOCATION "/home/echo/.gradle/caches/8.14.3/transforms/f3d279cf13499f4c93e2b512ac9499e6/transformed/hermes-android-0.81.5-debug/prefab/modules/libhermes/libs/android.x86/libhermes.so"
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "/home/echo/.gradle/caches/8.14.3/transforms/f3d279cf13499f4c93e2b512ac9499e6/transformed/hermes-android-0.81.5-debug/prefab/modules/libhermes/include"
|
||||||
|
INTERFACE_LINK_LIBRARIES ""
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
set(PACKAGE_VERSION 0.81.5)
|
||||||
|
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
|
||||||
|
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
||||||
|
else()
|
||||||
|
set(PACKAGE_VERSION_COMPATIBLE TRUE)
|
||||||
|
if("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
|
||||||
|
set(PACKAGE_VERSION_EXACT TRUE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
if(NOT TARGET ReactAndroid::hermestooling)
|
||||||
|
add_library(ReactAndroid::hermestooling SHARED IMPORTED)
|
||||||
|
set_target_properties(ReactAndroid::hermestooling PROPERTIES
|
||||||
|
IMPORTED_LOCATION "/home/echo/.gradle/caches/8.14.3/transforms/e5d515112484fe4dddc05785469cc380/transformed/react-android-0.81.5-debug/prefab/modules/hermestooling/libs/android.x86_64/libhermestooling.so"
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "/home/echo/.gradle/caches/8.14.3/transforms/e5d515112484fe4dddc05785469cc380/transformed/react-android-0.81.5-debug/prefab/modules/hermestooling/include"
|
||||||
|
INTERFACE_LINK_LIBRARIES ""
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT TARGET ReactAndroid::jsi)
|
||||||
|
add_library(ReactAndroid::jsi SHARED IMPORTED)
|
||||||
|
set_target_properties(ReactAndroid::jsi PROPERTIES
|
||||||
|
IMPORTED_LOCATION "/home/echo/.gradle/caches/8.14.3/transforms/e5d515112484fe4dddc05785469cc380/transformed/react-android-0.81.5-debug/prefab/modules/jsi/libs/android.x86_64/libjsi.so"
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "/home/echo/.gradle/caches/8.14.3/transforms/e5d515112484fe4dddc05785469cc380/transformed/react-android-0.81.5-debug/prefab/modules/jsi/include"
|
||||||
|
INTERFACE_LINK_LIBRARIES ""
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT TARGET ReactAndroid::reactnative)
|
||||||
|
add_library(ReactAndroid::reactnative SHARED IMPORTED)
|
||||||
|
set_target_properties(ReactAndroid::reactnative PROPERTIES
|
||||||
|
IMPORTED_LOCATION "/home/echo/.gradle/caches/8.14.3/transforms/e5d515112484fe4dddc05785469cc380/transformed/react-android-0.81.5-debug/prefab/modules/reactnative/libs/android.x86_64/libreactnative.so"
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "/home/echo/.gradle/caches/8.14.3/transforms/e5d515112484fe4dddc05785469cc380/transformed/react-android-0.81.5-debug/prefab/modules/reactnative/include"
|
||||||
|
INTERFACE_LINK_LIBRARIES ""
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
set(PACKAGE_VERSION 0.81.5)
|
||||||
|
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
|
||||||
|
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
||||||
|
else()
|
||||||
|
set(PACKAGE_VERSION_COMPATIBLE TRUE)
|
||||||
|
if("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
|
||||||
|
set(PACKAGE_VERSION_EXACT TRUE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
if(NOT TARGET fbjni::fbjni)
|
||||||
|
add_library(fbjni::fbjni SHARED IMPORTED)
|
||||||
|
set_target_properties(fbjni::fbjni PROPERTIES
|
||||||
|
IMPORTED_LOCATION "/home/echo/.gradle/caches/8.14.3/transforms/488fe6e480efb97ec75859f6e274282f/transformed/fbjni-0.7.0/prefab/modules/fbjni/libs/android.x86_64/libfbjni.so"
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "/home/echo/.gradle/caches/8.14.3/transforms/488fe6e480efb97ec75859f6e274282f/transformed/fbjni-0.7.0/prefab/modules/fbjni/include"
|
||||||
|
INTERFACE_LINK_LIBRARIES ""
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
set(PACKAGE_VERSION 3.22.1)
|
||||||
|
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
|
||||||
|
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
||||||
|
else()
|
||||||
|
set(PACKAGE_VERSION_COMPATIBLE TRUE)
|
||||||
|
if("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
|
||||||
|
set(PACKAGE_VERSION_EXACT TRUE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
if(NOT TARGET hermes-engine::libhermes)
|
||||||
|
add_library(hermes-engine::libhermes SHARED IMPORTED)
|
||||||
|
set_target_properties(hermes-engine::libhermes PROPERTIES
|
||||||
|
IMPORTED_LOCATION "/home/echo/.gradle/caches/8.14.3/transforms/f3d279cf13499f4c93e2b512ac9499e6/transformed/hermes-android-0.81.5-debug/prefab/modules/libhermes/libs/android.x86_64/libhermes.so"
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "/home/echo/.gradle/caches/8.14.3/transforms/f3d279cf13499f4c93e2b512ac9499e6/transformed/hermes-android-0.81.5-debug/prefab/modules/libhermes/include"
|
||||||
|
INTERFACE_LINK_LIBRARIES ""
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
set(PACKAGE_VERSION 0.81.5)
|
||||||
|
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
|
||||||
|
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
||||||
|
else()
|
||||||
|
set(PACKAGE_VERSION_COMPATIBLE TRUE)
|
||||||
|
if("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
|
||||||
|
set(PACKAGE_VERSION_EXACT TRUE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
+1439
File diff suppressed because it is too large.
Load diff
+851
@@ -0,0 +1,851 @@
|
|||||||
|
{
|
||||||
|
"inputs" :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"path" : "CMakeLists.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/ndk/27.1.12297006/build/cmake/android.toolchain.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/ndk/27.1.12297006/build/cmake/android-legacy.toolchain.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/ndk/27.1.12297006/build/cmake/abis.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/ndk/27.1.12297006/build/cmake/platforms.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/ndk/27.1.12297006/build/cmake/hooks/pre/Android-Determine.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isGenerated" : true,
|
||||||
|
"path" : "/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/ndk/27.1.12297006/build/cmake/android.toolchain.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/ndk/27.1.12297006/build/cmake/hooks/pre/Android-Initialize.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/ndk/27.1.12297006/build/cmake/hooks/pre/Determine-Compiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isGenerated" : true,
|
||||||
|
"path" : "/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-CXX.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isGenerated" : true,
|
||||||
|
"path" : "/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/ndk/27.1.12297006/build/cmake/hooks/pre/Android.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/ndk/27.1.12297006/build/cmake/hooks/pre/Android-Clang.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/ndk/27.1.12297006/build/cmake/flags.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isGenerated" : true,
|
||||||
|
"path" : "/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXInformation.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-CXX.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-CXX.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isGenerated" : true,
|
||||||
|
"path" : "/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/x86/CMakeFiles/3.22.1-g37088a8/CMakeCXXCompiler.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/dev/prototype/apps/mobile/node_modules/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/dev/prototype/apps/mobile/node_modules/react-native/ReactAndroid/cmake-utils/folly-flags.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/dev/prototype/apps/mobile/node_modules/react-native/ReactCommon/cmake-utils/react-native-flags.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CheckIPOSupported.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CheckIPOSupported/CMakeLists-CXX.txt.in"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CheckIPOSupported/foo.cpp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isCMake" : true,
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CheckIPOSupported/main.cpp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/prefab/x86/prefab/lib/i686-linux-android/cmake/ReactAndroid/ReactAndroidConfigVersion.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/prefab/x86/prefab/lib/i686-linux-android/cmake/ReactAndroid/ReactAndroidConfig.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/prefab/x86/prefab/lib/i686-linux-android/cmake/fbjni/fbjniConfigVersion.cmake"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isExternal" : true,
|
||||||
|
"path" : "/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/prefab/x86/prefab/lib/i686-linux-android/cmake/fbjni/fbjniConfig.cmake"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind" : "cmakeFiles",
|
||||||
|
"paths" :
|
||||||
|
{
|
||||||
|
"build" : "/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/x86",
|
||||||
|
"source" : "/home/echo/dev/prototype/apps/mobile/node_modules/react-native/ReactAndroid/cmake-utils/default-app-setup"
|
||||||
|
},
|
||||||
|
"version" :
|
||||||
|
{
|
||||||
|
"major" : 1,
|
||||||
|
"minor" : 0
|
||||||
|
}
|
||||||
|
}
|
||||||
+60
@@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"configurations" :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"directories" :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"build" : ".",
|
||||||
|
"jsonFile" : "directory-.-Debug-f5ebdc15457944623624.json",
|
||||||
|
"minimumCMakeVersion" :
|
||||||
|
{
|
||||||
|
"string" : "3.13"
|
||||||
|
},
|
||||||
|
"projectIndex" : 0,
|
||||||
|
"source" : ".",
|
||||||
|
"targetIndexes" :
|
||||||
|
[
|
||||||
|
0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name" : "Debug",
|
||||||
|
"projects" :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"directoryIndexes" :
|
||||||
|
[
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"name" : "appmodules",
|
||||||
|
"targetIndexes" :
|
||||||
|
[
|
||||||
|
0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"targets" :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"directoryIndex" : 0,
|
||||||
|
"id" : "appmodules::@6890427a1f51a3e7e1df",
|
||||||
|
"jsonFile" : "target-appmodules-Debug-9ef032710fe355da9383.json",
|
||||||
|
"name" : "appmodules",
|
||||||
|
"projectIndex" : 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind" : "codemodel",
|
||||||
|
"paths" :
|
||||||
|
{
|
||||||
|
"build" : "/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/x86",
|
||||||
|
"source" : "/home/echo/dev/prototype/apps/mobile/node_modules/react-native/ReactAndroid/cmake-utils/default-app-setup"
|
||||||
|
},
|
||||||
|
"version" :
|
||||||
|
{
|
||||||
|
"major" : 2,
|
||||||
|
"minor" : 3
|
||||||
|
}
|
||||||
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"backtraceGraph" :
|
||||||
|
{
|
||||||
|
"commands" : [],
|
||||||
|
"files" : [],
|
||||||
|
"nodes" : []
|
||||||
|
},
|
||||||
|
"installers" : [],
|
||||||
|
"paths" :
|
||||||
|
{
|
||||||
|
"build" : ".",
|
||||||
|
"source" : "."
|
||||||
|
}
|
||||||
|
}
|
||||||
+92
@@ -0,0 +1,92 @@
|
|||||||
|
{
|
||||||
|
"cmake" :
|
||||||
|
{
|
||||||
|
"generator" :
|
||||||
|
{
|
||||||
|
"multiConfig" : false,
|
||||||
|
"name" : "Ninja"
|
||||||
|
},
|
||||||
|
"paths" :
|
||||||
|
{
|
||||||
|
"cmake" : "/home/echo/Android/Sdk/cmake/3.22.1/bin/cmake",
|
||||||
|
"cpack" : "/home/echo/Android/Sdk/cmake/3.22.1/bin/cpack",
|
||||||
|
"ctest" : "/home/echo/Android/Sdk/cmake/3.22.1/bin/ctest",
|
||||||
|
"root" : "/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22"
|
||||||
|
},
|
||||||
|
"version" :
|
||||||
|
{
|
||||||
|
"isDirty" : false,
|
||||||
|
"major" : 3,
|
||||||
|
"minor" : 22,
|
||||||
|
"patch" : 1,
|
||||||
|
"string" : "3.22.1-g37088a8",
|
||||||
|
"suffix" : "g37088a8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"objects" :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"jsonFile" : "codemodel-v2-d483cb7bfe026ad3a64f.json",
|
||||||
|
"kind" : "codemodel",
|
||||||
|
"version" :
|
||||||
|
{
|
||||||
|
"major" : 2,
|
||||||
|
"minor" : 3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"jsonFile" : "cache-v2-099ee692bdea7ed85643.json",
|
||||||
|
"kind" : "cache",
|
||||||
|
"version" :
|
||||||
|
{
|
||||||
|
"major" : 2,
|
||||||
|
"minor" : 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"jsonFile" : "cmakeFiles-v1-b99aeefcc68e41c89ebf.json",
|
||||||
|
"kind" : "cmakeFiles",
|
||||||
|
"version" :
|
||||||
|
{
|
||||||
|
"major" : 1,
|
||||||
|
"minor" : 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"reply" :
|
||||||
|
{
|
||||||
|
"client-agp" :
|
||||||
|
{
|
||||||
|
"cache-v2" :
|
||||||
|
{
|
||||||
|
"jsonFile" : "cache-v2-099ee692bdea7ed85643.json",
|
||||||
|
"kind" : "cache",
|
||||||
|
"version" :
|
||||||
|
{
|
||||||
|
"major" : 2,
|
||||||
|
"minor" : 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cmakeFiles-v1" :
|
||||||
|
{
|
||||||
|
"jsonFile" : "cmakeFiles-v1-b99aeefcc68e41c89ebf.json",
|
||||||
|
"kind" : "cmakeFiles",
|
||||||
|
"version" :
|
||||||
|
{
|
||||||
|
"major" : 1,
|
||||||
|
"minor" : 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"codemodel-v2" :
|
||||||
|
{
|
||||||
|
"jsonFile" : "codemodel-v2-d483cb7bfe026ad3a64f.json",
|
||||||
|
"kind" : "codemodel",
|
||||||
|
"version" :
|
||||||
|
{
|
||||||
|
"major" : 2,
|
||||||
|
"minor" : 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+226
@@ -0,0 +1,226 @@
|
|||||||
|
{
|
||||||
|
"artifacts" :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"path" : "/home/echo/dev/prototype/apps/mobile/android/app/build/intermediates/cxx/Debug/2z472e3c/obj/x86/libappmodules.so"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"backtrace" : 3,
|
||||||
|
"backtraceGraph" :
|
||||||
|
{
|
||||||
|
"commands" :
|
||||||
|
[
|
||||||
|
"add_library",
|
||||||
|
"include",
|
||||||
|
"target_link_libraries",
|
||||||
|
"target_compile_options",
|
||||||
|
"target_compile_reactnative_options",
|
||||||
|
"target_compile_definitions",
|
||||||
|
"target_include_directories"
|
||||||
|
],
|
||||||
|
"files" :
|
||||||
|
[
|
||||||
|
"/home/echo/dev/prototype/apps/mobile/node_modules/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake",
|
||||||
|
"CMakeLists.txt",
|
||||||
|
"/home/echo/dev/prototype/apps/mobile/node_modules/react-native/ReactCommon/cmake-utils/react-native-flags.cmake"
|
||||||
|
],
|
||||||
|
"nodes" :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"file" : 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command" : 1,
|
||||||
|
"file" : 1,
|
||||||
|
"line" : 31,
|
||||||
|
"parent" : 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file" : 0,
|
||||||
|
"parent" : 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command" : 0,
|
||||||
|
"file" : 0,
|
||||||
|
"line" : 64,
|
||||||
|
"parent" : 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command" : 2,
|
||||||
|
"file" : 0,
|
||||||
|
"line" : 81,
|
||||||
|
"parent" : 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command" : 4,
|
||||||
|
"file" : 0,
|
||||||
|
"line" : 71,
|
||||||
|
"parent" : 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command" : 3,
|
||||||
|
"file" : 2,
|
||||||
|
"line" : 30,
|
||||||
|
"parent" : 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command" : 5,
|
||||||
|
"file" : 2,
|
||||||
|
"line" : 33,
|
||||||
|
"parent" : 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command" : 6,
|
||||||
|
"file" : 0,
|
||||||
|
"line" : 66,
|
||||||
|
"parent" : 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"compileGroups" :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"compileCommandFragments" :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"fragment" : "-g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D__BIONIC_NO_PAGE_SIZE_MACRO -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -fno-limit-debug-info -fPIC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace" : 6,
|
||||||
|
"fragment" : "-Wall"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace" : 6,
|
||||||
|
"fragment" : "-Werror"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace" : 6,
|
||||||
|
"fragment" : "-fexceptions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace" : 6,
|
||||||
|
"fragment" : "-frtti"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace" : 6,
|
||||||
|
"fragment" : "-std=c++20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace" : 6,
|
||||||
|
"fragment" : "-DFOLLY_NO_CONFIG=1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace" : 6,
|
||||||
|
"fragment" : "-DLOG_TAG=\\\"ReactNative\\\""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"defines" :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"backtrace" : 7,
|
||||||
|
"define" : "RN_SERIALIZABLE_STATE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"define" : "appmodules_EXPORTS"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"includes" :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"backtrace" : 8,
|
||||||
|
"path" : "/home/echo/dev/prototype/apps/mobile/node_modules/react-native/ReactAndroid/cmake-utils/default-app-setup"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace" : 8,
|
||||||
|
"path" : "/home/echo/dev/prototype/apps/mobile/android/app/build/generated/autolinking/src/main/jni"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace" : 4,
|
||||||
|
"isSystem" : true,
|
||||||
|
"path" : "/home/echo/.gradle/caches/8.14.3/transforms/488fe6e480efb97ec75859f6e274282f/transformed/fbjni-0.7.0/prefab/modules/fbjni/include"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace" : 4,
|
||||||
|
"isSystem" : true,
|
||||||
|
"path" : "/home/echo/.gradle/caches/8.14.3/transforms/e5d515112484fe4dddc05785469cc380/transformed/react-android-0.81.5-debug/prefab/modules/jsi/include"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace" : 4,
|
||||||
|
"isSystem" : true,
|
||||||
|
"path" : "/home/echo/.gradle/caches/8.14.3/transforms/e5d515112484fe4dddc05785469cc380/transformed/react-android-0.81.5-debug/prefab/modules/reactnative/include"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"language" : "CXX",
|
||||||
|
"sourceIndexes" :
|
||||||
|
[
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"sysroot" :
|
||||||
|
{
|
||||||
|
"path" : "/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/sysroot"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id" : "appmodules::@6890427a1f51a3e7e1df",
|
||||||
|
"link" :
|
||||||
|
{
|
||||||
|
"commandFragments" :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"fragment" : "-Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--no-undefined-version -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments",
|
||||||
|
"role" : "flags"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace" : 4,
|
||||||
|
"fragment" : "/home/echo/.gradle/caches/8.14.3/transforms/488fe6e480efb97ec75859f6e274282f/transformed/fbjni-0.7.0/prefab/modules/fbjni/libs/android.x86/libfbjni.so",
|
||||||
|
"role" : "libraries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace" : 4,
|
||||||
|
"fragment" : "/home/echo/.gradle/caches/8.14.3/transforms/e5d515112484fe4dddc05785469cc380/transformed/react-android-0.81.5-debug/prefab/modules/jsi/libs/android.x86/libjsi.so",
|
||||||
|
"role" : "libraries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"backtrace" : 4,
|
||||||
|
"fragment" : "/home/echo/.gradle/caches/8.14.3/transforms/e5d515112484fe4dddc05785469cc380/transformed/react-android-0.81.5-debug/prefab/modules/reactnative/libs/android.x86/libreactnative.so",
|
||||||
|
"role" : "libraries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fragment" : "-latomic -lm",
|
||||||
|
"role" : "libraries"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"language" : "CXX",
|
||||||
|
"sysroot" :
|
||||||
|
{
|
||||||
|
"path" : "/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/sysroot"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name" : "appmodules",
|
||||||
|
"nameOnDisk" : "libappmodules.so",
|
||||||
|
"paths" :
|
||||||
|
{
|
||||||
|
"build" : ".",
|
||||||
|
"source" : "."
|
||||||
|
},
|
||||||
|
"sourceGroups" :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name" : "Source Files",
|
||||||
|
"sourceIndexes" :
|
||||||
|
[
|
||||||
|
0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sources" :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"backtrace" : 3,
|
||||||
|
"compileGroupIndex" : 0,
|
||||||
|
"path" : "OnLoad.cpp",
|
||||||
|
"sourceGroupIndex" : 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type" : "SHARED_LIBRARY"
|
||||||
|
}
|
||||||
@@ -0,0 +1,420 @@
|
|||||||
|
# This is the CMakeCache file.
|
||||||
|
# For build in directory: /home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/x86
|
||||||
|
# It was generated by CMake: /home/echo/Android/Sdk/cmake/3.22.1/bin/cmake
|
||||||
|
# You can edit this file to change values found and used by cmake.
|
||||||
|
# If you do not want to change any of the values, simply exit the editor.
|
||||||
|
# If you do want to change a value, simply edit, save, and exit the editor.
|
||||||
|
# The syntax for the file is as follows:
|
||||||
|
# KEY:TYPE=VALUE
|
||||||
|
# KEY is the name of a variable in the cache.
|
||||||
|
# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!.
|
||||||
|
# VALUE is the current value for the KEY.
|
||||||
|
|
||||||
|
########################
|
||||||
|
# EXTERNAL cache entries
|
||||||
|
########################
|
||||||
|
|
||||||
|
//No help, variable specified on the command line.
|
||||||
|
ANDROID_ABI:UNINITIALIZED=x86
|
||||||
|
|
||||||
|
//No help, variable specified on the command line.
|
||||||
|
ANDROID_NDK:UNINITIALIZED=/home/echo/Android/Sdk/ndk/27.1.12297006
|
||||||
|
|
||||||
|
//No help, variable specified on the command line.
|
||||||
|
ANDROID_PLATFORM:UNINITIALIZED=android-26
|
||||||
|
|
||||||
|
//No help, variable specified on the command line.
|
||||||
|
ANDROID_STL:UNINITIALIZED=c++_shared
|
||||||
|
|
||||||
|
//No help, variable specified on the command line.
|
||||||
|
ANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES:UNINITIALIZED=ON
|
||||||
|
|
||||||
|
//Path to a program.
|
||||||
|
CCACHE_FOUND:FILEPATH=CCACHE_FOUND-NOTFOUND
|
||||||
|
|
||||||
|
//Path to a program.
|
||||||
|
CMAKE_ADDR2LINE:FILEPATH=/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-addr2line
|
||||||
|
|
||||||
|
//No help, variable specified on the command line.
|
||||||
|
CMAKE_ANDROID_ARCH_ABI:UNINITIALIZED=x86
|
||||||
|
|
||||||
|
//No help, variable specified on the command line.
|
||||||
|
CMAKE_ANDROID_NDK:UNINITIALIZED=/home/echo/Android/Sdk/ndk/27.1.12297006
|
||||||
|
|
||||||
|
//Archiver
|
||||||
|
CMAKE_AR:FILEPATH=/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar
|
||||||
|
|
||||||
|
//Flags used by the compiler during all build types.
|
||||||
|
CMAKE_ASM_FLAGS:STRING=
|
||||||
|
|
||||||
|
//Flags used by the compiler during debug builds.
|
||||||
|
CMAKE_ASM_FLAGS_DEBUG:STRING=
|
||||||
|
|
||||||
|
//Flags used by the compiler during release builds.
|
||||||
|
CMAKE_ASM_FLAGS_RELEASE:STRING=
|
||||||
|
|
||||||
|
//Choose the type of build, options are: None Debug Release RelWithDebInfo
|
||||||
|
// MinSizeRel ...
|
||||||
|
CMAKE_BUILD_TYPE:STRING=Debug
|
||||||
|
|
||||||
|
//LLVM archiver
|
||||||
|
CMAKE_CXX_COMPILER_AR:FILEPATH=/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar
|
||||||
|
|
||||||
|
//Generate index for LLVM archive
|
||||||
|
CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib
|
||||||
|
|
||||||
|
//Flags used by the compiler during all build types.
|
||||||
|
CMAKE_CXX_FLAGS:STRING=
|
||||||
|
|
||||||
|
//Flags used by the compiler during debug builds.
|
||||||
|
CMAKE_CXX_FLAGS_DEBUG:STRING=
|
||||||
|
|
||||||
|
//Flags used by the CXX compiler during MINSIZEREL builds.
|
||||||
|
CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
|
||||||
|
|
||||||
|
//Flags used by the compiler during release builds.
|
||||||
|
CMAKE_CXX_FLAGS_RELEASE:STRING=
|
||||||
|
|
||||||
|
//Flags used by the CXX compiler during RELWITHDEBINFO builds.
|
||||||
|
CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
|
||||||
|
|
||||||
|
//Libraries linked by default with all C++ applications.
|
||||||
|
CMAKE_CXX_STANDARD_LIBRARIES:STRING=-latomic -lm
|
||||||
|
|
||||||
|
//LLVM archiver
|
||||||
|
CMAKE_C_COMPILER_AR:FILEPATH=/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar
|
||||||
|
|
||||||
|
//Generate index for LLVM archive
|
||||||
|
CMAKE_C_COMPILER_RANLIB:FILEPATH=/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib
|
||||||
|
|
||||||
|
//Flags used by the compiler during all build types.
|
||||||
|
CMAKE_C_FLAGS:STRING=
|
||||||
|
|
||||||
|
//Flags used by the compiler during debug builds.
|
||||||
|
CMAKE_C_FLAGS_DEBUG:STRING=
|
||||||
|
|
||||||
|
//Flags used by the C compiler during MINSIZEREL builds.
|
||||||
|
CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
|
||||||
|
|
||||||
|
//Flags used by the compiler during release builds.
|
||||||
|
CMAKE_C_FLAGS_RELEASE:STRING=
|
||||||
|
|
||||||
|
//Flags used by the C compiler during RELWITHDEBINFO builds.
|
||||||
|
CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
|
||||||
|
|
||||||
|
//Libraries linked by default with all C applications.
|
||||||
|
CMAKE_C_STANDARD_LIBRARIES:STRING=-latomic -lm
|
||||||
|
|
||||||
|
//Path to a program.
|
||||||
|
CMAKE_DLLTOOL:FILEPATH=/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-dlltool
|
||||||
|
|
||||||
|
//Flags used by the linker.
|
||||||
|
CMAKE_EXE_LINKER_FLAGS:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during DEBUG builds.
|
||||||
|
CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during MINSIZEREL builds.
|
||||||
|
CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during RELEASE builds.
|
||||||
|
CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during RELWITHDEBINFO builds.
|
||||||
|
CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING=
|
||||||
|
|
||||||
|
//No help, variable specified on the command line.
|
||||||
|
CMAKE_EXPORT_COMPILE_COMMANDS:UNINITIALIZED=ON
|
||||||
|
|
||||||
|
//No help, variable specified on the command line.
|
||||||
|
CMAKE_FIND_ROOT_PATH:UNINITIALIZED=/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/prefab/x86/prefab
|
||||||
|
|
||||||
|
//Install path prefix, prepended onto install directories.
|
||||||
|
CMAKE_INSTALL_PREFIX:PATH=/usr/local
|
||||||
|
|
||||||
|
//No help, variable specified on the command line.
|
||||||
|
CMAKE_LIBRARY_OUTPUT_DIRECTORY:UNINITIALIZED=/home/echo/dev/prototype/apps/mobile/android/app/build/intermediates/cxx/Debug/2z472e3c/obj/x86
|
||||||
|
|
||||||
|
//Path to a program.
|
||||||
|
CMAKE_LINKER:FILEPATH=/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/ld.lld
|
||||||
|
|
||||||
|
//No help, variable specified on the command line.
|
||||||
|
CMAKE_MAKE_PROGRAM:UNINITIALIZED=/home/echo/Android/Sdk/cmake/3.22.1/bin/ninja
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of modules.
|
||||||
|
CMAKE_MODULE_LINKER_FLAGS:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of modules during
|
||||||
|
// DEBUG builds.
|
||||||
|
CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of modules during
|
||||||
|
// MINSIZEREL builds.
|
||||||
|
CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of modules during
|
||||||
|
// RELEASE builds.
|
||||||
|
CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of modules during
|
||||||
|
// RELWITHDEBINFO builds.
|
||||||
|
CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING=
|
||||||
|
|
||||||
|
//Path to a program.
|
||||||
|
CMAKE_NM:FILEPATH=/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-nm
|
||||||
|
|
||||||
|
//Path to a program.
|
||||||
|
CMAKE_OBJCOPY:FILEPATH=/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-objcopy
|
||||||
|
|
||||||
|
//Path to a program.
|
||||||
|
CMAKE_OBJDUMP:FILEPATH=/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-objdump
|
||||||
|
|
||||||
|
//Value Computed by CMake
|
||||||
|
CMAKE_PROJECT_DESCRIPTION:STATIC=
|
||||||
|
|
||||||
|
//Value Computed by CMake
|
||||||
|
CMAKE_PROJECT_HOMEPAGE_URL:STATIC=
|
||||||
|
|
||||||
|
//Value Computed by CMake
|
||||||
|
CMAKE_PROJECT_NAME:STATIC=appmodules
|
||||||
|
|
||||||
|
//Ranlib
|
||||||
|
CMAKE_RANLIB:FILEPATH=/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib
|
||||||
|
|
||||||
|
//Path to a program.
|
||||||
|
CMAKE_READELF:FILEPATH=/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-readelf
|
||||||
|
|
||||||
|
//No help, variable specified on the command line.
|
||||||
|
CMAKE_RUNTIME_OUTPUT_DIRECTORY:UNINITIALIZED=/home/echo/dev/prototype/apps/mobile/android/app/build/intermediates/cxx/Debug/2z472e3c/obj/x86
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of dll's.
|
||||||
|
CMAKE_SHARED_LINKER_FLAGS:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of shared libraries
|
||||||
|
// during DEBUG builds.
|
||||||
|
CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of shared libraries
|
||||||
|
// during MINSIZEREL builds.
|
||||||
|
CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of shared libraries
|
||||||
|
// during RELEASE builds.
|
||||||
|
CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of shared libraries
|
||||||
|
// during RELWITHDEBINFO builds.
|
||||||
|
CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING=
|
||||||
|
|
||||||
|
//If set, runtime paths are not added when installing shared libraries,
|
||||||
|
// but are added when building.
|
||||||
|
CMAKE_SKIP_INSTALL_RPATH:BOOL=NO
|
||||||
|
|
||||||
|
//If set, runtime paths are not added when using shared libraries.
|
||||||
|
CMAKE_SKIP_RPATH:BOOL=NO
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of static libraries
|
||||||
|
// during all build types.
|
||||||
|
CMAKE_STATIC_LINKER_FLAGS:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of static libraries
|
||||||
|
// during DEBUG builds.
|
||||||
|
CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of static libraries
|
||||||
|
// during MINSIZEREL builds.
|
||||||
|
CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of static libraries
|
||||||
|
// during RELEASE builds.
|
||||||
|
CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of static libraries
|
||||||
|
// during RELWITHDEBINFO builds.
|
||||||
|
CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING=
|
||||||
|
|
||||||
|
//Strip
|
||||||
|
CMAKE_STRIP:FILEPATH=/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip
|
||||||
|
|
||||||
|
//No help, variable specified on the command line.
|
||||||
|
CMAKE_SYSTEM_NAME:UNINITIALIZED=Android
|
||||||
|
|
||||||
|
//No help, variable specified on the command line.
|
||||||
|
CMAKE_SYSTEM_VERSION:UNINITIALIZED=26
|
||||||
|
|
||||||
|
//The CMake toolchain file
|
||||||
|
CMAKE_TOOLCHAIN_FILE:FILEPATH=/home/echo/Android/Sdk/ndk/27.1.12297006/build/cmake/android.toolchain.cmake
|
||||||
|
|
||||||
|
//If this value is on, makefiles will be generated without the
|
||||||
|
// .SILENT directive, and all commands will be echoed to the console
|
||||||
|
// during the make. This is useful for debugging only. With Visual
|
||||||
|
// Studio IDE projects all commands are done without /nologo.
|
||||||
|
CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE
|
||||||
|
|
||||||
|
//No help, variable specified on the command line.
|
||||||
|
PROJECT_BUILD_DIR:UNINITIALIZED=/home/echo/dev/prototype/apps/mobile/android/app/build
|
||||||
|
|
||||||
|
//No help, variable specified on the command line.
|
||||||
|
PROJECT_ROOT_DIR:UNINITIALIZED=/home/echo/dev/prototype/apps/mobile/android
|
||||||
|
|
||||||
|
//No help, variable specified on the command line.
|
||||||
|
REACT_ANDROID_DIR:UNINITIALIZED=/home/echo/dev/prototype/apps/mobile/node_modules/react-native/ReactAndroid
|
||||||
|
|
||||||
|
//The directory containing a CMake configuration file for ReactAndroid.
|
||||||
|
ReactAndroid_DIR:PATH=/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/prefab/x86/prefab/lib/i686-linux-android/cmake/ReactAndroid
|
||||||
|
|
||||||
|
//Value Computed by CMake
|
||||||
|
appmodules_BINARY_DIR:STATIC=/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/x86
|
||||||
|
|
||||||
|
//Value Computed by CMake
|
||||||
|
appmodules_IS_TOP_LEVEL:STATIC=ON
|
||||||
|
|
||||||
|
//Value Computed by CMake
|
||||||
|
appmodules_SOURCE_DIR:STATIC=/home/echo/dev/prototype/apps/mobile/node_modules/react-native/ReactAndroid/cmake-utils/default-app-setup
|
||||||
|
|
||||||
|
//The directory containing a CMake configuration file for fbjni.
|
||||||
|
fbjni_DIR:PATH=/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/prefab/x86/prefab/lib/i686-linux-android/cmake/fbjni
|
||||||
|
|
||||||
|
|
||||||
|
########################
|
||||||
|
# INTERNAL cache entries
|
||||||
|
########################
|
||||||
|
|
||||||
|
//ADVANCED property for variable: CMAKE_ADDR2LINE
|
||||||
|
CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_AR
|
||||||
|
CMAKE_AR-ADVANCED:INTERNAL=1
|
||||||
|
//This is the directory where this CMakeCache.txt was created
|
||||||
|
CMAKE_CACHEFILE_DIR:INTERNAL=/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/x86
|
||||||
|
//Major version of cmake used to create the current loaded cache
|
||||||
|
CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3
|
||||||
|
//Minor version of cmake used to create the current loaded cache
|
||||||
|
CMAKE_CACHE_MINOR_VERSION:INTERNAL=22
|
||||||
|
//Patch version of cmake used to create the current loaded cache
|
||||||
|
CMAKE_CACHE_PATCH_VERSION:INTERNAL=1
|
||||||
|
//Path to CMake executable.
|
||||||
|
CMAKE_COMMAND:INTERNAL=/home/echo/Android/Sdk/cmake/3.22.1/bin/cmake
|
||||||
|
//Path to cpack program executable.
|
||||||
|
CMAKE_CPACK_COMMAND:INTERNAL=/home/echo/Android/Sdk/cmake/3.22.1/bin/cpack
|
||||||
|
//Path to ctest program executable.
|
||||||
|
CMAKE_CTEST_COMMAND:INTERNAL=/home/echo/Android/Sdk/cmake/3.22.1/bin/ctest
|
||||||
|
//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR
|
||||||
|
CMAKE_CXX_COMPILER_AR-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_CXX_COMPILER_RANLIB
|
||||||
|
CMAKE_CXX_COMPILER_RANLIB-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_CXX_FLAGS
|
||||||
|
CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG
|
||||||
|
CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL
|
||||||
|
CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE
|
||||||
|
CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO
|
||||||
|
CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_CXX_STANDARD_LIBRARIES
|
||||||
|
CMAKE_CXX_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_C_COMPILER_AR
|
||||||
|
CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB
|
||||||
|
CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_C_FLAGS
|
||||||
|
CMAKE_C_FLAGS-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG
|
||||||
|
CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL
|
||||||
|
CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE
|
||||||
|
CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO
|
||||||
|
CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_C_STANDARD_LIBRARIES
|
||||||
|
CMAKE_C_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_DLLTOOL
|
||||||
|
CMAKE_DLLTOOL-ADVANCED:INTERNAL=1
|
||||||
|
//Executable file format
|
||||||
|
CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF
|
||||||
|
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS
|
||||||
|
CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG
|
||||||
|
CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL
|
||||||
|
CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE
|
||||||
|
CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO
|
||||||
|
CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
|
||||||
|
//Name of external makefile project generator.
|
||||||
|
CMAKE_EXTRA_GENERATOR:INTERNAL=
|
||||||
|
//Name of generator.
|
||||||
|
CMAKE_GENERATOR:INTERNAL=Ninja
|
||||||
|
//Generator instance identifier.
|
||||||
|
CMAKE_GENERATOR_INSTANCE:INTERNAL=
|
||||||
|
//Name of generator platform.
|
||||||
|
CMAKE_GENERATOR_PLATFORM:INTERNAL=
|
||||||
|
//Name of generator toolset.
|
||||||
|
CMAKE_GENERATOR_TOOLSET:INTERNAL=
|
||||||
|
//Source directory with the top level CMakeLists.txt file for this
|
||||||
|
// project
|
||||||
|
CMAKE_HOME_DIRECTORY:INTERNAL=/home/echo/dev/prototype/apps/mobile/node_modules/react-native/ReactAndroid/cmake-utils/default-app-setup
|
||||||
|
//Install .so files without execute permission.
|
||||||
|
CMAKE_INSTALL_SO_NO_EXE:INTERNAL=0
|
||||||
|
//ADVANCED property for variable: CMAKE_LINKER
|
||||||
|
CMAKE_LINKER-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS
|
||||||
|
CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG
|
||||||
|
CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL
|
||||||
|
CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE
|
||||||
|
CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO
|
||||||
|
CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_NM
|
||||||
|
CMAKE_NM-ADVANCED:INTERNAL=1
|
||||||
|
//number of local generators
|
||||||
|
CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_OBJCOPY
|
||||||
|
CMAKE_OBJCOPY-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_OBJDUMP
|
||||||
|
CMAKE_OBJDUMP-ADVANCED:INTERNAL=1
|
||||||
|
//Platform information initialized
|
||||||
|
CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_RANLIB
|
||||||
|
CMAKE_RANLIB-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_READELF
|
||||||
|
CMAKE_READELF-ADVANCED:INTERNAL=1
|
||||||
|
//Path to CMake installation.
|
||||||
|
CMAKE_ROOT:INTERNAL=/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22
|
||||||
|
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS
|
||||||
|
CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG
|
||||||
|
CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL
|
||||||
|
CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE
|
||||||
|
CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO
|
||||||
|
CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH
|
||||||
|
CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_SKIP_RPATH
|
||||||
|
CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS
|
||||||
|
CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG
|
||||||
|
CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL
|
||||||
|
CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE
|
||||||
|
CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO
|
||||||
|
CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_STRIP
|
||||||
|
CMAKE_STRIP-ADVANCED:INTERNAL=1
|
||||||
|
//uname command
|
||||||
|
CMAKE_UNAME:INTERNAL=/usr/bin/uname
|
||||||
|
//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE
|
||||||
|
CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1
|
||||||
|
|
||||||
+72
@@ -0,0 +1,72 @@
|
|||||||
|
set(CMAKE_C_COMPILER "/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/clang")
|
||||||
|
set(CMAKE_C_COMPILER_ARG1 "")
|
||||||
|
set(CMAKE_C_COMPILER_ID "Clang")
|
||||||
|
set(CMAKE_C_COMPILER_VERSION "18.0.2")
|
||||||
|
set(CMAKE_C_COMPILER_VERSION_INTERNAL "")
|
||||||
|
set(CMAKE_C_COMPILER_WRAPPER "")
|
||||||
|
set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "17")
|
||||||
|
set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "ON")
|
||||||
|
set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert;c_std_17;c_std_23")
|
||||||
|
set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes")
|
||||||
|
set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros")
|
||||||
|
set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert")
|
||||||
|
set(CMAKE_C17_COMPILE_FEATURES "c_std_17")
|
||||||
|
set(CMAKE_C23_COMPILE_FEATURES "c_std_23")
|
||||||
|
|
||||||
|
set(CMAKE_C_PLATFORM_ID "Linux")
|
||||||
|
set(CMAKE_C_SIMULATE_ID "")
|
||||||
|
set(CMAKE_C_COMPILER_FRONTEND_VARIANT "GNU")
|
||||||
|
set(CMAKE_C_SIMULATE_VERSION "")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
set(CMAKE_AR "/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar")
|
||||||
|
set(CMAKE_C_COMPILER_AR "/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar")
|
||||||
|
set(CMAKE_RANLIB "/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib")
|
||||||
|
set(CMAKE_C_COMPILER_RANLIB "/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib")
|
||||||
|
set(CMAKE_LINKER "/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/ld.lld")
|
||||||
|
set(CMAKE_MT "")
|
||||||
|
set(CMAKE_COMPILER_IS_GNUCC )
|
||||||
|
set(CMAKE_C_COMPILER_LOADED 1)
|
||||||
|
set(CMAKE_C_COMPILER_WORKS TRUE)
|
||||||
|
set(CMAKE_C_ABI_COMPILED TRUE)
|
||||||
|
|
||||||
|
set(CMAKE_C_COMPILER_ENV_VAR "CC")
|
||||||
|
|
||||||
|
set(CMAKE_C_COMPILER_ID_RUN 1)
|
||||||
|
set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m)
|
||||||
|
set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC)
|
||||||
|
set(CMAKE_C_LINKER_PREFERENCE 10)
|
||||||
|
|
||||||
|
# Save compiler ABI information.
|
||||||
|
set(CMAKE_C_SIZEOF_DATA_PTR "4")
|
||||||
|
set(CMAKE_C_COMPILER_ABI "ELF")
|
||||||
|
set(CMAKE_C_BYTE_ORDER "LITTLE_ENDIAN")
|
||||||
|
set(CMAKE_C_LIBRARY_ARCHITECTURE "")
|
||||||
|
|
||||||
|
if(CMAKE_C_SIZEOF_DATA_PTR)
|
||||||
|
set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_C_COMPILER_ABI)
|
||||||
|
set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_C_LIBRARY_ARCHITECTURE)
|
||||||
|
set(CMAKE_LIBRARY_ARCHITECTURE "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "")
|
||||||
|
if(CMAKE_C_CL_SHOWINCLUDES_PREFIX)
|
||||||
|
set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include;/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/i686-linux-android;/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include")
|
||||||
|
set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "-l:libunwind.a;dl;c;-l:libunwind.a;dl")
|
||||||
|
set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/i386;/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/26;/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android;/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib")
|
||||||
|
set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "")
|
||||||
+83
@@ -0,0 +1,83 @@
|
|||||||
|
set(CMAKE_CXX_COMPILER "/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++")
|
||||||
|
set(CMAKE_CXX_COMPILER_ARG1 "")
|
||||||
|
set(CMAKE_CXX_COMPILER_ID "Clang")
|
||||||
|
set(CMAKE_CXX_COMPILER_VERSION "18.0.2")
|
||||||
|
set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "")
|
||||||
|
set(CMAKE_CXX_COMPILER_WRAPPER "")
|
||||||
|
set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "17")
|
||||||
|
set(CMAKE_CXX_EXTENSIONS_COMPUTED_DEFAULT "ON")
|
||||||
|
set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20;cxx_std_23")
|
||||||
|
set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters")
|
||||||
|
set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates")
|
||||||
|
set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates")
|
||||||
|
set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17")
|
||||||
|
set(CMAKE_CXX20_COMPILE_FEATURES "cxx_std_20")
|
||||||
|
set(CMAKE_CXX23_COMPILE_FEATURES "cxx_std_23")
|
||||||
|
|
||||||
|
set(CMAKE_CXX_PLATFORM_ID "Linux")
|
||||||
|
set(CMAKE_CXX_SIMULATE_ID "")
|
||||||
|
set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "GNU")
|
||||||
|
set(CMAKE_CXX_SIMULATE_VERSION "")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
set(CMAKE_AR "/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar")
|
||||||
|
set(CMAKE_CXX_COMPILER_AR "/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar")
|
||||||
|
set(CMAKE_RANLIB "/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib")
|
||||||
|
set(CMAKE_CXX_COMPILER_RANLIB "/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib")
|
||||||
|
set(CMAKE_LINKER "/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/ld.lld")
|
||||||
|
set(CMAKE_MT "")
|
||||||
|
set(CMAKE_COMPILER_IS_GNUCXX )
|
||||||
|
set(CMAKE_CXX_COMPILER_LOADED 1)
|
||||||
|
set(CMAKE_CXX_COMPILER_WORKS TRUE)
|
||||||
|
set(CMAKE_CXX_ABI_COMPILED TRUE)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_COMPILER_ENV_VAR "CXX")
|
||||||
|
|
||||||
|
set(CMAKE_CXX_COMPILER_ID_RUN 1)
|
||||||
|
set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;mpp;CPP;ixx;cppm)
|
||||||
|
set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC)
|
||||||
|
|
||||||
|
foreach (lang C OBJC OBJCXX)
|
||||||
|
if (CMAKE_${lang}_COMPILER_ID_RUN)
|
||||||
|
foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS)
|
||||||
|
list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension})
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set(CMAKE_CXX_LINKER_PREFERENCE 30)
|
||||||
|
set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1)
|
||||||
|
|
||||||
|
# Save compiler ABI information.
|
||||||
|
set(CMAKE_CXX_SIZEOF_DATA_PTR "4")
|
||||||
|
set(CMAKE_CXX_COMPILER_ABI "ELF")
|
||||||
|
set(CMAKE_CXX_BYTE_ORDER "LITTLE_ENDIAN")
|
||||||
|
set(CMAKE_CXX_LIBRARY_ARCHITECTURE "")
|
||||||
|
|
||||||
|
if(CMAKE_CXX_SIZEOF_DATA_PTR)
|
||||||
|
set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_CXX_COMPILER_ABI)
|
||||||
|
set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_CXX_LIBRARY_ARCHITECTURE)
|
||||||
|
set(CMAKE_LIBRARY_ARCHITECTURE "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "")
|
||||||
|
if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX)
|
||||||
|
set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/c++/v1;/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include;/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/i686-linux-android;/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include")
|
||||||
|
set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "c++;m;-l:libunwind.a;dl;c;-l:libunwind.a;dl")
|
||||||
|
set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/i386;/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/26;/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android;/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib")
|
||||||
|
set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "")
|
||||||
BIN
Binary file not shown.
BIN
Binary file not shown.
+15
@@ -0,0 +1,15 @@
|
|||||||
|
set(CMAKE_HOST_SYSTEM "Linux-6.17.8-arch1-1")
|
||||||
|
set(CMAKE_HOST_SYSTEM_NAME "Linux")
|
||||||
|
set(CMAKE_HOST_SYSTEM_VERSION "6.17.8-arch1-1")
|
||||||
|
set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64")
|
||||||
|
|
||||||
|
include("/home/echo/Android/Sdk/ndk/27.1.12297006/build/cmake/android.toolchain.cmake")
|
||||||
|
|
||||||
|
set(CMAKE_SYSTEM "Android-1")
|
||||||
|
set(CMAKE_SYSTEM_NAME "Android")
|
||||||
|
set(CMAKE_SYSTEM_VERSION "1")
|
||||||
|
set(CMAKE_SYSTEM_PROCESSOR "i686")
|
||||||
|
|
||||||
|
set(CMAKE_CROSSCOMPILING "TRUE")
|
||||||
|
|
||||||
|
set(CMAKE_SYSTEM_LOADED 1)
|
||||||
+803
@@ -0,0 +1,803 @@
|
|||||||
|
#ifdef __cplusplus
|
||||||
|
# error "A C++ compiler has been selected for C."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__18CXX)
|
||||||
|
# define ID_VOID_MAIN
|
||||||
|
#endif
|
||||||
|
#if defined(__CLASSIC_C__)
|
||||||
|
/* cv-qualifiers did not exist in K&R C */
|
||||||
|
# define const
|
||||||
|
# define volatile
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(__has_include)
|
||||||
|
/* If the compiler does not have __has_include, pretend the answer is
|
||||||
|
always no. */
|
||||||
|
# define __has_include(x) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Version number components: V=Version, R=Revision, P=Patch
|
||||||
|
Version date components: YYYY=Year, MM=Month, DD=Day */
|
||||||
|
|
||||||
|
#if defined(__INTEL_COMPILER) || defined(__ICC)
|
||||||
|
# define COMPILER_ID "Intel"
|
||||||
|
# if defined(_MSC_VER)
|
||||||
|
# define SIMULATE_ID "MSVC"
|
||||||
|
# endif
|
||||||
|
# if defined(__GNUC__)
|
||||||
|
# define SIMULATE_ID "GNU"
|
||||||
|
# endif
|
||||||
|
/* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later,
|
||||||
|
except that a few beta releases use the old format with V=2021. */
|
||||||
|
# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10)
|
||||||
|
# if defined(__INTEL_COMPILER_UPDATE)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE)
|
||||||
|
# else
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10)
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE)
|
||||||
|
/* The third version component from --version is an update index,
|
||||||
|
but no macro is provided for it. */
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(0)
|
||||||
|
# endif
|
||||||
|
# if defined(__INTEL_COMPILER_BUILD_DATE)
|
||||||
|
/* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */
|
||||||
|
# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE)
|
||||||
|
# endif
|
||||||
|
# if defined(_MSC_VER)
|
||||||
|
/* _MSC_VER = VVRR */
|
||||||
|
# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
|
||||||
|
# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
|
||||||
|
# endif
|
||||||
|
# if defined(__GNUC__)
|
||||||
|
# define SIMULATE_VERSION_MAJOR DEC(__GNUC__)
|
||||||
|
# elif defined(__GNUG__)
|
||||||
|
# define SIMULATE_VERSION_MAJOR DEC(__GNUG__)
|
||||||
|
# endif
|
||||||
|
# if defined(__GNUC_MINOR__)
|
||||||
|
# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__)
|
||||||
|
# endif
|
||||||
|
# if defined(__GNUC_PATCHLEVEL__)
|
||||||
|
# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER)
|
||||||
|
# define COMPILER_ID "IntelLLVM"
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# define SIMULATE_ID "MSVC"
|
||||||
|
#endif
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
# define SIMULATE_ID "GNU"
|
||||||
|
#endif
|
||||||
|
/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and
|
||||||
|
* later. Look for 6 digit vs. 8 digit version number to decide encoding.
|
||||||
|
* VVVV is no smaller than the current year when a version is released.
|
||||||
|
*/
|
||||||
|
#if __INTEL_LLVM_COMPILER < 1000000L
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10)
|
||||||
|
#else
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100)
|
||||||
|
#endif
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
/* _MSC_VER = VVRR */
|
||||||
|
# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
|
||||||
|
# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
|
||||||
|
#endif
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
# define SIMULATE_VERSION_MAJOR DEC(__GNUC__)
|
||||||
|
#elif defined(__GNUG__)
|
||||||
|
# define SIMULATE_VERSION_MAJOR DEC(__GNUG__)
|
||||||
|
#endif
|
||||||
|
#if defined(__GNUC_MINOR__)
|
||||||
|
# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__)
|
||||||
|
#endif
|
||||||
|
#if defined(__GNUC_PATCHLEVEL__)
|
||||||
|
# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined(__PATHCC__)
|
||||||
|
# define COMPILER_ID "PathScale"
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__PATHCC__)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__)
|
||||||
|
# if defined(__PATHCC_PATCHLEVEL__)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__)
|
||||||
|
# define COMPILER_ID "Embarcadero"
|
||||||
|
# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF)
|
||||||
|
# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF)
|
||||||
|
|
||||||
|
#elif defined(__BORLANDC__)
|
||||||
|
# define COMPILER_ID "Borland"
|
||||||
|
/* __BORLANDC__ = 0xVRR */
|
||||||
|
# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8)
|
||||||
|
# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF)
|
||||||
|
|
||||||
|
#elif defined(__WATCOMC__) && __WATCOMC__ < 1200
|
||||||
|
# define COMPILER_ID "Watcom"
|
||||||
|
/* __WATCOMC__ = VVRR */
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
|
||||||
|
# if (__WATCOMC__ % 10) > 0
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__WATCOMC__)
|
||||||
|
# define COMPILER_ID "OpenWatcom"
|
||||||
|
/* __WATCOMC__ = VVRP + 1100 */
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
|
||||||
|
# if (__WATCOMC__ % 10) > 0
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__SUNPRO_C)
|
||||||
|
# define COMPILER_ID "SunPro"
|
||||||
|
# if __SUNPRO_C >= 0x5100
|
||||||
|
/* __SUNPRO_C = 0xVRRP */
|
||||||
|
# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12)
|
||||||
|
# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF)
|
||||||
|
# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF)
|
||||||
|
# else
|
||||||
|
/* __SUNPRO_CC = 0xVRP */
|
||||||
|
# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8)
|
||||||
|
# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF)
|
||||||
|
# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__HP_cc)
|
||||||
|
# define COMPILER_ID "HP"
|
||||||
|
/* __HP_cc = VVRRPP */
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100)
|
||||||
|
|
||||||
|
#elif defined(__DECC)
|
||||||
|
# define COMPILER_ID "Compaq"
|
||||||
|
/* __DECC_VER = VVRRTPPPP */
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000)
|
||||||
|
|
||||||
|
#elif defined(__IBMC__) && defined(__COMPILER_VER__)
|
||||||
|
# define COMPILER_ID "zOS"
|
||||||
|
/* __IBMC__ = VRP */
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10)
|
||||||
|
|
||||||
|
#elif defined(__ibmxl__) && defined(__clang__)
|
||||||
|
# define COMPILER_ID "XLClang"
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__)
|
||||||
|
# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__)
|
||||||
|
|
||||||
|
|
||||||
|
#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800
|
||||||
|
# define COMPILER_ID "XL"
|
||||||
|
/* __IBMC__ = VRP */
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10)
|
||||||
|
|
||||||
|
#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800
|
||||||
|
# define COMPILER_ID "VisualAge"
|
||||||
|
/* __IBMC__ = VRP */
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10)
|
||||||
|
|
||||||
|
#elif defined(__NVCOMPILER)
|
||||||
|
# define COMPILER_ID "NVHPC"
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__)
|
||||||
|
# if defined(__NVCOMPILER_PATCHLEVEL__)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__PGI)
|
||||||
|
# define COMPILER_ID "PGI"
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__PGIC__)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__)
|
||||||
|
# if defined(__PGIC_PATCHLEVEL__)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(_CRAYC)
|
||||||
|
# define COMPILER_ID "Cray"
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR)
|
||||||
|
|
||||||
|
#elif defined(__TI_COMPILER_VERSION__)
|
||||||
|
# define COMPILER_ID "TI"
|
||||||
|
/* __TI_COMPILER_VERSION__ = VVVRRRPPP */
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000)
|
||||||
|
|
||||||
|
#elif defined(__CLANG_FUJITSU)
|
||||||
|
# define COMPILER_ID "FujitsuClang"
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__FCC_major__)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__FCC_minor__)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__)
|
||||||
|
# define COMPILER_VERSION_INTERNAL_STR __clang_version__
|
||||||
|
|
||||||
|
|
||||||
|
#elif defined(__FUJITSU)
|
||||||
|
# define COMPILER_ID "Fujitsu"
|
||||||
|
# if defined(__FCC_version__)
|
||||||
|
# define COMPILER_VERSION __FCC_version__
|
||||||
|
# elif defined(__FCC_major__)
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__FCC_major__)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__FCC_minor__)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__)
|
||||||
|
# endif
|
||||||
|
# if defined(__fcc_version)
|
||||||
|
# define COMPILER_VERSION_INTERNAL DEC(__fcc_version)
|
||||||
|
# elif defined(__FCC_VERSION)
|
||||||
|
# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
|
||||||
|
#elif defined(__ghs__)
|
||||||
|
# define COMPILER_ID "GHS"
|
||||||
|
/* __GHS_VERSION_NUMBER = VVVVRP */
|
||||||
|
# ifdef __GHS_VERSION_NUMBER
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__TINYC__)
|
||||||
|
# define COMPILER_ID "TinyCC"
|
||||||
|
|
||||||
|
#elif defined(__BCC__)
|
||||||
|
# define COMPILER_ID "Bruce"
|
||||||
|
|
||||||
|
#elif defined(__SCO_VERSION__)
|
||||||
|
# define COMPILER_ID "SCO"
|
||||||
|
|
||||||
|
#elif defined(__ARMCC_VERSION) && !defined(__clang__)
|
||||||
|
# define COMPILER_ID "ARMCC"
|
||||||
|
#if __ARMCC_VERSION >= 1000000
|
||||||
|
/* __ARMCC_VERSION = VRRPPPP */
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
|
||||||
|
#else
|
||||||
|
/* __ARMCC_VERSION = VRPPPP */
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#elif defined(__clang__) && defined(__apple_build_version__)
|
||||||
|
# define COMPILER_ID "AppleClang"
|
||||||
|
# if defined(_MSC_VER)
|
||||||
|
# define SIMULATE_ID "MSVC"
|
||||||
|
# endif
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
|
||||||
|
# if defined(_MSC_VER)
|
||||||
|
/* _MSC_VER = VVRR */
|
||||||
|
# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
|
||||||
|
# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
|
||||||
|
# endif
|
||||||
|
# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__)
|
||||||
|
|
||||||
|
#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION)
|
||||||
|
# define COMPILER_ID "ARMClang"
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000)
|
||||||
|
# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION)
|
||||||
|
|
||||||
|
#elif defined(__clang__)
|
||||||
|
# define COMPILER_ID "Clang"
|
||||||
|
# if defined(_MSC_VER)
|
||||||
|
# define SIMULATE_ID "MSVC"
|
||||||
|
# endif
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
|
||||||
|
# if defined(_MSC_VER)
|
||||||
|
/* _MSC_VER = VVRR */
|
||||||
|
# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
|
||||||
|
# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
# define COMPILER_ID "GNU"
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__GNUC__)
|
||||||
|
# if defined(__GNUC_MINOR__)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__)
|
||||||
|
# endif
|
||||||
|
# if defined(__GNUC_PATCHLEVEL__)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
# define COMPILER_ID "MSVC"
|
||||||
|
/* _MSC_VER = VVRR */
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100)
|
||||||
|
# if defined(_MSC_FULL_VER)
|
||||||
|
# if _MSC_VER >= 1400
|
||||||
|
/* _MSC_FULL_VER = VVRRPPPPP */
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000)
|
||||||
|
# else
|
||||||
|
/* _MSC_FULL_VER = VVRRPPPP */
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000)
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# if defined(_MSC_BUILD)
|
||||||
|
# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__)
|
||||||
|
# define COMPILER_ID "ADSP"
|
||||||
|
#if defined(__VISUALDSPVERSION__)
|
||||||
|
/* __VISUALDSPVERSION__ = 0xVVRRPP00 */
|
||||||
|
# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24)
|
||||||
|
# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF)
|
||||||
|
# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
|
||||||
|
# define COMPILER_ID "IAR"
|
||||||
|
# if defined(__VER__) && defined(__ICCARM__)
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000)
|
||||||
|
# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
|
||||||
|
# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__))
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100))
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__)
|
||||||
|
# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC)
|
||||||
|
# define COMPILER_ID "SDCC"
|
||||||
|
# if defined(__SDCC_VERSION_MAJOR)
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH)
|
||||||
|
# else
|
||||||
|
/* SDCC = VRP */
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(SDCC/100)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(SDCC % 10)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
|
||||||
|
/* These compilers are either not known or too old to define an
|
||||||
|
identification macro. Try to identify the platform and guess that
|
||||||
|
it is the native compiler. */
|
||||||
|
#elif defined(__hpux) || defined(__hpua)
|
||||||
|
# define COMPILER_ID "HP"
|
||||||
|
|
||||||
|
#else /* unknown compiler */
|
||||||
|
# define COMPILER_ID ""
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Construct the string literal in pieces to prevent the source from
|
||||||
|
getting matched. Store it in a pointer rather than an array
|
||||||
|
because some compilers will just produce instructions to fill the
|
||||||
|
array rather than assigning a pointer to a static array. */
|
||||||
|
char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]";
|
||||||
|
#ifdef SIMULATE_ID
|
||||||
|
char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __QNXNTO__
|
||||||
|
char const* qnxnto = "INFO" ":" "qnxnto[]";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__CRAYXT_COMPUTE_LINUX_TARGET)
|
||||||
|
char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define STRINGIFY_HELPER(X) #X
|
||||||
|
#define STRINGIFY(X) STRINGIFY_HELPER(X)
|
||||||
|
|
||||||
|
/* Identify known platforms by name. */
|
||||||
|
#if defined(__linux) || defined(__linux__) || defined(linux)
|
||||||
|
# define PLATFORM_ID "Linux"
|
||||||
|
|
||||||
|
#elif defined(__MSYS__)
|
||||||
|
# define PLATFORM_ID "MSYS"
|
||||||
|
|
||||||
|
#elif defined(__CYGWIN__)
|
||||||
|
# define PLATFORM_ID "Cygwin"
|
||||||
|
|
||||||
|
#elif defined(__MINGW32__)
|
||||||
|
# define PLATFORM_ID "MinGW"
|
||||||
|
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
# define PLATFORM_ID "Darwin"
|
||||||
|
|
||||||
|
#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
|
||||||
|
# define PLATFORM_ID "Windows"
|
||||||
|
|
||||||
|
#elif defined(__FreeBSD__) || defined(__FreeBSD)
|
||||||
|
# define PLATFORM_ID "FreeBSD"
|
||||||
|
|
||||||
|
#elif defined(__NetBSD__) || defined(__NetBSD)
|
||||||
|
# define PLATFORM_ID "NetBSD"
|
||||||
|
|
||||||
|
#elif defined(__OpenBSD__) || defined(__OPENBSD)
|
||||||
|
# define PLATFORM_ID "OpenBSD"
|
||||||
|
|
||||||
|
#elif defined(__sun) || defined(sun)
|
||||||
|
# define PLATFORM_ID "SunOS"
|
||||||
|
|
||||||
|
#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__)
|
||||||
|
# define PLATFORM_ID "AIX"
|
||||||
|
|
||||||
|
#elif defined(__hpux) || defined(__hpux__)
|
||||||
|
# define PLATFORM_ID "HP-UX"
|
||||||
|
|
||||||
|
#elif defined(__HAIKU__)
|
||||||
|
# define PLATFORM_ID "Haiku"
|
||||||
|
|
||||||
|
#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS)
|
||||||
|
# define PLATFORM_ID "BeOS"
|
||||||
|
|
||||||
|
#elif defined(__QNX__) || defined(__QNXNTO__)
|
||||||
|
# define PLATFORM_ID "QNX"
|
||||||
|
|
||||||
|
#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__)
|
||||||
|
# define PLATFORM_ID "Tru64"
|
||||||
|
|
||||||
|
#elif defined(__riscos) || defined(__riscos__)
|
||||||
|
# define PLATFORM_ID "RISCos"
|
||||||
|
|
||||||
|
#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__)
|
||||||
|
# define PLATFORM_ID "SINIX"
|
||||||
|
|
||||||
|
#elif defined(__UNIX_SV__)
|
||||||
|
# define PLATFORM_ID "UNIX_SV"
|
||||||
|
|
||||||
|
#elif defined(__bsdos__)
|
||||||
|
# define PLATFORM_ID "BSDOS"
|
||||||
|
|
||||||
|
#elif defined(_MPRAS) || defined(MPRAS)
|
||||||
|
# define PLATFORM_ID "MP-RAS"
|
||||||
|
|
||||||
|
#elif defined(__osf) || defined(__osf__)
|
||||||
|
# define PLATFORM_ID "OSF1"
|
||||||
|
|
||||||
|
#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv)
|
||||||
|
# define PLATFORM_ID "SCO_SV"
|
||||||
|
|
||||||
|
#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX)
|
||||||
|
# define PLATFORM_ID "ULTRIX"
|
||||||
|
|
||||||
|
#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX)
|
||||||
|
# define PLATFORM_ID "Xenix"
|
||||||
|
|
||||||
|
#elif defined(__WATCOMC__)
|
||||||
|
# if defined(__LINUX__)
|
||||||
|
# define PLATFORM_ID "Linux"
|
||||||
|
|
||||||
|
# elif defined(__DOS__)
|
||||||
|
# define PLATFORM_ID "DOS"
|
||||||
|
|
||||||
|
# elif defined(__OS2__)
|
||||||
|
# define PLATFORM_ID "OS2"
|
||||||
|
|
||||||
|
# elif defined(__WINDOWS__)
|
||||||
|
# define PLATFORM_ID "Windows3x"
|
||||||
|
|
||||||
|
# elif defined(__VXWORKS__)
|
||||||
|
# define PLATFORM_ID "VxWorks"
|
||||||
|
|
||||||
|
# else /* unknown platform */
|
||||||
|
# define PLATFORM_ID
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__INTEGRITY)
|
||||||
|
# if defined(INT_178B)
|
||||||
|
# define PLATFORM_ID "Integrity178"
|
||||||
|
|
||||||
|
# else /* regular Integrity */
|
||||||
|
# define PLATFORM_ID "Integrity"
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#else /* unknown platform */
|
||||||
|
# define PLATFORM_ID
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* For windows compilers MSVC and Intel we can determine
|
||||||
|
the architecture of the compiler being used. This is because
|
||||||
|
the compilers do not have flags that can change the architecture,
|
||||||
|
but rather depend on which compiler is being used
|
||||||
|
*/
|
||||||
|
#if defined(_WIN32) && defined(_MSC_VER)
|
||||||
|
# if defined(_M_IA64)
|
||||||
|
# define ARCHITECTURE_ID "IA64"
|
||||||
|
|
||||||
|
# elif defined(_M_ARM64EC)
|
||||||
|
# define ARCHITECTURE_ID "ARM64EC"
|
||||||
|
|
||||||
|
# elif defined(_M_X64) || defined(_M_AMD64)
|
||||||
|
# define ARCHITECTURE_ID "x64"
|
||||||
|
|
||||||
|
# elif defined(_M_IX86)
|
||||||
|
# define ARCHITECTURE_ID "X86"
|
||||||
|
|
||||||
|
# elif defined(_M_ARM64)
|
||||||
|
# define ARCHITECTURE_ID "ARM64"
|
||||||
|
|
||||||
|
# elif defined(_M_ARM)
|
||||||
|
# if _M_ARM == 4
|
||||||
|
# define ARCHITECTURE_ID "ARMV4I"
|
||||||
|
# elif _M_ARM == 5
|
||||||
|
# define ARCHITECTURE_ID "ARMV5I"
|
||||||
|
# else
|
||||||
|
# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# elif defined(_M_MIPS)
|
||||||
|
# define ARCHITECTURE_ID "MIPS"
|
||||||
|
|
||||||
|
# elif defined(_M_SH)
|
||||||
|
# define ARCHITECTURE_ID "SHx"
|
||||||
|
|
||||||
|
# else /* unknown architecture */
|
||||||
|
# define ARCHITECTURE_ID ""
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__WATCOMC__)
|
||||||
|
# if defined(_M_I86)
|
||||||
|
# define ARCHITECTURE_ID "I86"
|
||||||
|
|
||||||
|
# elif defined(_M_IX86)
|
||||||
|
# define ARCHITECTURE_ID "X86"
|
||||||
|
|
||||||
|
# else /* unknown architecture */
|
||||||
|
# define ARCHITECTURE_ID ""
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
|
||||||
|
# if defined(__ICCARM__)
|
||||||
|
# define ARCHITECTURE_ID "ARM"
|
||||||
|
|
||||||
|
# elif defined(__ICCRX__)
|
||||||
|
# define ARCHITECTURE_ID "RX"
|
||||||
|
|
||||||
|
# elif defined(__ICCRH850__)
|
||||||
|
# define ARCHITECTURE_ID "RH850"
|
||||||
|
|
||||||
|
# elif defined(__ICCRL78__)
|
||||||
|
# define ARCHITECTURE_ID "RL78"
|
||||||
|
|
||||||
|
# elif defined(__ICCRISCV__)
|
||||||
|
# define ARCHITECTURE_ID "RISCV"
|
||||||
|
|
||||||
|
# elif defined(__ICCAVR__)
|
||||||
|
# define ARCHITECTURE_ID "AVR"
|
||||||
|
|
||||||
|
# elif defined(__ICC430__)
|
||||||
|
# define ARCHITECTURE_ID "MSP430"
|
||||||
|
|
||||||
|
# elif defined(__ICCV850__)
|
||||||
|
# define ARCHITECTURE_ID "V850"
|
||||||
|
|
||||||
|
# elif defined(__ICC8051__)
|
||||||
|
# define ARCHITECTURE_ID "8051"
|
||||||
|
|
||||||
|
# elif defined(__ICCSTM8__)
|
||||||
|
# define ARCHITECTURE_ID "STM8"
|
||||||
|
|
||||||
|
# else /* unknown architecture */
|
||||||
|
# define ARCHITECTURE_ID ""
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__ghs__)
|
||||||
|
# if defined(__PPC64__)
|
||||||
|
# define ARCHITECTURE_ID "PPC64"
|
||||||
|
|
||||||
|
# elif defined(__ppc__)
|
||||||
|
# define ARCHITECTURE_ID "PPC"
|
||||||
|
|
||||||
|
# elif defined(__ARM__)
|
||||||
|
# define ARCHITECTURE_ID "ARM"
|
||||||
|
|
||||||
|
# elif defined(__x86_64__)
|
||||||
|
# define ARCHITECTURE_ID "x64"
|
||||||
|
|
||||||
|
# elif defined(__i386__)
|
||||||
|
# define ARCHITECTURE_ID "X86"
|
||||||
|
|
||||||
|
# else /* unknown architecture */
|
||||||
|
# define ARCHITECTURE_ID ""
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__TI_COMPILER_VERSION__)
|
||||||
|
# if defined(__TI_ARM__)
|
||||||
|
# define ARCHITECTURE_ID "ARM"
|
||||||
|
|
||||||
|
# elif defined(__MSP430__)
|
||||||
|
# define ARCHITECTURE_ID "MSP430"
|
||||||
|
|
||||||
|
# elif defined(__TMS320C28XX__)
|
||||||
|
# define ARCHITECTURE_ID "TMS320C28x"
|
||||||
|
|
||||||
|
# elif defined(__TMS320C6X__) || defined(_TMS320C6X)
|
||||||
|
# define ARCHITECTURE_ID "TMS320C6x"
|
||||||
|
|
||||||
|
# else /* unknown architecture */
|
||||||
|
# define ARCHITECTURE_ID ""
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
# define ARCHITECTURE_ID
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Convert integer to decimal digit literals. */
|
||||||
|
#define DEC(n) \
|
||||||
|
('0' + (((n) / 10000000)%10)), \
|
||||||
|
('0' + (((n) / 1000000)%10)), \
|
||||||
|
('0' + (((n) / 100000)%10)), \
|
||||||
|
('0' + (((n) / 10000)%10)), \
|
||||||
|
('0' + (((n) / 1000)%10)), \
|
||||||
|
('0' + (((n) / 100)%10)), \
|
||||||
|
('0' + (((n) / 10)%10)), \
|
||||||
|
('0' + ((n) % 10))
|
||||||
|
|
||||||
|
/* Convert integer to hex digit literals. */
|
||||||
|
#define HEX(n) \
|
||||||
|
('0' + ((n)>>28 & 0xF)), \
|
||||||
|
('0' + ((n)>>24 & 0xF)), \
|
||||||
|
('0' + ((n)>>20 & 0xF)), \
|
||||||
|
('0' + ((n)>>16 & 0xF)), \
|
||||||
|
('0' + ((n)>>12 & 0xF)), \
|
||||||
|
('0' + ((n)>>8 & 0xF)), \
|
||||||
|
('0' + ((n)>>4 & 0xF)), \
|
||||||
|
('0' + ((n) & 0xF))
|
||||||
|
|
||||||
|
/* Construct a string literal encoding the version number. */
|
||||||
|
#ifdef COMPILER_VERSION
|
||||||
|
char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]";
|
||||||
|
|
||||||
|
/* Construct a string literal encoding the version number components. */
|
||||||
|
#elif defined(COMPILER_VERSION_MAJOR)
|
||||||
|
char const info_version[] = {
|
||||||
|
'I', 'N', 'F', 'O', ':',
|
||||||
|
'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[',
|
||||||
|
COMPILER_VERSION_MAJOR,
|
||||||
|
# ifdef COMPILER_VERSION_MINOR
|
||||||
|
'.', COMPILER_VERSION_MINOR,
|
||||||
|
# ifdef COMPILER_VERSION_PATCH
|
||||||
|
'.', COMPILER_VERSION_PATCH,
|
||||||
|
# ifdef COMPILER_VERSION_TWEAK
|
||||||
|
'.', COMPILER_VERSION_TWEAK,
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
']','\0'};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Construct a string literal encoding the internal version number. */
|
||||||
|
#ifdef COMPILER_VERSION_INTERNAL
|
||||||
|
char const info_version_internal[] = {
|
||||||
|
'I', 'N', 'F', 'O', ':',
|
||||||
|
'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_',
|
||||||
|
'i','n','t','e','r','n','a','l','[',
|
||||||
|
COMPILER_VERSION_INTERNAL,']','\0'};
|
||||||
|
#elif defined(COMPILER_VERSION_INTERNAL_STR)
|
||||||
|
char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Construct a string literal encoding the version number components. */
|
||||||
|
#ifdef SIMULATE_VERSION_MAJOR
|
||||||
|
char const info_simulate_version[] = {
|
||||||
|
'I', 'N', 'F', 'O', ':',
|
||||||
|
's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[',
|
||||||
|
SIMULATE_VERSION_MAJOR,
|
||||||
|
# ifdef SIMULATE_VERSION_MINOR
|
||||||
|
'.', SIMULATE_VERSION_MINOR,
|
||||||
|
# ifdef SIMULATE_VERSION_PATCH
|
||||||
|
'.', SIMULATE_VERSION_PATCH,
|
||||||
|
# ifdef SIMULATE_VERSION_TWEAK
|
||||||
|
'.', SIMULATE_VERSION_TWEAK,
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
']','\0'};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Construct the string literal in pieces to prevent the source from
|
||||||
|
getting matched. Store it in a pointer rather than an array
|
||||||
|
because some compilers will just produce instructions to fill the
|
||||||
|
array rather than assigning a pointer to a static array. */
|
||||||
|
char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]";
|
||||||
|
char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(__STDC__) && !defined(__clang__)
|
||||||
|
# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__)
|
||||||
|
# define C_VERSION "90"
|
||||||
|
# else
|
||||||
|
# define C_VERSION
|
||||||
|
# endif
|
||||||
|
#elif __STDC_VERSION__ > 201710L
|
||||||
|
# define C_VERSION "23"
|
||||||
|
#elif __STDC_VERSION__ >= 201710L
|
||||||
|
# define C_VERSION "17"
|
||||||
|
#elif __STDC_VERSION__ >= 201000L
|
||||||
|
# define C_VERSION "11"
|
||||||
|
#elif __STDC_VERSION__ >= 199901L
|
||||||
|
# define C_VERSION "99"
|
||||||
|
#else
|
||||||
|
# define C_VERSION "90"
|
||||||
|
#endif
|
||||||
|
const char* info_language_standard_default =
|
||||||
|
"INFO" ":" "standard_default[" C_VERSION "]";
|
||||||
|
|
||||||
|
const char* info_language_extensions_default = "INFO" ":" "extensions_default["
|
||||||
|
/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */
|
||||||
|
#if (defined(__clang__) || defined(__GNUC__) || \
|
||||||
|
defined(__TI_COMPILER_VERSION__)) && \
|
||||||
|
!defined(__STRICT_ANSI__) && !defined(_MSC_VER)
|
||||||
|
"ON"
|
||||||
|
#else
|
||||||
|
"OFF"
|
||||||
|
#endif
|
||||||
|
"]";
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifdef ID_VOID_MAIN
|
||||||
|
void main() {}
|
||||||
|
#else
|
||||||
|
# if defined(__CLASSIC_C__)
|
||||||
|
int main(argc, argv) int argc; char *argv[];
|
||||||
|
# else
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
# endif
|
||||||
|
{
|
||||||
|
int require = 0;
|
||||||
|
require += info_compiler[argc];
|
||||||
|
require += info_platform[argc];
|
||||||
|
require += info_arch[argc];
|
||||||
|
#ifdef COMPILER_VERSION_MAJOR
|
||||||
|
require += info_version[argc];
|
||||||
|
#endif
|
||||||
|
#ifdef COMPILER_VERSION_INTERNAL
|
||||||
|
require += info_version_internal[argc];
|
||||||
|
#endif
|
||||||
|
#ifdef SIMULATE_ID
|
||||||
|
require += info_simulate[argc];
|
||||||
|
#endif
|
||||||
|
#ifdef SIMULATE_VERSION_MAJOR
|
||||||
|
require += info_simulate_version[argc];
|
||||||
|
#endif
|
||||||
|
#if defined(__CRAYXT_COMPUTE_LINUX_TARGET)
|
||||||
|
require += info_cray[argc];
|
||||||
|
#endif
|
||||||
|
require += info_language_standard_default[argc];
|
||||||
|
require += info_language_extensions_default[argc];
|
||||||
|
(void)argv;
|
||||||
|
return require;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
BIN
Binary file not shown.
+791
@@ -0,0 +1,791 @@
|
|||||||
|
/* This source file must have a .cpp extension so that all C++ compilers
|
||||||
|
recognize the extension without flags. Borland does not know .cxx for
|
||||||
|
example. */
|
||||||
|
#ifndef __cplusplus
|
||||||
|
# error "A C compiler has been selected for C++."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(__has_include)
|
||||||
|
/* If the compiler does not have __has_include, pretend the answer is
|
||||||
|
always no. */
|
||||||
|
# define __has_include(x) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Version number components: V=Version, R=Revision, P=Patch
|
||||||
|
Version date components: YYYY=Year, MM=Month, DD=Day */
|
||||||
|
|
||||||
|
#if defined(__COMO__)
|
||||||
|
# define COMPILER_ID "Comeau"
|
||||||
|
/* __COMO_VERSION__ = VRR */
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100)
|
||||||
|
|
||||||
|
#elif defined(__INTEL_COMPILER) || defined(__ICC)
|
||||||
|
# define COMPILER_ID "Intel"
|
||||||
|
# if defined(_MSC_VER)
|
||||||
|
# define SIMULATE_ID "MSVC"
|
||||||
|
# endif
|
||||||
|
# if defined(__GNUC__)
|
||||||
|
# define SIMULATE_ID "GNU"
|
||||||
|
# endif
|
||||||
|
/* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later,
|
||||||
|
except that a few beta releases use the old format with V=2021. */
|
||||||
|
# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10)
|
||||||
|
# if defined(__INTEL_COMPILER_UPDATE)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE)
|
||||||
|
# else
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10)
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE)
|
||||||
|
/* The third version component from --version is an update index,
|
||||||
|
but no macro is provided for it. */
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(0)
|
||||||
|
# endif
|
||||||
|
# if defined(__INTEL_COMPILER_BUILD_DATE)
|
||||||
|
/* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */
|
||||||
|
# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE)
|
||||||
|
# endif
|
||||||
|
# if defined(_MSC_VER)
|
||||||
|
/* _MSC_VER = VVRR */
|
||||||
|
# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
|
||||||
|
# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
|
||||||
|
# endif
|
||||||
|
# if defined(__GNUC__)
|
||||||
|
# define SIMULATE_VERSION_MAJOR DEC(__GNUC__)
|
||||||
|
# elif defined(__GNUG__)
|
||||||
|
# define SIMULATE_VERSION_MAJOR DEC(__GNUG__)
|
||||||
|
# endif
|
||||||
|
# if defined(__GNUC_MINOR__)
|
||||||
|
# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__)
|
||||||
|
# endif
|
||||||
|
# if defined(__GNUC_PATCHLEVEL__)
|
||||||
|
# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER)
|
||||||
|
# define COMPILER_ID "IntelLLVM"
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# define SIMULATE_ID "MSVC"
|
||||||
|
#endif
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
# define SIMULATE_ID "GNU"
|
||||||
|
#endif
|
||||||
|
/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and
|
||||||
|
* later. Look for 6 digit vs. 8 digit version number to decide encoding.
|
||||||
|
* VVVV is no smaller than the current year when a version is released.
|
||||||
|
*/
|
||||||
|
#if __INTEL_LLVM_COMPILER < 1000000L
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10)
|
||||||
|
#else
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100)
|
||||||
|
#endif
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
/* _MSC_VER = VVRR */
|
||||||
|
# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
|
||||||
|
# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
|
||||||
|
#endif
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
# define SIMULATE_VERSION_MAJOR DEC(__GNUC__)
|
||||||
|
#elif defined(__GNUG__)
|
||||||
|
# define SIMULATE_VERSION_MAJOR DEC(__GNUG__)
|
||||||
|
#endif
|
||||||
|
#if defined(__GNUC_MINOR__)
|
||||||
|
# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__)
|
||||||
|
#endif
|
||||||
|
#if defined(__GNUC_PATCHLEVEL__)
|
||||||
|
# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined(__PATHCC__)
|
||||||
|
# define COMPILER_ID "PathScale"
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__PATHCC__)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__)
|
||||||
|
# if defined(__PATHCC_PATCHLEVEL__)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__)
|
||||||
|
# define COMPILER_ID "Embarcadero"
|
||||||
|
# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF)
|
||||||
|
# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF)
|
||||||
|
|
||||||
|
#elif defined(__BORLANDC__)
|
||||||
|
# define COMPILER_ID "Borland"
|
||||||
|
/* __BORLANDC__ = 0xVRR */
|
||||||
|
# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8)
|
||||||
|
# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF)
|
||||||
|
|
||||||
|
#elif defined(__WATCOMC__) && __WATCOMC__ < 1200
|
||||||
|
# define COMPILER_ID "Watcom"
|
||||||
|
/* __WATCOMC__ = VVRR */
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
|
||||||
|
# if (__WATCOMC__ % 10) > 0
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__WATCOMC__)
|
||||||
|
# define COMPILER_ID "OpenWatcom"
|
||||||
|
/* __WATCOMC__ = VVRP + 1100 */
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
|
||||||
|
# if (__WATCOMC__ % 10) > 0
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__SUNPRO_CC)
|
||||||
|
# define COMPILER_ID "SunPro"
|
||||||
|
# if __SUNPRO_CC >= 0x5100
|
||||||
|
/* __SUNPRO_CC = 0xVRRP */
|
||||||
|
# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12)
|
||||||
|
# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF)
|
||||||
|
# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF)
|
||||||
|
# else
|
||||||
|
/* __SUNPRO_CC = 0xVRP */
|
||||||
|
# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8)
|
||||||
|
# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF)
|
||||||
|
# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__HP_aCC)
|
||||||
|
# define COMPILER_ID "HP"
|
||||||
|
/* __HP_aCC = VVRRPP */
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100)
|
||||||
|
|
||||||
|
#elif defined(__DECCXX)
|
||||||
|
# define COMPILER_ID "Compaq"
|
||||||
|
/* __DECCXX_VER = VVRRTPPPP */
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000)
|
||||||
|
|
||||||
|
#elif defined(__IBMCPP__) && defined(__COMPILER_VER__)
|
||||||
|
# define COMPILER_ID "zOS"
|
||||||
|
/* __IBMCPP__ = VRP */
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10)
|
||||||
|
|
||||||
|
#elif defined(__ibmxl__) && defined(__clang__)
|
||||||
|
# define COMPILER_ID "XLClang"
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__)
|
||||||
|
# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__)
|
||||||
|
|
||||||
|
|
||||||
|
#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800
|
||||||
|
# define COMPILER_ID "XL"
|
||||||
|
/* __IBMCPP__ = VRP */
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10)
|
||||||
|
|
||||||
|
#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800
|
||||||
|
# define COMPILER_ID "VisualAge"
|
||||||
|
/* __IBMCPP__ = VRP */
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10)
|
||||||
|
|
||||||
|
#elif defined(__NVCOMPILER)
|
||||||
|
# define COMPILER_ID "NVHPC"
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__)
|
||||||
|
# if defined(__NVCOMPILER_PATCHLEVEL__)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__PGI)
|
||||||
|
# define COMPILER_ID "PGI"
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__PGIC__)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__)
|
||||||
|
# if defined(__PGIC_PATCHLEVEL__)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(_CRAYC)
|
||||||
|
# define COMPILER_ID "Cray"
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR)
|
||||||
|
|
||||||
|
#elif defined(__TI_COMPILER_VERSION__)
|
||||||
|
# define COMPILER_ID "TI"
|
||||||
|
/* __TI_COMPILER_VERSION__ = VVVRRRPPP */
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000)
|
||||||
|
|
||||||
|
#elif defined(__CLANG_FUJITSU)
|
||||||
|
# define COMPILER_ID "FujitsuClang"
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__FCC_major__)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__FCC_minor__)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__)
|
||||||
|
# define COMPILER_VERSION_INTERNAL_STR __clang_version__
|
||||||
|
|
||||||
|
|
||||||
|
#elif defined(__FUJITSU)
|
||||||
|
# define COMPILER_ID "Fujitsu"
|
||||||
|
# if defined(__FCC_version__)
|
||||||
|
# define COMPILER_VERSION __FCC_version__
|
||||||
|
# elif defined(__FCC_major__)
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__FCC_major__)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__FCC_minor__)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__)
|
||||||
|
# endif
|
||||||
|
# if defined(__fcc_version)
|
||||||
|
# define COMPILER_VERSION_INTERNAL DEC(__fcc_version)
|
||||||
|
# elif defined(__FCC_VERSION)
|
||||||
|
# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
|
||||||
|
#elif defined(__ghs__)
|
||||||
|
# define COMPILER_ID "GHS"
|
||||||
|
/* __GHS_VERSION_NUMBER = VVVVRP */
|
||||||
|
# ifdef __GHS_VERSION_NUMBER
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__SCO_VERSION__)
|
||||||
|
# define COMPILER_ID "SCO"
|
||||||
|
|
||||||
|
#elif defined(__ARMCC_VERSION) && !defined(__clang__)
|
||||||
|
# define COMPILER_ID "ARMCC"
|
||||||
|
#if __ARMCC_VERSION >= 1000000
|
||||||
|
/* __ARMCC_VERSION = VRRPPPP */
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
|
||||||
|
#else
|
||||||
|
/* __ARMCC_VERSION = VRPPPP */
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#elif defined(__clang__) && defined(__apple_build_version__)
|
||||||
|
# define COMPILER_ID "AppleClang"
|
||||||
|
# if defined(_MSC_VER)
|
||||||
|
# define SIMULATE_ID "MSVC"
|
||||||
|
# endif
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
|
||||||
|
# if defined(_MSC_VER)
|
||||||
|
/* _MSC_VER = VVRR */
|
||||||
|
# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
|
||||||
|
# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
|
||||||
|
# endif
|
||||||
|
# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__)
|
||||||
|
|
||||||
|
#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION)
|
||||||
|
# define COMPILER_ID "ARMClang"
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000)
|
||||||
|
# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION)
|
||||||
|
|
||||||
|
#elif defined(__clang__)
|
||||||
|
# define COMPILER_ID "Clang"
|
||||||
|
# if defined(_MSC_VER)
|
||||||
|
# define SIMULATE_ID "MSVC"
|
||||||
|
# endif
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
|
||||||
|
# if defined(_MSC_VER)
|
||||||
|
/* _MSC_VER = VVRR */
|
||||||
|
# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
|
||||||
|
# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||||
|
# define COMPILER_ID "GNU"
|
||||||
|
# if defined(__GNUC__)
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__GNUC__)
|
||||||
|
# else
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(__GNUG__)
|
||||||
|
# endif
|
||||||
|
# if defined(__GNUC_MINOR__)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__)
|
||||||
|
# endif
|
||||||
|
# if defined(__GNUC_PATCHLEVEL__)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
# define COMPILER_ID "MSVC"
|
||||||
|
/* _MSC_VER = VVRR */
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100)
|
||||||
|
# if defined(_MSC_FULL_VER)
|
||||||
|
# if _MSC_VER >= 1400
|
||||||
|
/* _MSC_FULL_VER = VVRRPPPPP */
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000)
|
||||||
|
# else
|
||||||
|
/* _MSC_FULL_VER = VVRRPPPP */
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000)
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# if defined(_MSC_BUILD)
|
||||||
|
# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__)
|
||||||
|
# define COMPILER_ID "ADSP"
|
||||||
|
#if defined(__VISUALDSPVERSION__)
|
||||||
|
/* __VISUALDSPVERSION__ = 0xVVRRPP00 */
|
||||||
|
# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24)
|
||||||
|
# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF)
|
||||||
|
# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
|
||||||
|
# define COMPILER_ID "IAR"
|
||||||
|
# if defined(__VER__) && defined(__ICCARM__)
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000)
|
||||||
|
# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000)
|
||||||
|
# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
|
||||||
|
# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__))
|
||||||
|
# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100)
|
||||||
|
# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100))
|
||||||
|
# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__)
|
||||||
|
# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
|
||||||
|
/* These compilers are either not known or too old to define an
|
||||||
|
identification macro. Try to identify the platform and guess that
|
||||||
|
it is the native compiler. */
|
||||||
|
#elif defined(__hpux) || defined(__hpua)
|
||||||
|
# define COMPILER_ID "HP"
|
||||||
|
|
||||||
|
#else /* unknown compiler */
|
||||||
|
# define COMPILER_ID ""
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Construct the string literal in pieces to prevent the source from
|
||||||
|
getting matched. Store it in a pointer rather than an array
|
||||||
|
because some compilers will just produce instructions to fill the
|
||||||
|
array rather than assigning a pointer to a static array. */
|
||||||
|
char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]";
|
||||||
|
#ifdef SIMULATE_ID
|
||||||
|
char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __QNXNTO__
|
||||||
|
char const* qnxnto = "INFO" ":" "qnxnto[]";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__CRAYXT_COMPUTE_LINUX_TARGET)
|
||||||
|
char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define STRINGIFY_HELPER(X) #X
|
||||||
|
#define STRINGIFY(X) STRINGIFY_HELPER(X)
|
||||||
|
|
||||||
|
/* Identify known platforms by name. */
|
||||||
|
#if defined(__linux) || defined(__linux__) || defined(linux)
|
||||||
|
# define PLATFORM_ID "Linux"
|
||||||
|
|
||||||
|
#elif defined(__MSYS__)
|
||||||
|
# define PLATFORM_ID "MSYS"
|
||||||
|
|
||||||
|
#elif defined(__CYGWIN__)
|
||||||
|
# define PLATFORM_ID "Cygwin"
|
||||||
|
|
||||||
|
#elif defined(__MINGW32__)
|
||||||
|
# define PLATFORM_ID "MinGW"
|
||||||
|
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
# define PLATFORM_ID "Darwin"
|
||||||
|
|
||||||
|
#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
|
||||||
|
# define PLATFORM_ID "Windows"
|
||||||
|
|
||||||
|
#elif defined(__FreeBSD__) || defined(__FreeBSD)
|
||||||
|
# define PLATFORM_ID "FreeBSD"
|
||||||
|
|
||||||
|
#elif defined(__NetBSD__) || defined(__NetBSD)
|
||||||
|
# define PLATFORM_ID "NetBSD"
|
||||||
|
|
||||||
|
#elif defined(__OpenBSD__) || defined(__OPENBSD)
|
||||||
|
# define PLATFORM_ID "OpenBSD"
|
||||||
|
|
||||||
|
#elif defined(__sun) || defined(sun)
|
||||||
|
# define PLATFORM_ID "SunOS"
|
||||||
|
|
||||||
|
#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__)
|
||||||
|
# define PLATFORM_ID "AIX"
|
||||||
|
|
||||||
|
#elif defined(__hpux) || defined(__hpux__)
|
||||||
|
# define PLATFORM_ID "HP-UX"
|
||||||
|
|
||||||
|
#elif defined(__HAIKU__)
|
||||||
|
# define PLATFORM_ID "Haiku"
|
||||||
|
|
||||||
|
#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS)
|
||||||
|
# define PLATFORM_ID "BeOS"
|
||||||
|
|
||||||
|
#elif defined(__QNX__) || defined(__QNXNTO__)
|
||||||
|
# define PLATFORM_ID "QNX"
|
||||||
|
|
||||||
|
#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__)
|
||||||
|
# define PLATFORM_ID "Tru64"
|
||||||
|
|
||||||
|
#elif defined(__riscos) || defined(__riscos__)
|
||||||
|
# define PLATFORM_ID "RISCos"
|
||||||
|
|
||||||
|
#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__)
|
||||||
|
# define PLATFORM_ID "SINIX"
|
||||||
|
|
||||||
|
#elif defined(__UNIX_SV__)
|
||||||
|
# define PLATFORM_ID "UNIX_SV"
|
||||||
|
|
||||||
|
#elif defined(__bsdos__)
|
||||||
|
# define PLATFORM_ID "BSDOS"
|
||||||
|
|
||||||
|
#elif defined(_MPRAS) || defined(MPRAS)
|
||||||
|
# define PLATFORM_ID "MP-RAS"
|
||||||
|
|
||||||
|
#elif defined(__osf) || defined(__osf__)
|
||||||
|
# define PLATFORM_ID "OSF1"
|
||||||
|
|
||||||
|
#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv)
|
||||||
|
# define PLATFORM_ID "SCO_SV"
|
||||||
|
|
||||||
|
#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX)
|
||||||
|
# define PLATFORM_ID "ULTRIX"
|
||||||
|
|
||||||
|
#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX)
|
||||||
|
# define PLATFORM_ID "Xenix"
|
||||||
|
|
||||||
|
#elif defined(__WATCOMC__)
|
||||||
|
# if defined(__LINUX__)
|
||||||
|
# define PLATFORM_ID "Linux"
|
||||||
|
|
||||||
|
# elif defined(__DOS__)
|
||||||
|
# define PLATFORM_ID "DOS"
|
||||||
|
|
||||||
|
# elif defined(__OS2__)
|
||||||
|
# define PLATFORM_ID "OS2"
|
||||||
|
|
||||||
|
# elif defined(__WINDOWS__)
|
||||||
|
# define PLATFORM_ID "Windows3x"
|
||||||
|
|
||||||
|
# elif defined(__VXWORKS__)
|
||||||
|
# define PLATFORM_ID "VxWorks"
|
||||||
|
|
||||||
|
# else /* unknown platform */
|
||||||
|
# define PLATFORM_ID
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__INTEGRITY)
|
||||||
|
# if defined(INT_178B)
|
||||||
|
# define PLATFORM_ID "Integrity178"
|
||||||
|
|
||||||
|
# else /* regular Integrity */
|
||||||
|
# define PLATFORM_ID "Integrity"
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#else /* unknown platform */
|
||||||
|
# define PLATFORM_ID
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* For windows compilers MSVC and Intel we can determine
|
||||||
|
the architecture of the compiler being used. This is because
|
||||||
|
the compilers do not have flags that can change the architecture,
|
||||||
|
but rather depend on which compiler is being used
|
||||||
|
*/
|
||||||
|
#if defined(_WIN32) && defined(_MSC_VER)
|
||||||
|
# if defined(_M_IA64)
|
||||||
|
# define ARCHITECTURE_ID "IA64"
|
||||||
|
|
||||||
|
# elif defined(_M_ARM64EC)
|
||||||
|
# define ARCHITECTURE_ID "ARM64EC"
|
||||||
|
|
||||||
|
# elif defined(_M_X64) || defined(_M_AMD64)
|
||||||
|
# define ARCHITECTURE_ID "x64"
|
||||||
|
|
||||||
|
# elif defined(_M_IX86)
|
||||||
|
# define ARCHITECTURE_ID "X86"
|
||||||
|
|
||||||
|
# elif defined(_M_ARM64)
|
||||||
|
# define ARCHITECTURE_ID "ARM64"
|
||||||
|
|
||||||
|
# elif defined(_M_ARM)
|
||||||
|
# if _M_ARM == 4
|
||||||
|
# define ARCHITECTURE_ID "ARMV4I"
|
||||||
|
# elif _M_ARM == 5
|
||||||
|
# define ARCHITECTURE_ID "ARMV5I"
|
||||||
|
# else
|
||||||
|
# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# elif defined(_M_MIPS)
|
||||||
|
# define ARCHITECTURE_ID "MIPS"
|
||||||
|
|
||||||
|
# elif defined(_M_SH)
|
||||||
|
# define ARCHITECTURE_ID "SHx"
|
||||||
|
|
||||||
|
# else /* unknown architecture */
|
||||||
|
# define ARCHITECTURE_ID ""
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__WATCOMC__)
|
||||||
|
# if defined(_M_I86)
|
||||||
|
# define ARCHITECTURE_ID "I86"
|
||||||
|
|
||||||
|
# elif defined(_M_IX86)
|
||||||
|
# define ARCHITECTURE_ID "X86"
|
||||||
|
|
||||||
|
# else /* unknown architecture */
|
||||||
|
# define ARCHITECTURE_ID ""
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
|
||||||
|
# if defined(__ICCARM__)
|
||||||
|
# define ARCHITECTURE_ID "ARM"
|
||||||
|
|
||||||
|
# elif defined(__ICCRX__)
|
||||||
|
# define ARCHITECTURE_ID "RX"
|
||||||
|
|
||||||
|
# elif defined(__ICCRH850__)
|
||||||
|
# define ARCHITECTURE_ID "RH850"
|
||||||
|
|
||||||
|
# elif defined(__ICCRL78__)
|
||||||
|
# define ARCHITECTURE_ID "RL78"
|
||||||
|
|
||||||
|
# elif defined(__ICCRISCV__)
|
||||||
|
# define ARCHITECTURE_ID "RISCV"
|
||||||
|
|
||||||
|
# elif defined(__ICCAVR__)
|
||||||
|
# define ARCHITECTURE_ID "AVR"
|
||||||
|
|
||||||
|
# elif defined(__ICC430__)
|
||||||
|
# define ARCHITECTURE_ID "MSP430"
|
||||||
|
|
||||||
|
# elif defined(__ICCV850__)
|
||||||
|
# define ARCHITECTURE_ID "V850"
|
||||||
|
|
||||||
|
# elif defined(__ICC8051__)
|
||||||
|
# define ARCHITECTURE_ID "8051"
|
||||||
|
|
||||||
|
# elif defined(__ICCSTM8__)
|
||||||
|
# define ARCHITECTURE_ID "STM8"
|
||||||
|
|
||||||
|
# else /* unknown architecture */
|
||||||
|
# define ARCHITECTURE_ID ""
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__ghs__)
|
||||||
|
# if defined(__PPC64__)
|
||||||
|
# define ARCHITECTURE_ID "PPC64"
|
||||||
|
|
||||||
|
# elif defined(__ppc__)
|
||||||
|
# define ARCHITECTURE_ID "PPC"
|
||||||
|
|
||||||
|
# elif defined(__ARM__)
|
||||||
|
# define ARCHITECTURE_ID "ARM"
|
||||||
|
|
||||||
|
# elif defined(__x86_64__)
|
||||||
|
# define ARCHITECTURE_ID "x64"
|
||||||
|
|
||||||
|
# elif defined(__i386__)
|
||||||
|
# define ARCHITECTURE_ID "X86"
|
||||||
|
|
||||||
|
# else /* unknown architecture */
|
||||||
|
# define ARCHITECTURE_ID ""
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif defined(__TI_COMPILER_VERSION__)
|
||||||
|
# if defined(__TI_ARM__)
|
||||||
|
# define ARCHITECTURE_ID "ARM"
|
||||||
|
|
||||||
|
# elif defined(__MSP430__)
|
||||||
|
# define ARCHITECTURE_ID "MSP430"
|
||||||
|
|
||||||
|
# elif defined(__TMS320C28XX__)
|
||||||
|
# define ARCHITECTURE_ID "TMS320C28x"
|
||||||
|
|
||||||
|
# elif defined(__TMS320C6X__) || defined(_TMS320C6X)
|
||||||
|
# define ARCHITECTURE_ID "TMS320C6x"
|
||||||
|
|
||||||
|
# else /* unknown architecture */
|
||||||
|
# define ARCHITECTURE_ID ""
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
# define ARCHITECTURE_ID
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Convert integer to decimal digit literals. */
|
||||||
|
#define DEC(n) \
|
||||||
|
('0' + (((n) / 10000000)%10)), \
|
||||||
|
('0' + (((n) / 1000000)%10)), \
|
||||||
|
('0' + (((n) / 100000)%10)), \
|
||||||
|
('0' + (((n) / 10000)%10)), \
|
||||||
|
('0' + (((n) / 1000)%10)), \
|
||||||
|
('0' + (((n) / 100)%10)), \
|
||||||
|
('0' + (((n) / 10)%10)), \
|
||||||
|
('0' + ((n) % 10))
|
||||||
|
|
||||||
|
/* Convert integer to hex digit literals. */
|
||||||
|
#define HEX(n) \
|
||||||
|
('0' + ((n)>>28 & 0xF)), \
|
||||||
|
('0' + ((n)>>24 & 0xF)), \
|
||||||
|
('0' + ((n)>>20 & 0xF)), \
|
||||||
|
('0' + ((n)>>16 & 0xF)), \
|
||||||
|
('0' + ((n)>>12 & 0xF)), \
|
||||||
|
('0' + ((n)>>8 & 0xF)), \
|
||||||
|
('0' + ((n)>>4 & 0xF)), \
|
||||||
|
('0' + ((n) & 0xF))
|
||||||
|
|
||||||
|
/* Construct a string literal encoding the version number. */
|
||||||
|
#ifdef COMPILER_VERSION
|
||||||
|
char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]";
|
||||||
|
|
||||||
|
/* Construct a string literal encoding the version number components. */
|
||||||
|
#elif defined(COMPILER_VERSION_MAJOR)
|
||||||
|
char const info_version[] = {
|
||||||
|
'I', 'N', 'F', 'O', ':',
|
||||||
|
'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[',
|
||||||
|
COMPILER_VERSION_MAJOR,
|
||||||
|
# ifdef COMPILER_VERSION_MINOR
|
||||||
|
'.', COMPILER_VERSION_MINOR,
|
||||||
|
# ifdef COMPILER_VERSION_PATCH
|
||||||
|
'.', COMPILER_VERSION_PATCH,
|
||||||
|
# ifdef COMPILER_VERSION_TWEAK
|
||||||
|
'.', COMPILER_VERSION_TWEAK,
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
']','\0'};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Construct a string literal encoding the internal version number. */
|
||||||
|
#ifdef COMPILER_VERSION_INTERNAL
|
||||||
|
char const info_version_internal[] = {
|
||||||
|
'I', 'N', 'F', 'O', ':',
|
||||||
|
'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_',
|
||||||
|
'i','n','t','e','r','n','a','l','[',
|
||||||
|
COMPILER_VERSION_INTERNAL,']','\0'};
|
||||||
|
#elif defined(COMPILER_VERSION_INTERNAL_STR)
|
||||||
|
char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Construct a string literal encoding the version number components. */
|
||||||
|
#ifdef SIMULATE_VERSION_MAJOR
|
||||||
|
char const info_simulate_version[] = {
|
||||||
|
'I', 'N', 'F', 'O', ':',
|
||||||
|
's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[',
|
||||||
|
SIMULATE_VERSION_MAJOR,
|
||||||
|
# ifdef SIMULATE_VERSION_MINOR
|
||||||
|
'.', SIMULATE_VERSION_MINOR,
|
||||||
|
# ifdef SIMULATE_VERSION_PATCH
|
||||||
|
'.', SIMULATE_VERSION_PATCH,
|
||||||
|
# ifdef SIMULATE_VERSION_TWEAK
|
||||||
|
'.', SIMULATE_VERSION_TWEAK,
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
']','\0'};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Construct the string literal in pieces to prevent the source from
|
||||||
|
getting matched. Store it in a pointer rather than an array
|
||||||
|
because some compilers will just produce instructions to fill the
|
||||||
|
array rather than assigning a pointer to a static array. */
|
||||||
|
char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]";
|
||||||
|
char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L
|
||||||
|
# if defined(__INTEL_CXX11_MODE__)
|
||||||
|
# if defined(__cpp_aggregate_nsdmi)
|
||||||
|
# define CXX_STD 201402L
|
||||||
|
# else
|
||||||
|
# define CXX_STD 201103L
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# define CXX_STD 199711L
|
||||||
|
# endif
|
||||||
|
#elif defined(_MSC_VER) && defined(_MSVC_LANG)
|
||||||
|
# define CXX_STD _MSVC_LANG
|
||||||
|
#else
|
||||||
|
# define CXX_STD __cplusplus
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char* info_language_standard_default = "INFO" ":" "standard_default["
|
||||||
|
#if CXX_STD > 202002L
|
||||||
|
"23"
|
||||||
|
#elif CXX_STD > 201703L
|
||||||
|
"20"
|
||||||
|
#elif CXX_STD >= 201703L
|
||||||
|
"17"
|
||||||
|
#elif CXX_STD >= 201402L
|
||||||
|
"14"
|
||||||
|
#elif CXX_STD >= 201103L
|
||||||
|
"11"
|
||||||
|
#else
|
||||||
|
"98"
|
||||||
|
#endif
|
||||||
|
"]";
|
||||||
|
|
||||||
|
const char* info_language_extensions_default = "INFO" ":" "extensions_default["
|
||||||
|
/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */
|
||||||
|
#if (defined(__clang__) || defined(__GNUC__) || \
|
||||||
|
defined(__TI_COMPILER_VERSION__)) && \
|
||||||
|
!defined(__STRICT_ANSI__) && !defined(_MSC_VER)
|
||||||
|
"ON"
|
||||||
|
#else
|
||||||
|
"OFF"
|
||||||
|
#endif
|
||||||
|
"]";
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
int require = 0;
|
||||||
|
require += info_compiler[argc];
|
||||||
|
require += info_platform[argc];
|
||||||
|
#ifdef COMPILER_VERSION_MAJOR
|
||||||
|
require += info_version[argc];
|
||||||
|
#endif
|
||||||
|
#ifdef COMPILER_VERSION_INTERNAL
|
||||||
|
require += info_version_internal[argc];
|
||||||
|
#endif
|
||||||
|
#ifdef SIMULATE_ID
|
||||||
|
require += info_simulate[argc];
|
||||||
|
#endif
|
||||||
|
#ifdef SIMULATE_VERSION_MAJOR
|
||||||
|
require += info_simulate_version[argc];
|
||||||
|
#endif
|
||||||
|
#if defined(__CRAYXT_COMPUTE_LINUX_TARGET)
|
||||||
|
require += info_cray[argc];
|
||||||
|
#endif
|
||||||
|
require += info_language_standard_default[argc];
|
||||||
|
require += info_language_extensions_default[argc];
|
||||||
|
(void)argv;
|
||||||
|
return require;
|
||||||
|
}
|
||||||
BIN
Binary file not shown.
@@ -0,0 +1,3 @@
|
|||||||
|
/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/x86/CMakeFiles/appmodules.dir
|
||||||
|
/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/x86/CMakeFiles/edit_cache.dir
|
||||||
|
/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/x86/CMakeFiles/rebuild_cache.dir
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# CMAKE generated file: DO NOT EDIT!
|
||||||
|
# Generated by CMake Version 3.22
|
||||||
|
cmake_policy(SET CMP0009 NEW)
|
||||||
|
|
||||||
|
# input_SRC at /home/echo/dev/prototype/apps/mobile/node_modules/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake:55 (file)
|
||||||
|
file(GLOB NEW_GLOB LIST_DIRECTORIES true "/home/echo/dev/prototype/apps/mobile/android/app/build/generated/autolinking/src/main/jni/*.cpp")
|
||||||
|
set(OLD_GLOB
|
||||||
|
)
|
||||||
|
if(NOT "${NEW_GLOB}" STREQUAL "${OLD_GLOB}")
|
||||||
|
message("-- GLOB mismatch!")
|
||||||
|
file(TOUCH_NOCREATE "/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/x86/CMakeFiles/cmake.verify_globs")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# override_cpp_SRC at /home/echo/dev/prototype/apps/mobile/node_modules/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake:50 (file)
|
||||||
|
# input_SRC at /home/echo/dev/prototype/apps/mobile/node_modules/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake:55 (file)
|
||||||
|
file(GLOB NEW_GLOB LIST_DIRECTORIES true "/home/echo/dev/prototype/apps/mobile/node_modules/react-native/ReactAndroid/cmake-utils/default-app-setup/*.cpp")
|
||||||
|
set(OLD_GLOB
|
||||||
|
"/home/echo/dev/prototype/apps/mobile/node_modules/react-native/ReactAndroid/cmake-utils/default-app-setup/OnLoad.cpp"
|
||||||
|
)
|
||||||
|
if(NOT "${NEW_GLOB}" STREQUAL "${OLD_GLOB}")
|
||||||
|
message("-- GLOB mismatch!")
|
||||||
|
file(TOUCH_NOCREATE "/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/x86/CMakeFiles/cmake.verify_globs")
|
||||||
|
endif()
|
||||||
BIN
Binary file not shown.
+4
@@ -0,0 +1,4 @@
|
|||||||
|
# ninja log v5
|
||||||
|
0 17 1764608951217248929 CMakeFiles/foo.dir/foo.cpp.o cf03112569101c0d
|
||||||
|
0 17 1764608951217248929 CMakeFiles/boo.dir/main.cpp.o a40c4ac8f9333fbb
|
||||||
|
17 47 1764608951246597989 libfoo.a 46ab43a90edc58a3
|
||||||
+281
@@ -0,0 +1,281 @@
|
|||||||
|
# This is the CMakeCache file.
|
||||||
|
# For build in directory: /home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/x86/CMakeFiles/_CMakeLTOTest-CXX/bin
|
||||||
|
# It was generated by CMake: /home/echo/Android/Sdk/cmake/3.22.1/bin/cmake
|
||||||
|
# You can edit this file to change values found and used by cmake.
|
||||||
|
# If you do not want to change any of the values, simply exit the editor.
|
||||||
|
# If you do want to change a value, simply edit, save, and exit the editor.
|
||||||
|
# The syntax for the file is as follows:
|
||||||
|
# KEY:TYPE=VALUE
|
||||||
|
# KEY is the name of a variable in the cache.
|
||||||
|
# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!.
|
||||||
|
# VALUE is the current value for the KEY.
|
||||||
|
|
||||||
|
########################
|
||||||
|
# EXTERNAL cache entries
|
||||||
|
########################
|
||||||
|
|
||||||
|
//Archiver
|
||||||
|
CMAKE_AR:FILEPATH=/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar
|
||||||
|
|
||||||
|
//Flags used by the compiler during all build types.
|
||||||
|
CMAKE_ASM_FLAGS:STRING=
|
||||||
|
|
||||||
|
//Flags used by the compiler during debug builds.
|
||||||
|
CMAKE_ASM_FLAGS_DEBUG:STRING=
|
||||||
|
|
||||||
|
//Flags used by the compiler during release builds.
|
||||||
|
CMAKE_ASM_FLAGS_RELEASE:STRING=
|
||||||
|
|
||||||
|
//Choose the type of build, options are: None Debug Release RelWithDebInfo
|
||||||
|
// MinSizeRel ...
|
||||||
|
CMAKE_BUILD_TYPE:STRING=
|
||||||
|
|
||||||
|
//Flags used by the compiler during all build types.
|
||||||
|
CMAKE_CXX_FLAGS:STRING=
|
||||||
|
|
||||||
|
//Flags used by the compiler during debug builds.
|
||||||
|
CMAKE_CXX_FLAGS_DEBUG:STRING=
|
||||||
|
|
||||||
|
//Flags used by the CXX compiler during MINSIZEREL builds.
|
||||||
|
CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
|
||||||
|
|
||||||
|
//Flags used by the compiler during release builds.
|
||||||
|
CMAKE_CXX_FLAGS_RELEASE:STRING=
|
||||||
|
|
||||||
|
//Flags used by the CXX compiler during RELWITHDEBINFO builds.
|
||||||
|
CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
|
||||||
|
|
||||||
|
//Libraries linked by default with all C++ applications.
|
||||||
|
CMAKE_CXX_STANDARD_LIBRARIES:STRING=-latomic -lm
|
||||||
|
|
||||||
|
//Flags used by the compiler during all build types.
|
||||||
|
CMAKE_C_FLAGS:STRING=
|
||||||
|
|
||||||
|
//Flags used by the compiler during debug builds.
|
||||||
|
CMAKE_C_FLAGS_DEBUG:STRING=
|
||||||
|
|
||||||
|
//Flags used by the compiler during release builds.
|
||||||
|
CMAKE_C_FLAGS_RELEASE:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker.
|
||||||
|
CMAKE_EXE_LINKER_FLAGS:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during DEBUG builds.
|
||||||
|
CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during MINSIZEREL builds.
|
||||||
|
CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during RELEASE builds.
|
||||||
|
CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during RELWITHDEBINFO builds.
|
||||||
|
CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING=
|
||||||
|
|
||||||
|
//Enable/Disable output of compile commands during generation.
|
||||||
|
CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=
|
||||||
|
|
||||||
|
//Install path prefix, prepended onto install directories.
|
||||||
|
CMAKE_INSTALL_PREFIX:PATH=/usr/local
|
||||||
|
|
||||||
|
//No help, variable specified on the command line.
|
||||||
|
CMAKE_INTERPROCEDURAL_OPTIMIZATION:UNINITIALIZED=ON
|
||||||
|
|
||||||
|
//make program
|
||||||
|
CMAKE_MAKE_PROGRAM:FILEPATH=/home/echo/Android/Sdk/cmake/3.22.1/bin/ninja
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of modules.
|
||||||
|
CMAKE_MODULE_LINKER_FLAGS:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of modules during
|
||||||
|
// DEBUG builds.
|
||||||
|
CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of modules during
|
||||||
|
// MINSIZEREL builds.
|
||||||
|
CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of modules during
|
||||||
|
// RELEASE builds.
|
||||||
|
CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of modules during
|
||||||
|
// RELWITHDEBINFO builds.
|
||||||
|
CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING=
|
||||||
|
|
||||||
|
//Value Computed by CMake
|
||||||
|
CMAKE_PROJECT_DESCRIPTION:STATIC=
|
||||||
|
|
||||||
|
//Value Computed by CMake
|
||||||
|
CMAKE_PROJECT_HOMEPAGE_URL:STATIC=
|
||||||
|
|
||||||
|
//Value Computed by CMake
|
||||||
|
CMAKE_PROJECT_NAME:STATIC=lto-test
|
||||||
|
|
||||||
|
//Ranlib
|
||||||
|
CMAKE_RANLIB:FILEPATH=/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of dll's.
|
||||||
|
CMAKE_SHARED_LINKER_FLAGS:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of shared libraries
|
||||||
|
// during DEBUG builds.
|
||||||
|
CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of shared libraries
|
||||||
|
// during MINSIZEREL builds.
|
||||||
|
CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of shared libraries
|
||||||
|
// during RELEASE builds.
|
||||||
|
CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of shared libraries
|
||||||
|
// during RELWITHDEBINFO builds.
|
||||||
|
CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING=
|
||||||
|
|
||||||
|
//If set, runtime paths are not added when installing shared libraries,
|
||||||
|
// but are added when building.
|
||||||
|
CMAKE_SKIP_INSTALL_RPATH:BOOL=NO
|
||||||
|
|
||||||
|
//If set, runtime paths are not added when using shared libraries.
|
||||||
|
CMAKE_SKIP_RPATH:BOOL=NO
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of static libraries
|
||||||
|
// during all build types.
|
||||||
|
CMAKE_STATIC_LINKER_FLAGS:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of static libraries
|
||||||
|
// during DEBUG builds.
|
||||||
|
CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of static libraries
|
||||||
|
// during MINSIZEREL builds.
|
||||||
|
CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of static libraries
|
||||||
|
// during RELEASE builds.
|
||||||
|
CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING=
|
||||||
|
|
||||||
|
//Flags used by the linker during the creation of static libraries
|
||||||
|
// during RELWITHDEBINFO builds.
|
||||||
|
CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING=
|
||||||
|
|
||||||
|
//Strip
|
||||||
|
CMAKE_STRIP:FILEPATH=/home/echo/Android/Sdk/ndk/27.1.12297006/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip
|
||||||
|
|
||||||
|
//If this value is on, makefiles will be generated without the
|
||||||
|
// .SILENT directive, and all commands will be echoed to the console
|
||||||
|
// during the make. This is useful for debugging only. With Visual
|
||||||
|
// Studio IDE projects all commands are done without /nologo.
|
||||||
|
CMAKE_VERBOSE_MAKEFILE:BOOL=ON
|
||||||
|
|
||||||
|
//Value Computed by CMake
|
||||||
|
lto-test_BINARY_DIR:STATIC=/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/x86/CMakeFiles/_CMakeLTOTest-CXX/bin
|
||||||
|
|
||||||
|
//Value Computed by CMake
|
||||||
|
lto-test_IS_TOP_LEVEL:STATIC=ON
|
||||||
|
|
||||||
|
//Value Computed by CMake
|
||||||
|
lto-test_SOURCE_DIR:STATIC=/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/x86/CMakeFiles/_CMakeLTOTest-CXX/src
|
||||||
|
|
||||||
|
|
||||||
|
########################
|
||||||
|
# INTERNAL cache entries
|
||||||
|
########################
|
||||||
|
|
||||||
|
//This is the directory where this CMakeCache.txt was created
|
||||||
|
CMAKE_CACHEFILE_DIR:INTERNAL=/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/x86/CMakeFiles/_CMakeLTOTest-CXX/bin
|
||||||
|
//Major version of cmake used to create the current loaded cache
|
||||||
|
CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3
|
||||||
|
//Minor version of cmake used to create the current loaded cache
|
||||||
|
CMAKE_CACHE_MINOR_VERSION:INTERNAL=22
|
||||||
|
//Patch version of cmake used to create the current loaded cache
|
||||||
|
CMAKE_CACHE_PATCH_VERSION:INTERNAL=1
|
||||||
|
//Path to CMake executable.
|
||||||
|
CMAKE_COMMAND:INTERNAL=/home/echo/Android/Sdk/cmake/3.22.1/bin/cmake
|
||||||
|
//Path to cpack program executable.
|
||||||
|
CMAKE_CPACK_COMMAND:INTERNAL=/home/echo/Android/Sdk/cmake/3.22.1/bin/cpack
|
||||||
|
//Path to ctest program executable.
|
||||||
|
CMAKE_CTEST_COMMAND:INTERNAL=/home/echo/Android/Sdk/cmake/3.22.1/bin/ctest
|
||||||
|
//ADVANCED property for variable: CMAKE_CXX_FLAGS
|
||||||
|
CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG
|
||||||
|
CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL
|
||||||
|
CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE
|
||||||
|
CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO
|
||||||
|
CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_CXX_STANDARD_LIBRARIES
|
||||||
|
CMAKE_CXX_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS
|
||||||
|
CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG
|
||||||
|
CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL
|
||||||
|
CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE
|
||||||
|
CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO
|
||||||
|
CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS
|
||||||
|
CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1
|
||||||
|
//Name of external makefile project generator.
|
||||||
|
CMAKE_EXTRA_GENERATOR:INTERNAL=
|
||||||
|
//Name of generator.
|
||||||
|
CMAKE_GENERATOR:INTERNAL=Ninja
|
||||||
|
//Generator instance identifier.
|
||||||
|
CMAKE_GENERATOR_INSTANCE:INTERNAL=
|
||||||
|
//Name of generator platform.
|
||||||
|
CMAKE_GENERATOR_PLATFORM:INTERNAL=
|
||||||
|
//Name of generator toolset.
|
||||||
|
CMAKE_GENERATOR_TOOLSET:INTERNAL=
|
||||||
|
//Source directory with the top level CMakeLists.txt file for this
|
||||||
|
// project
|
||||||
|
CMAKE_HOME_DIRECTORY:INTERNAL=/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/x86/CMakeFiles/_CMakeLTOTest-CXX/src
|
||||||
|
//Install .so files without execute permission.
|
||||||
|
CMAKE_INSTALL_SO_NO_EXE:INTERNAL=0
|
||||||
|
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS
|
||||||
|
CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG
|
||||||
|
CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL
|
||||||
|
CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE
|
||||||
|
CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO
|
||||||
|
CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
|
||||||
|
//number of local generators
|
||||||
|
CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1
|
||||||
|
//Path to CMake installation.
|
||||||
|
CMAKE_ROOT:INTERNAL=/home/echo/Android/Sdk/cmake/3.22.1/share/cmake-3.22
|
||||||
|
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS
|
||||||
|
CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG
|
||||||
|
CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL
|
||||||
|
CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE
|
||||||
|
CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO
|
||||||
|
CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH
|
||||||
|
CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_SKIP_RPATH
|
||||||
|
CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS
|
||||||
|
CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG
|
||||||
|
CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL
|
||||||
|
CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE
|
||||||
|
CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
|
||||||
|
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO
|
||||||
|
CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
|
||||||
|
CMAKE_SUPPRESS_DEVELOPER_WARNINGS:INTERNAL=FALSE
|
||||||
|
//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE
|
||||||
|
CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1
|
||||||
|
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/x86/CMakeFiles/_CMakeLTOTest-CXX/bin/CMakeFiles/foo.dir
|
||||||
|
/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/x86/CMakeFiles/_CMakeLTOTest-CXX/bin/CMakeFiles/boo.dir
|
||||||
|
/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/x86/CMakeFiles/_CMakeLTOTest-CXX/bin/CMakeFiles/edit_cache.dir
|
||||||
|
/home/echo/dev/prototype/apps/mobile/android/app/.cxx/Debug/2z472e3c/x86/CMakeFiles/_CMakeLTOTest-CXX/bin/CMakeFiles/rebuild_cache.dir
|
||||||
BIN
Binary file not shown.
+1
@@ -0,0 +1 @@
|
|||||||
|
# This file is generated by cmake for dependency checking of the CMakeCache.txt file
|
||||||
BIN
Binary file not shown.
Loaded 100 of 312 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user