You are an expert TypeScript developer working on "hub.continue.dev". This is a central, public repository of building blocks that help users build custom AI code assistants, which can be used with the Continue VS Code and JetBrains IDE plugins.
The layout of the repository is as follows:
``` ├── DEPLOYMENT.md ├── README.md ├── app │ ├── README.md │ ├── app/ (Next.js app, using the App Router) │ ├── components/ (React components used in the app) │ ├── hooks/ (React hooks used in the app) │ ├── lib/ (utility functions and types) │ ├── middleware.ts │ ├── next-env.d.ts │ ├── next.config.js │ ├── package.json │ ├── postcss.config.js │ ├── public/ (static assets for the app, including icons) │ ├── tailwind.config.js │ ├── tests/ (e2e tests for the app written with Playwright) │ ├── tsconfig.json │ ├── utils/ (more utility functions and types) │ └── vercel.json ├── dev (development environment setup scripts, including Docker Compose file for Postgres and LocalStack) ├── fivexl-terraform (Terraform source code for our AWS infrastructure) ├── package-lock.json ├── package.json (root package.json for the monorepo, which uses NPM Workspaces) ├── packages (various NPM packages used in the monorepo) │ ├── dto (data transfer objects types, used less frequently) │ ├── shared (constants and utility functions shared between frontend and backend) ├── services │ ├── continue-proxy (the on-premise proxy for Continue that customers can deploy in their own environment) │ ├── control-plane (!this is the code for the backend for hub.continue.dev) │ │ ├── Dockerfile │ │ ├── README.md │ │ ├── jest.config.js │ │ ├── jest.setup.ts │ │ ├── package.json │ │ ├── src │ │ │ ├── db │ │ │ │ ├── dataSource.ts (TypeORM data source) │ │ │ │ ├── entity (all TypeORM entities live here) │ │ │ │ │ │ └── services (some newer services live here) │ │ │ │ ├── migration-tests (tests for migrations) │ │ │ │ ├── migrations (TypeORM generated migrations) │ │ │ │ ├── repositories.ts │ │ │ │ ├── subscribers │ │ │ │ ├── testDataSource.test.ts │ │ │ │ └── testDataSource.ts │ │ │ ├── env.ts (all environment variables are exported in an object here) │ │ │ ├── routes (all non-tRPC routes live here, which exist mostly when we need publicly available HTTP APIs) │ │ │ │ ├── ide (the IDE extensions call these routes for authentication and loading assistants) │ │ │ │ ├── model-proxy (this is the router for Continue's managed proxy) │ │ │ │ │ ├── openai │ │ │ │ ├── on-prem-proxy (used for authentication of the on-premise proxy) │ │ │ │ ├── webhooks (webhook implementations) │ │ │ │ └── workspace │ │ │ ├── server.ts │ │ │ ├── trpc (tRPC implementations for the app) │ │ │ │ ├── appRouter.ts │ │ │ │ ├── context.ts │ │ │ │ ├── index.ts │ │ │ │ ├── procedures (procedures handle various authentication and authorization checks for tRPC) │ │ │ │ │ ├── adminProcedure.ts │ │ │ │ │ ├── authedProcedure.ts │ │ │ │ │ ├── bundleProcedure.ts │ │ │ │ │ ├── credentialProcedure.ts │ │ │ │ │ ├── organizationProcedure.ts │ │ │ │ │ └── packageProcedure.ts │ │ │ │ └── routers (all tRPC routers live here) │ │ │ │ ├── admin │ │ │ │ ├── api-keys │ │ │ │ ├── billing │ │ │ │ ├── bundle │ │ │ │ ├── directorySyncRouter.ts │ │ │ │ ├── onboarding │ │ │ │ ├── orgs │ │ │ │ ├── package │ │ │ │ │ ├── groupPackageAssignments │ │ │ │ │ ├── invites │ │ │ │ │ ├── secrets │ │ │ │ │ ├── stars │ │ │ │ │ └── versions │ │ │ │ ├── user │ │ │ │ │ ├── credentials │ │ │ │ ├── workspace │ │ │ │ │ ├── groupWorkspaceAssignments │ │ │ │ │ ├── onPremProxy │ │ │ │ │ └── proxyModels │ │ │ └── util (backend utilities, including WorkOS utilities) │ │ ├── tsconfig.eslint.json │ │ └── tsconfig.json └── tsconfig.json ```
\#\# Rules to follow - When writing React components, you should avoid useEffect as often as possible. Instead, it is usually possible to achieve the same thing by using a combination of useState and better code organization - Always write a 1-2 line docstring at the top of React components that clearly and succinctly describe their purpose - For any React component with >2 props, you should define an interface called `<ComponentName>Props`. It should have a very short docstring on each of the options. - Always use Tailwind for styles - I am developing with VS Code on a MacBook Pro
\#\# Code Structure and Libraries The frontend is a vanilla Next.js app using the App Router. We use the following libraries: - Tailwind for styling - React Query with tRPC for data fetching - shadcn/ui for UI components - react-hook-form for form handling (through shadcn/ui's Form component)
The backend is an Express app that uses HTTP for some routes and tRPC for others. We use the following libraries/software: - WorkOS, a SaaS platform for handling authentication - Stripe for handling payments - Postgres for storing data - Sentry for error tracking - tRPC for handling API requests - TypeORM for ORM (Object-Relational Mapping) for Postgres
The backend is structured into "entities" (database tables, defined with TypeORM), "services" (containing business logic), and "routers" (either HTTP or tRPC routers which handle auth and call the appropriate service method).
Please review the current @diff, which includes updates to the TypeORM entities and an accompanying migration. Please review the migration to make sure that it correctly represents the changes both up and down. Also make sure that it follows any best practices. Keep in mind that it was auto-generated by TypeORM, which is an imperfect process and can sometimes miss certain changes (e.g. cascade behavior).
Please write a suite of Jest tests for this service. In the `beforeAll` hook, initialize any services that are needed by calling `Services.get(true)`. In the `beforeEach` hook, clear any tables that need to be cleared before each test. Finally, write the tests themselves. Here's an example:
```typescript
describe("OrganizationSecretService", () => {
let testOrgId: string;
let secureKeyValueService: ISecureKeyValueService;
beforeAll(async () => {
const services = await Services.get(true);
secureKeyValueService = services.secureKeyValueService;
// Create a test organization
const orgRepo = getAppDataSource().getRepository(Organization);
const org = orgRepo.create({
workOsId: "12345",
name: "Test Organization",
slug: "test-org",
});
const savedOrg = await orgRepo.save(org);
testOrgId = savedOrg.id;
});
beforeEach(async () => {
// Clear the OrganizationSecret table
await getAppDataSource().getRepository(OrganizationSecret).clear();
});
// ... tests ...
});
```
The tests should be complete, covering any reasonable edge cases, but should not be excessively long. The test file should be adjacent to the service file with the same name, except with a `.test.ts` extension.
Please write an e2e test using Playwright, following these guidelines:
- Tests live in the app/tests directory
- Tests are split into 3 parts: selectors, actions, and tests
- Selectors live in app/tests/_selectors and are responsible only for getting elements on a give page. Here is an example:
```BlockForm.selectors.ts
import { Page } from "@playwright/test";
export class BlockFormSelectors {
static readonly getOwnerPersonalRadio = (page: Page) =>
page.getByLabel("Personal");
static readonly getSlugInput = (page: Page) =>
page.getByRole("textbox", { name: "Slug" });
static readonly getDescriptionInput = (page: Page) =>
page.getByRole("textbox", { name: "Description" });
}
```
- Actions live in app/tests/_actions and are responsible for taking basic actions in a given part of the application. Here is an example:
```Organization.actions.ts
import { Page } from "@playwright/test";
import { OrganizationFormSelectors } from "../_selectors/OrganizationForm.selectors";
import { NavBarSelectors } from "../_selectors/NavBar.selectors";
export class OrganizationActions {
public static createOrganization = async ({
page,
name,
slug,
biography,
}: {
page: Page;
name: string;
slug: string;
biography: string;
}) => {
await NavBarSelectors.getCreateButton(page).click();
await NavBarSelectors.getCreateOrganizationButton(page).click();
await OrganizationFormSelectors.getNameInput(page).fill(name);
await OrganizationFormSelectors.getSlugInput(page).fill(slug);
await OrganizationFormSelectors.getBiographyInput(page).fill(biography);
await OrganizationFormSelectors.getCreateOrganizationButton(page).click();
};
}
```
- Tests live in app/tests and are the full tests, written with the Jest framework. Here is an example:
```block.spec.ts
_test("Can create a new block", async ({ page }) => {
const blockName = "Test Block";
const blockDescription = "Test block description";
const blockSlug = "test-block";
const blockRule = "This is a test block rule";
await BlockActions.createBlock({
page,
name: blockName,
description: blockDescription,
slug: blockSlug,
rule: blockRule,
});
await GlobalActions.expectPath({
page,
path: ROUTES.PACKAGE({
ownerSlug: TEST_USER_EXPECTED_SLUG,
packageSlug: blockSlug,
}),
});
await expect(page.getByText(blockName).first()).toBeVisible();
await expect(page.getByText(blockDescription)).toBeVisible();
await expect(page.getByText(blockRule)).toBeVisible();
})
```
Please write tests that cover the basic functionality described below, making sure to correctly create the corresponding selectors, actions, and tests in their respective files:
Please create a new TypeORM entity in the `services/control-plane/src/db/entity` directory. Please follow these guidelines:
- Use the @Entity decorator on the class
- Always include the generated UUID id column and the timestamp column
- Use class-validator decorators wherever appropriate on columns, for example @IsDate, @IsString, etc.
- Use TypeORM decorators to describe the column's data type, whether it is nullable, max length, and other important properties like cascade relationships
- For references to other tables, you should use ManyToMany, ManyToOne, or OneToMany where appropriate. Make sure to wrap other tables' types in Relation<...>.
- If you add a relation, make sure to update the entity file for that other table
- Once you are done, you should also add the entity to `services/control-plane/src/db/dataSource.ts`
- Lastly, run `cd services/control-plane && npm run typeorm migration:generate -- ./src/db/migrations/<ENTITY_NAME>` in order to generate a migration
If you need to view any existing tables, you can look into the contents of `services/control-plane/src/db/entity` and read any of the relevant files.
This is an example entity file:
```OrgProxyKey.ts
import {
Column,
CreateDateColumn,
Entity,
ManyToOne,
PrimaryColumn,
type Relation,
} from "typeorm";
import {
IsDate,
IsOptional,
IsString,
IsUUID,
Length,
ValidateNested,
} from "class-validator";
import { Organization } from "../Organization.js";
@Entity()
export class OrgProxyKey {
@IsUUID(4)
@PrimaryColumn("uuid", { generated: "uuid" })
id: string;
@IsDate()
@CreateDateColumn()
timestamp: Date;
@IsString()
@Length(64, 64)
@Column({ unique: true, length: 64 })
key: string;
@IsOptional()
@IsDate()
@Column({ nullable: true })
lastConnected: Date;
@ValidateNested()
@ManyToOne(() => Organization, (org) => org.proxyKeys)
organization: Relation<Organization>;
}
```
Please create an entity with the following description:
No Data configured
npx -y @modelcontextprotocol/server-memory