diff --git a/apps/dashboard/CHANGELOG.md b/apps/dashboard/CHANGELOG.md
index 1eb8fec7b..ab40f851a 100644
--- a/apps/dashboard/CHANGELOG.md
+++ b/apps/dashboard/CHANGELOG.md
@@ -1,5 +1,11 @@
# @unkey/web
+## 0.1.40
+
+### Patch Changes
+
+- @unkey/ratelimit@0.5.1
+
## 0.1.39
### Patch Changes
diff --git a/apps/dashboard/app/(app)/apis/[apiId]/keys/[keyAuthId]/[keyId]/page.tsx b/apps/dashboard/app/(app)/apis/[apiId]/keys/[keyAuthId]/[keyId]/page.tsx
index f94ecb0bd..72bfda765 100644
--- a/apps/dashboard/app/(app)/apis/[apiId]/keys/[keyAuthId]/[keyId]/page.tsx
+++ b/apps/dashboard/app/(app)/apis/[apiId]/keys/[keyAuthId]/[keyId]/page.tsx
@@ -111,6 +111,9 @@ export default async function APIKeyDetailPage(props: {
.then((res) => res.val?.at(0)?.time ?? 0),
]);
+ // Sort all verifications by time first
+ const sortedVerifications = verifications.val!.sort((a, b) => a.time - b.time);
+
const successOverTime: { x: string; y: number }[] = [];
const ratelimitedOverTime: { x: string; y: number }[] = [];
const usageExceededOverTime: { x: string; y: number }[] = [];
@@ -119,30 +122,47 @@ export default async function APIKeyDetailPage(props: {
const expiredOverTime: { x: string; y: number }[] = [];
const forbiddenOverTime: { x: string; y: number }[] = [];
- for (const d of verifications.val!.sort((a, b) => a.time - b.time)) {
+ // Get all unique timestamps
+ const uniqueDates = [...new Set(sortedVerifications.map((d) => d.time))].sort((a, b) => a - b);
+
+ // Ensure each array has entries for all timestamps with zero counts
+ for (const timestamp of uniqueDates) {
+ const x = new Date(timestamp).toISOString();
+ successOverTime.push({ x, y: 0 });
+ ratelimitedOverTime.push({ x, y: 0 });
+ usageExceededOverTime.push({ x, y: 0 });
+ disabledOverTime.push({ x, y: 0 });
+ insufficientPermissionsOverTime.push({ x, y: 0 });
+ expiredOverTime.push({ x, y: 0 });
+ forbiddenOverTime.push({ x, y: 0 });
+ }
+
+ for (const d of sortedVerifications) {
const x = new Date(d.time).toISOString();
+ const index = uniqueDates.indexOf(d.time);
+
switch (d.outcome) {
case "":
case "VALID":
- successOverTime.push({ x, y: d.count });
+ successOverTime[index] = { x, y: d.count };
break;
case "RATE_LIMITED":
- ratelimitedOverTime.push({ x, y: d.count });
+ ratelimitedOverTime[index] = { x, y: d.count };
break;
case "USAGE_EXCEEDED":
- usageExceededOverTime.push({ x, y: d.count });
+ usageExceededOverTime[index] = { x, y: d.count };
break;
case "DISABLED":
- disabledOverTime.push({ x, y: d.count });
+ disabledOverTime[index] = { x, y: d.count };
break;
case "INSUFFICIENT_PERMISSIONS":
- insufficientPermissionsOverTime.push({ x, y: d.count });
+ insufficientPermissionsOverTime[index] = { x, y: d.count };
break;
case "EXPIRED":
- expiredOverTime.push({ x, y: d.count });
+ expiredOverTime[index] = { x, y: d.count };
break;
case "FORBIDDEN":
- forbiddenOverTime.push({ x, y: d.count });
+ forbiddenOverTime[index] = { x, y: d.count };
break;
}
}
@@ -209,6 +229,7 @@ export default async function APIKeyDetailPage(props: {
stats.forbidden += v.count;
}
});
+
const roleTee = key.workspace.roles.map((role) => {
const nested: NestedPermissions = {};
for (const permission of key.workspace.permissions) {
@@ -328,7 +349,7 @@ export default async function APIKeyDetailPage(props: {
-
+
) => {
const { resolvedTheme } = useTheme();
- const colors: { light: Record; dark: Record } = {
+ const colors: {
+ light: Record;
+ dark: Record;
+ } = {
light: {
primary: "#1c1917",
warn: "#FFCD07",
@@ -133,9 +136,9 @@ export const LineChart: React.FC<{
tooltip={{
formatter: (datum) => ({
name: datum.category,
- value: `${Intl.NumberFormat(undefined, { notation: "compact" }).format(
- Number(datum.y),
- )} ms`,
+ value: `${Intl.NumberFormat(undefined, {
+ notation: "compact",
+ }).format(Number(datum.y))} ms`,
}),
}}
/>
@@ -202,6 +205,53 @@ export const StackedColumnChart: React.FC<{
colors: Array;
}> = ({ data, timeGranularity, colors }) => {
const { axisColor } = useColors(colors);
+
+ const formatDate = (date: string) => {
+ const d = new Date(date);
+ if (Number.isNaN(d.getTime())) {
+ return date;
+ }
+
+ switch (timeGranularity) {
+ case "minute":
+ return d.toLocaleString(undefined, {
+ hour: "numeric",
+ minute: "2-digit",
+ hour12: true,
+ month: "short",
+ day: "numeric",
+ });
+ case "hour":
+ return d.toLocaleString(undefined, {
+ hour: "numeric",
+ hour12: true,
+ month: "short",
+ day: "numeric",
+ year: "numeric",
+ });
+ case "day":
+ return d.toLocaleString(undefined, {
+ weekday: "short",
+ month: "short",
+ day: "numeric",
+ year: "numeric",
+ });
+ case "month":
+ return d.toLocaleString(undefined, {
+ month: "long",
+ year: "numeric",
+ });
+ default:
+ return d.toLocaleString(undefined, {
+ month: "short",
+ day: "numeric",
+ year: "numeric",
+ hour: "numeric",
+ minute: "2-digit",
+ });
+ }
+ };
+
return (
({
name: datum.category,
- value: Intl.NumberFormat(undefined, { notation: "compact" }).format(Number(datum.y)),
+ value: Intl.NumberFormat(undefined, {
+ notation: "compact",
+ maximumFractionDigits: 1,
+ compactDisplay: "short",
+ }).format(Number(datum.y)),
}),
}}
/>
diff --git a/apps/dashboard/package.json b/apps/dashboard/package.json
index 8796f2eca..f1dec61d7 100644
--- a/apps/dashboard/package.json
+++ b/apps/dashboard/package.json
@@ -1,6 +1,6 @@
{
"name": "@unkey/dashboard",
- "version": "0.1.39",
+ "version": "0.1.40",
"private": true,
"scripts": {
"dev": "next dev",
diff --git a/packages/api/CHANGELOG.md b/packages/api/CHANGELOG.md
index e0824693f..4cec01e33 100644
--- a/packages/api/CHANGELOG.md
+++ b/packages/api/CHANGELOG.md
@@ -1,5 +1,11 @@
# @unkey/api
+## 0.30.0
+
+### Minor Changes
+
+- 0746b33: Add the types for error codes
+
## 0.29.0
### Minor Changes
diff --git a/packages/api/package.json b/packages/api/package.json
index af6aa472c..1bb94cd86 100644
--- a/packages/api/package.json
+++ b/packages/api/package.json
@@ -1,6 +1,6 @@
{
"name": "@unkey/api",
- "version": "0.29.0",
+ "version": "0.30.0",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
@@ -9,12 +9,19 @@
"publishConfig": {
"access": "public"
},
- "keywords": ["unkey", "client", "api"],
+ "keywords": [
+ "unkey",
+ "client",
+ "api"
+ ],
"bugs": {
"url": "https://github.com/unkeyed/unkey/issues"
},
"homepage": "https://github.com/unkeyed/unkey#readme",
- "files": ["./dist/**", "README.md"],
+ "files": [
+ "./dist/**",
+ "README.md"
+ ],
"author": "Andreas Thomas ",
"scripts": {
"generate": "openapi-typescript https://api.unkey.dev/openapi.json -o ./src/openapi.d.ts",
diff --git a/packages/api/src/errors.ts b/packages/api/src/errors.ts
index 866ff1642..f04cedbeb 100644
--- a/packages/api/src/errors.ts
+++ b/packages/api/src/errors.ts
@@ -2,4 +2,10 @@ import type { paths } from "./openapi";
// this is what a json body response looks like
export type ErrorResponse =
- paths["/v1/liveness"]["get"]["responses"]["500"]["content"]["application/json"];
+ | paths["/v1/liveness"]["get"]["responses"]["400"]["content"]["application/json"]
+ | paths["/v1/liveness"]["get"]["responses"]["401"]["content"]["application/json"]
+ | paths["/v1/liveness"]["get"]["responses"]["403"]["content"]["application/json"]
+ | paths["/v1/liveness"]["get"]["responses"]["404"]["content"]["application/json"]
+ | paths["/v1/liveness"]["get"]["responses"]["409"]["content"]["application/json"]
+ | paths["/v1/liveness"]["get"]["responses"]["429"]["content"]["application/json"]
+ | paths["/v1/liveness"]["get"]["responses"]["500"]["content"]["application/json"];
diff --git a/packages/hono/CHANGELOG.md b/packages/hono/CHANGELOG.md
index 6f3b3d77d..00da89b88 100644
--- a/packages/hono/CHANGELOG.md
+++ b/packages/hono/CHANGELOG.md
@@ -1,5 +1,12 @@
# @unkey/hono
+## 1.4.11
+
+### Patch Changes
+
+- Updated dependencies [0746b33]
+ - @unkey/api@0.30.0
+
## 1.4.10
### Patch Changes
diff --git a/packages/hono/package.json b/packages/hono/package.json
index 82c7598c6..fcabc2fa0 100644
--- a/packages/hono/package.json
+++ b/packages/hono/package.json
@@ -1,6 +1,6 @@
{
"name": "@unkey/hono",
- "version": "1.4.10",
+ "version": "1.4.11",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"license": "MIT",
@@ -8,12 +8,19 @@
"publishConfig": {
"access": "public"
},
- "keywords": ["unkey", "client", "api", "hono"],
+ "keywords": [
+ "unkey",
+ "client",
+ "api",
+ "hono"
+ ],
"bugs": {
"url": "https://github.com/unkeyed/unkey/issues"
},
"homepage": "https://github.com/unkeyed/unkey#readme",
- "files": ["./dist/**"],
+ "files": [
+ "./dist/**"
+ ],
"author": "Andreas Thomas ",
"scripts": {
"build": "tsup",
diff --git a/packages/nextjs/CHANGELOG.md b/packages/nextjs/CHANGELOG.md
index 2c942a3bb..490cd960a 100644
--- a/packages/nextjs/CHANGELOG.md
+++ b/packages/nextjs/CHANGELOG.md
@@ -1,5 +1,12 @@
# @unkey/nextjs
+## 0.18.4
+
+### Patch Changes
+
+- Updated dependencies [0746b33]
+ - @unkey/api@0.30.0
+
## 0.18.3
### Patch Changes
diff --git a/packages/nextjs/package.json b/packages/nextjs/package.json
index a8ada0e7a..11bdf331b 100644
--- a/packages/nextjs/package.json
+++ b/packages/nextjs/package.json
@@ -1,6 +1,6 @@
{
"name": "@unkey/nextjs",
- "version": "0.18.3",
+ "version": "0.18.4",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"license": "MIT",
@@ -8,12 +8,19 @@
"publishConfig": {
"access": "public"
},
- "keywords": ["unkey", "client", "api"],
+ "keywords": [
+ "unkey",
+ "client",
+ "api"
+ ],
"bugs": {
"url": "https://github.com/unkeyed/unkey/issues"
},
"homepage": "https://github.com/unkeyed/unkey#readme",
- "files": ["./dist/**", "README.md"],
+ "files": [
+ "./dist/**",
+ "README.md"
+ ],
"author": "Andreas Thomas ",
"scripts": {
"build": "tsup"
diff --git a/packages/ratelimit/CHANGELOG.md b/packages/ratelimit/CHANGELOG.md
index b51453d18..e481e8bd8 100644
--- a/packages/ratelimit/CHANGELOG.md
+++ b/packages/ratelimit/CHANGELOG.md
@@ -1,5 +1,12 @@
# @unkey/ratelimit
+## 0.5.1
+
+### Patch Changes
+
+- Updated dependencies [0746b33]
+ - @unkey/api@0.30.0
+
## 0.5.0
### Minor Changes
diff --git a/packages/ratelimit/package.json b/packages/ratelimit/package.json
index 8e1639e4b..fb5c5e100 100644
--- a/packages/ratelimit/package.json
+++ b/packages/ratelimit/package.json
@@ -1,6 +1,6 @@
{
"name": "@unkey/ratelimit",
- "version": "0.5.0",
+ "version": "0.5.1",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
@@ -9,12 +9,20 @@
"publishConfig": {
"access": "public"
},
- "keywords": ["unkey", "ratelimit", "global", "serverless"],
+ "keywords": [
+ "unkey",
+ "ratelimit",
+ "global",
+ "serverless"
+ ],
"bugs": {
"url": "https://github.com/unkeyed/unkey/issues"
},
"homepage": "https://github.com/unkeyed/unkey#readme",
- "files": ["./dist/**", "README.md"],
+ "files": [
+ "./dist/**",
+ "README.md"
+ ],
"author": "Andreas Thomas ",
"scripts": {
"build": "tsup"