Skip to content
Merged
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions apps/api/src/integration/keys_updated_at_actually_updates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ test(
where: (table, { eq }) => eq(table.id, keyId),
});
expect(keyInDb).toBeDefined();
expect(keyInDb!.updatedAtM).toBeNull();
expect(keyInDb?.updatedAtM).toBeNull();

const updateRes = await h.post<V1KeysUpdateKeyRequest, V1KeysUpdateKeyResponse>({
url: "/v1/keys.updateKey",
Expand All @@ -36,8 +36,11 @@ test(
where: (table, { eq }) => eq(table.id, keyId),
});
expect(keyInDbAfterUpdate).toBeDefined();
expect(keyInDbAfterUpdate!.updatedAtM).not.toBeNull();
expect(keyInDbAfterUpdate!.updatedAtM).toBeGreaterThan(keyInDbAfterUpdate!.createdAtM);
expect(keyInDbAfterUpdate?.updatedAtM).not.toBeNull();
expect(keyInDbAfterUpdate?.updatedAtM).toBeGreaterThan(
// biome-ignore lint/style/noNonNullAssertion: Safe to leave
keyInDbAfterUpdate!.createdAtM,
);

const returnedKey = await h.get<V1KeysGetKeyResponse>({
url: `/v1/keys.getKey?keyId=${keyId}`,
Expand All @@ -48,7 +51,7 @@ test(
});

expect(returnedKey.status).toEqual(200);
expect(returnedKey.body.updatedAt).toEqual(keyInDbAfterUpdate!.updatedAtM);
expect(returnedKey.body.updatedAt).toEqual(keyInDbAfterUpdate?.updatedAtM);
},
{ timeout: 30_000 },
);
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ test("create with permissions", async (t) => {
permissions: ["domain.create", "dns.record.create"],
});
expect(create.error).toBeUndefined();
// biome-ignore lint/style/noNonNullAssertion: Safe to leave
const key = create.result!.key;

const verify = await sdk.keys.verify({
Expand All @@ -42,5 +43,5 @@ test("create with permissions", async (t) => {
expect(verify.error).toBeUndefined();
expect(verify.result).toBeDefined();

expect(verify.result!.valid).toBe(true);
expect(verify.result?.valid).toBe(true);
}, 10_000);
2 changes: 1 addition & 1 deletion apps/api/src/pkg/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export function createConnection(opts: ConnectionOptions): Database {
}

opts.logger.error("fetching from planetscale failed", {
message: lastError!.message,
message: lastError?.message,
retries: "exhausted",
});
throw lastError;
Expand Down
13 changes: 10 additions & 3 deletions apps/api/src/pkg/key_migration/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ export async function migrateKey(
username: env.DATABASE_USERNAME,
password: env.DATABASE_PASSWORD,
retry: 3,
logger: new ConsoleLogger({ requestId: "", application: "api", environment: env.ENVIRONMENT }),
logger: new ConsoleLogger({
requestId: "",
application: "api",
environment: env.ENVIRONMENT,
}),
});

const keyId = newId("key");
Expand All @@ -31,7 +35,7 @@ export async function migrateKey(
if (message.roles && message.roles.length > 0) {
const found = await db.query.roles.findMany({
where: (table, { inArray, and, eq }) =>
and(eq(table.workspaceId, message.workspaceId), inArray(table.name, message.roles!)),
and(eq(table.workspaceId, message.workspaceId), inArray(table.name, message.roles ?? [])),
});
const missingRoles = message.roles.filter((name) => !found.some((role) => role.name === name));
if (missingRoles.length > 0) {
Expand All @@ -51,7 +55,10 @@ export async function migrateKey(
if (message.permissions && message.permissions.length > 0) {
const found = await db.query.permissions.findMany({
where: (table, { inArray, and, eq }) =>
and(eq(table.workspaceId, message.workspaceId), inArray(table.name, message.permissions!)),
and(
eq(table.workspaceId, message.workspaceId),
inArray(table.name, message.permissions ?? []),
),
});
const missingRoles = message.permissions.filter(
(name) => !found.some((permission) => permission.name === name),
Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/pkg/middleware/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ async function getWorkspaceId(c: Context<HonoEnv>): Promise<string> {
if (!key) {
return null;
}
return key.forWorkspaceId!;
return key.forWorkspaceId;
});

if (err) {
Expand Down
1 change: 1 addition & 0 deletions apps/api/src/pkg/ratelimit/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ export class AgentRatelimiter implements RateLimiter {
}
}
if (res.length > 0) {
// biome-ignore lint/style/noNonNullAssertion: Safe to leave
return Ok(res[0].val!);
}

Expand Down
13 changes: 11 additions & 2 deletions apps/api/src/pkg/ratelimit/do_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export class DurableRateLimiter implements RateLimiter {
}
}
if (res.length > 0) {
// biome-ignore lint/style/noNonNullAssertion: Safe to leave
return Ok(res[0].val!);
}

Expand Down Expand Up @@ -199,7 +200,11 @@ export class DurableRateLimiter implements RateLimiter {
.fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ reset: req.reset, cost: req.cost, limit: req.limit }),
body: JSON.stringify({
reset: req.reset,
cost: req.cost,
limit: req.limit,
}),
})
.catch(async (e) => {
this.logger.warn("calling the ratelimit DO failed, retrying ...", {
Expand All @@ -210,7 +215,11 @@ export class DurableRateLimiter implements RateLimiter {
return this.getStub(req.objectName).fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ reset: req.reset, cost: req.cost, limit: req.limit }),
body: JSON.stringify({
reset: req.reset,
cost: req.cost,
limit: req.limit,
}),
});
});

Expand Down
1 change: 1 addition & 0 deletions apps/api/src/pkg/util/retry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export class Retry {
});
await new Promise((r) => setTimeout(r, backoff));
}
// biome-ignore lint/style/noNonNullAssertion: Safe to leave
return result!;
}
}
Expand Down
2 changes: 2 additions & 0 deletions apps/api/src/routes/legacy_keys_createKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ export const registerLegacyKeysCreate = (app: App) =>
await db.primary.transaction(async (tx) => {
await tx.insert(schema.keys).values({
id: keyId,
// biome-ignore lint/style/noNonNullAssertion: This is legacy already no need for change
keyAuthId: api.keyAuthId!,
name: req.name,
hash,
Expand Down Expand Up @@ -247,6 +248,7 @@ export const registerLegacyKeysCreate = (app: App) =>
},
{
type: "keyAuth",
// biome-ignore lint/style/noNonNullAssertion: This is legacy already no need for change
id: api.keyAuthId!,
},
{ type: "api", id: api.id },
Expand Down
1 change: 0 additions & 1 deletion apps/api/src/routes/v1_keys_whoami.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ export const registerV1KeysWhoAmI = (app: App) =>
},
api: dbRes.keyAuth.api,
identity: dbRes.identity,
// biome-ignore lint/suspicious/noExplicitAny: Safe to leave
} as any; // this was necessary so that we don't need to return the workspace and other types defined in keyByHash
});

Expand Down
74 changes: 0 additions & 74 deletions apps/dashboard/app/(app)/apis/[apiId]/select.tsx

This file was deleted.

7 changes: 5 additions & 2 deletions apps/dashboard/app/(app)/identities/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@ type Props = {
};
};

const DEFAULT_LIMIT = 100;
export default async function Page(props: Props) {
const search = parseAsString.withDefault("").parse(props.searchParams.search ?? "");
const limit = parseAsInteger.withDefault(100).parse(props.searchParams.limit ?? "100")!;
const limit = parseAsInteger
.withDefault(DEFAULT_LIMIT)
.parse(props.searchParams.limit ?? DEFAULT_LIMIT.toString());

const { orgId } = await getAuth();
const workspace = await db.query.workspaces.findFirst({
Expand Down Expand Up @@ -54,7 +57,7 @@ export default async function Page(props: Props) {
</Empty>
}
>
<Results search={search ?? ""} limit={limit} />
<Results search={search ?? ""} limit={limit ?? DEFAULT_LIMIT} />
</Suspense>
</div>
</PageContent>
Expand Down
2 changes: 1 addition & 1 deletion apps/dashboard/app/(app)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default async function Layout({ children }: LayoutProps) {
<div className="flex flex-1 overflow-hidden">
{/* Desktop Sidebar */}
<AppSidebar
workspace={{ ...workspace, quotas: workspace.quotas! }}
workspace={{ ...workspace, quotas: workspace.quotas }}
className="bg-gray-1 border-grayA-4"
/>

Expand Down
37 changes: 27 additions & 10 deletions apps/dashboard/app/(app)/settings/billing/client.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"use client";
import { toast } from "@/components/ui/toaster";
import type { Workspace } from "@/lib/db";
import { formatNumber } from "@/lib/fmt";
import { trpc } from "@/lib/trpc/client";
Expand All @@ -7,7 +8,6 @@ import { Button, Empty, SettingCard } from "@unkey/ui";
import ms from "ms";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { toast } from "sonner";
import type Stripe from "stripe";
import { WorkspaceNavbar } from "../workspace-navbar";
import { Confirm } from "./components/confirmation";
Expand Down Expand Up @@ -79,7 +79,12 @@ const Mutations = () => {
},
});

return { createSubscription, updateSubscription, cancelSubscription, uncancelSubscription };
return {
createSubscription,
updateSubscription,
cancelSubscription,
uncancelSubscription,
};
};

export const Client: React.FC<Props> = (props) => {
Expand Down Expand Up @@ -155,12 +160,21 @@ export const Client: React.FC<Props> = (props) => {
} updates your request quota to ${formatNumber(
p.quotas.requestsPerMonth,
)} per month immediately.`}
onConfirm={async () =>
onConfirm={async () => {
if (!props.currentProductId) {
console.error(
"Cannot update subscription: currentProductId is missing",
);
toast.error(
"Unable to update subscription. Please refresh and try again.",
);
return;
}
mutations.updateSubscription.mutateAsync({
oldProductId: props.currentProductId!,
oldProductId: props.currentProductId,
newProductId: p.id,
})
}
});
}}
trigger={(onClick) => (
<Button variant="outline" disabled={isSelected} onClick={onClick}>
Change
Expand All @@ -176,7 +190,9 @@ export const Client: React.FC<Props> = (props) => {
p.quotas.requestsPerMonth,
)} per month immediately.`}
onConfirm={() =>
mutations.createSubscription.mutateAsync({ productId: p.id })
mutations.createSubscription.mutateAsync({
productId: p.id,
})
}
fineprint={
props.hasPreviousSubscriptions
Expand Down Expand Up @@ -302,9 +318,10 @@ const CancelAlert: React.FC<{ cancelAt?: number }> = (props) => {
</SettingCard>
);
};
const SusbcriptionStatus: React.FC<{ status: Stripe.Subscription.Status; trialUntil?: number }> = (
props,
) => {
const SusbcriptionStatus: React.FC<{
status: Stripe.Subscription.Status;
trialUntil?: number;
}> = (props) => {
switch (props.status) {
case "active":
return null;
Expand Down
Loading
Loading