Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
12 changes: 12 additions & 0 deletions apps/app/gt.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"$schema": "https://assets.gtx.dev/config-schema.json",
"defaultLocale": "en",
"framework": "next-app",
"files": {
"gt": {
"output": "public/_gt/[locale].json"
}
},
"locales": ["es"],
"_versionId": "c755ac63434ef4ae61355e3c4f6891f5452696a69eeacc71ef29580bd242c5c4"
}
3 changes: 2 additions & 1 deletion apps/app/next.config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { withGTConfig } from 'gt-next/config';
import type { NextConfig } from 'next';
import './src/env.mjs';

Expand Down Expand Up @@ -51,4 +52,4 @@ const config: NextConfig = {
},
};

export default config;
export default withGTConfig(config, {});
7 changes: 5 additions & 2 deletions apps/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"dub": "^0.63.6",
"framer-motion": "^12.18.1",
"geist": "^1.3.1",
"gt-next": "^6.0.11",
"lucide-react": "^0.534.0",
"motion": "^12.9.2",
"next": "15.4.2-canary.16",
Expand Down Expand Up @@ -109,6 +110,7 @@
"eslint-config-next": "15.4.2-canary.16",
"fleetctl": "^4.68.1",
"glob": "^11.0.3",
"gtx-cli": "^2.0.22",
"jsdom": "^26.1.0",
"postcss": "^8.5.4",
"prisma": "^6.13.0",
Expand All @@ -132,7 +134,7 @@
"private": true,
"scripts": {
"analyze-locale-usage": "bunx tsx src/locales/analyze-locale-usage.ts",
"build": "next build",
"build": "bun run translate && next build",
"db:generate": "bun run db:getschema && prisma generate",
"db:getschema": "cp ../../node_modules/@trycompai/db/dist/schema.prisma prisma/schema.prisma",
"deploy:trigger-prod": "npx trigger.dev@latest deploy",
Expand All @@ -153,6 +155,7 @@
"test:ui": "vitest --ui",
"test:watch": "vitest --watch",
"trigger:dev": "npx trigger.dev@latest dev",
"typecheck": "tsc --noEmit"
"typecheck": "tsc --noEmit",
"translate": "locadex translate"
}
}
3,049 changes: 3,049 additions & 0 deletions apps/app/public/_gt/es.json

Large diffs are not rendered by default.

10 changes: 7 additions & 3 deletions apps/app/src/actions/change-organization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { auth } from '@/utils/auth';
import { db } from '@db';
import { getGT } from 'gt-next/server';
import { revalidatePath } from 'next/cache';
import { headers } from 'next/headers';
import { z } from 'zod';
Expand Down Expand Up @@ -32,9 +33,10 @@ export const changeOrganizationAction = authActionClient
});

if (!organizationMember) {
const t = await getGT();
return {
success: false,
error: 'Unauthorized',
error: t('Unauthorized'),
};
}

Expand All @@ -46,9 +48,10 @@ export const changeOrganizationAction = authActionClient
});

if (!organization) {
const t = await getGT();
return {
success: false,
error: 'Organization not found',
error: t('Organization not found'),
};
}

Expand All @@ -68,9 +71,10 @@ export const changeOrganizationAction = authActionClient
} catch (error) {
console.error('Error changing organization:', error);

const t = await getGT();
return {
success: false,
error: 'Failed to change organization',
error: t('Failed to change organization'),
};
}
});
13 changes: 9 additions & 4 deletions apps/app/src/actions/context-hub/create-context-entry-action.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
'use server';

import { db } from '@db';
import { getGT } from 'gt-next/server';
import { revalidatePath } from 'next/cache';
import { headers } from 'next/headers';
import { authActionClient } from '../safe-action';
import { createContextEntrySchema } from '../schema';
import { getCreateContextEntrySchema } from '../schema';

export const createContextEntryAction = authActionClient
.inputSchema(createContextEntrySchema)
.inputSchema(async () => {
const t = await getGT();
return getCreateContextEntrySchema(t);
})
.metadata({ name: 'create-context-entry' })
.action(async ({ parsedInput, ctx }) => {
const t = await getGT();
const { question, answer, tags } = parsedInput;
const organizationId = ctx.session.activeOrganizationId;
if (!organizationId) throw new Error('No active organization');
if (!organizationId) throw new Error(t('No active organization'));

await db.context.create({
data: {
Expand All @@ -21,7 +26,7 @@ export const createContextEntryAction = authActionClient
tags: tags
? tags
.split(',')
.map((t) => t.trim())
.map((tag) => tag.trim())
.filter(Boolean)
: [],
organizationId,
Expand Down
11 changes: 8 additions & 3 deletions apps/app/src/actions/context-hub/delete-context-entry-action.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
'use server';

import { db } from '@db';
import { getGT } from 'gt-next/server';
import { revalidatePath } from 'next/cache';
import { headers } from 'next/headers';
import { authActionClient } from '../safe-action';
import { deleteContextEntrySchema } from '../schema';
import { getDeleteContextEntrySchema } from '../schema';

export const deleteContextEntryAction = authActionClient
.inputSchema(deleteContextEntrySchema)
.inputSchema(async () => {
const t = await getGT();
return getDeleteContextEntrySchema(t);
})
.metadata({ name: 'delete-context-entry' })
.action(async ({ parsedInput, ctx }) => {
const t = await getGT();
const { id } = parsedInput;
const organizationId = ctx.session.activeOrganizationId;
if (!organizationId) throw new Error('No active organization');
if (!organizationId) throw new Error(t('No active organization'));

await db.context.delete({
where: { id, organizationId },
Expand Down
13 changes: 9 additions & 4 deletions apps/app/src/actions/context-hub/update-context-entry-action.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
'use server';

import { db } from '@db';
import { getGT } from 'gt-next/server';
import { revalidatePath } from 'next/cache';
import { headers } from 'next/headers';
import { authActionClient } from '../safe-action';
import { updateContextEntrySchema } from '../schema';
import { getUpdateContextEntrySchema } from '../schema';

export const updateContextEntryAction = authActionClient
.inputSchema(updateContextEntrySchema)
.inputSchema(async () => {
const t = await getGT();
return getUpdateContextEntrySchema(t);
})
.metadata({ name: 'update-context-entry' })
.action(async ({ parsedInput, ctx }) => {
const t = await getGT();
const { id, question, answer, tags } = parsedInput;
const organizationId = ctx.session.activeOrganizationId;
if (!organizationId) throw new Error('No active organization');
if (!organizationId) throw new Error(t('No active organization'));

await db.context.update({
where: { id, organizationId },
Expand All @@ -22,7 +27,7 @@ export const updateContextEntryAction = authActionClient
tags: tags
? tags
.split(',')
.map((t) => t.trim())
.map((tag) => tag.trim())
.filter(Boolean)
: [],
},
Expand Down
12 changes: 7 additions & 5 deletions apps/app/src/actions/files/upload-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { logger } from '@/utils/logger';
import { GetObjectCommand, PutObjectCommand } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
import { AttachmentEntityType, AttachmentType, db } from '@db';
import { getGT } from 'gt-next/server';
import { revalidatePath } from 'next/cache';
import { headers } from 'next/headers';
import { z } from 'zod';
Expand Down Expand Up @@ -54,21 +55,22 @@ export const uploadFile = async (input: z.infer<typeof uploadAttachmentSchema>)
logger.info(`[uploadFile] Starting upload for ${input.fileName}`);

console.log('[uploadFile] Checking S3 client availability');
const t = await getGT();
try {
// Check if S3 client is available
if (!s3Client) {
logger.error('[uploadFile] S3 client not initialized - check environment variables');
return {
success: false,
error: 'File upload service is currently unavailable. Please contact support.',
error: t('File upload service is currently unavailable. Please contact support.'),
} as const;
}

if (!BUCKET_NAME) {
logger.error('[uploadFile] S3 bucket name not configured');
return {
success: false,
error: 'File upload service is not properly configured.',
error: t('File upload service is not properly configured.'),
} as const;
}

Expand All @@ -84,7 +86,7 @@ export const uploadFile = async (input: z.infer<typeof uploadAttachmentSchema>)
logger.error('[uploadFile] Not authorized - no organization found');
return {
success: false,
error: 'Not authorized - no organization found',
error: t('Not authorized - no organization found'),
} as const;
}

Expand All @@ -101,7 +103,7 @@ export const uploadFile = async (input: z.infer<typeof uploadAttachmentSchema>)
);
return {
success: false,
error: `File exceeds the ${MAX_FILE_SIZE_MB}MB limit.`,
error: t('File exceeds the {maxSize}MB limit.', { maxSize: MAX_FILE_SIZE_MB }),
} as const;
}

Expand Down Expand Up @@ -157,7 +159,7 @@ export const uploadFile = async (input: z.infer<typeof uploadAttachmentSchema>)
logger.error(`[uploadFile] Error during upload process:`, error);
return {
success: false,
error: error instanceof Error ? error.message : 'An unknown error occurred.',
error: error instanceof Error ? error.message : t('An unknown error occurred.'),
} as const;
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
'use server';

import { db } from '@db';
import { getGT } from 'gt-next/server';
import { revalidatePath } from 'next/cache';
import { authActionClient } from '../safe-action';
import { deleteIntegrationConnectionSchema } from '../schema';
import { getDeleteIntegrationConnectionSchema } from '../schema';

export const deleteIntegrationConnectionAction = authActionClient
.inputSchema(deleteIntegrationConnectionSchema)
.inputSchema(async () => {
const t = await getGT();
return getDeleteIntegrationConnectionSchema(t);
})
.metadata({
name: 'delete-integration-connection',
track: {
Expand All @@ -19,11 +23,12 @@ export const deleteIntegrationConnectionAction = authActionClient
.action(async ({ parsedInput, ctx }) => {
const { integrationName } = parsedInput;
const { session } = ctx;
const t = await getGT();

if (!session.activeOrganizationId) {
return {
success: false,
error: 'Unauthorized',
error: t('Unauthorized'),
};
}

Expand All @@ -37,7 +42,7 @@ export const deleteIntegrationConnectionAction = authActionClient
if (!integration) {
return {
success: false,
error: 'Integration not found',
error: t('Integration not found'),
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@

'use server';

import { getGT } from 'gt-next/server';
import { authActionClient } from '../safe-action';
import { createIntegrationSchema } from '../schema';
import { getCreateIntegrationSchema } from '../schema';

export const retrieveIntegrationSessionTokenAction = authActionClient
.inputSchema(createIntegrationSchema)
.inputSchema(async () => {
const t = await getGT();
return getCreateIntegrationSchema(t);
})
.metadata({
name: 'retrieve-integration-session-token',
track: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { encrypt } from '@/lib/encryption';
import { db } from '@db';
import { getGT } from 'gt-next/server';
import { revalidatePath } from 'next/cache';
import { z } from 'zod';
import { authActionClient } from '../safe-action';
Expand All @@ -24,9 +25,10 @@ export const updateIntegrationSettingsAction = authActionClient
},
})
.action(async ({ parsedInput: { integration_id, option }, ctx: { session } }) => {
const t = await getGT();
try {
if (!session.activeOrganizationId) {
throw new Error('User organization not found');
throw new Error(t('User organization not found'));
}

let existingIntegration = await db.integration.findFirst({
Expand All @@ -51,7 +53,7 @@ export const updateIntegrationSettingsAction = authActionClient
const userSettings = existingIntegration.userSettings;

if (!userSettings) {
throw new Error('User settings not found');
throw new Error(t('User settings not found'));
}

const updatedUserSettings = {
Expand Down Expand Up @@ -87,7 +89,7 @@ export const updateIntegrationSettingsAction = authActionClient
console.error('Failed to update integration settings:', error);
return {
success: false,
error: error instanceof Error ? error.message : 'Failed to update integration settings',
error: error instanceof Error ? error.message : t('Failed to update integration settings'),
};
}
});
8 changes: 5 additions & 3 deletions apps/app/src/actions/organization/accept-invitation.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use server';

import { db } from '@db';
import { getGT } from 'gt-next/server';
import { revalidatePath, revalidateTag } from 'next/cache';
import { Resend } from 'resend';
import { z } from 'zod';
Expand Down Expand Up @@ -52,16 +53,17 @@ export const completeInvitation = authActionClientWithoutOrg
> => {
const { inviteCode } = parsedInput;
const user = ctx.user;
const t = await getGT();

if (!user || !user.email) {
throw new Error('Unauthorized');
throw new Error(t('Unauthorized'));
}

try {
const invitation = await validateInviteCode(inviteCode, user.email);

if (!invitation) {
throw new Error('Invitation either used or expired');
throw new Error(t('Invitation either used or expired'));
}

const existingMembership = await db.member.findFirst({
Expand Down Expand Up @@ -98,7 +100,7 @@ export const completeInvitation = authActionClientWithoutOrg
}

if (!invitation.role) {
throw new Error('Invitation role is required');
throw new Error(t('Invitation role is required'));
}

await db.member.create({
Expand Down
Loading