Compare commits
10 Commits
feat/log-d
...
feat/get-l
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
61d26e4ed8 | ||
|
|
878ffd15fc | ||
|
|
596f346181 | ||
|
|
7b59e2ac07 | ||
|
|
2a9b1fd2b5 | ||
|
|
a2d4314e14 | ||
|
|
f94e4d6da2 | ||
|
|
97f4defc0e | ||
|
|
dd29dc89fd | ||
|
|
486cdf8313 |
@@ -28,6 +28,7 @@ const config = {
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
/** Enables hot reloading for local packages without a build step */
|
||||
transpilePackages: [
|
||||
"@kan/api",
|
||||
@@ -65,6 +66,8 @@ const config = {
|
||||
},
|
||||
},
|
||||
},
|
||||
serverExternalPackages: ["pino"],
|
||||
|
||||
experimental: {
|
||||
// instrumentationHook: true,
|
||||
swcPlugins: [["@lingui/swc-plugin", {}]],
|
||||
|
||||
@@ -39,7 +39,7 @@ export function LabelForm({
|
||||
labelPublicId: entityId,
|
||||
},
|
||||
{
|
||||
enabled: isEdit && !!entityId,
|
||||
enabled: !!isEdit && entityId.length >= 12,
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -227,7 +227,7 @@ export const boardRouter = createTRPCRouter({
|
||||
boardSlug: z
|
||||
.string()
|
||||
.min(3)
|
||||
.max(24)
|
||||
.max(60)
|
||||
.regex(/^(?![-]+$)[a-zA-Z0-9-]+$/),
|
||||
members: z.array(z.string().min(12)).optional(),
|
||||
labels: z.array(z.string().min(12)).optional(),
|
||||
@@ -657,7 +657,7 @@ export const boardRouter = createTRPCRouter({
|
||||
boardSlug: z
|
||||
.string()
|
||||
.min(3)
|
||||
.max(24)
|
||||
.max(60)
|
||||
.regex(/^(?![-]+$)[a-zA-Z0-9-]+$/),
|
||||
boardPublicId: z.string().min(12),
|
||||
}),
|
||||
|
||||
@@ -3,7 +3,6 @@ import type { CreateNextContextOptions } from "@trpc/server/adapters/next";
|
||||
import type { NextApiRequest } from "next";
|
||||
import type { OpenApiMeta } from "trpc-to-openapi";
|
||||
import { initTRPC, TRPCError } from "@trpc/server";
|
||||
import { getHTTPStatusCodeFromError } from "@trpc/server/http";
|
||||
import { env } from "next-runtime-env";
|
||||
import superjson from "superjson";
|
||||
import { ZodError } from "zod";
|
||||
@@ -15,6 +14,27 @@ import { createLogger } from "@kan/logger";
|
||||
|
||||
const log = createLogger("api");
|
||||
|
||||
const TRPC_STATUS_MAP: Partial<Record<TRPCError["code"], number>> = {
|
||||
PARSE_ERROR: 400,
|
||||
BAD_REQUEST: 400,
|
||||
UNAUTHORIZED: 401,
|
||||
FORBIDDEN: 403,
|
||||
NOT_FOUND: 404,
|
||||
METHOD_NOT_SUPPORTED: 405,
|
||||
TIMEOUT: 408,
|
||||
CONFLICT: 409,
|
||||
PRECONDITION_FAILED: 412,
|
||||
PAYLOAD_TOO_LARGE: 413,
|
||||
UNPROCESSABLE_CONTENT: 422,
|
||||
TOO_MANY_REQUESTS: 429,
|
||||
CLIENT_CLOSED_REQUEST: 499,
|
||||
INTERNAL_SERVER_ERROR: 500,
|
||||
NOT_IMPLEMENTED: 501,
|
||||
BAD_GATEWAY: 502,
|
||||
SERVICE_UNAVAILABLE: 503,
|
||||
GATEWAY_TIMEOUT: 504,
|
||||
};
|
||||
|
||||
export interface User {
|
||||
id: string;
|
||||
name: string;
|
||||
@@ -110,8 +130,7 @@ export const createRESTContext = async ({ req }: CreateNextContextOptions) => {
|
||||
try {
|
||||
session = await auth.api.getSession();
|
||||
} catch (error) {
|
||||
log.error({ err: error }, "Error getting session");
|
||||
throw error;
|
||||
log.warn({ err: error }, "Failed to get session, treating as unauthenticated");
|
||||
}
|
||||
|
||||
return createInnerTRPCContext({
|
||||
@@ -170,7 +189,7 @@ const loggingMiddleware = t.middleware(async ({ path, type, next, ctx }) => {
|
||||
if (result.ok) {
|
||||
log.info({ ...meta, status: 200 }, `${label} OK`);
|
||||
} else {
|
||||
const status = getHTTPStatusCodeFromError(result.error);
|
||||
const status = TRPC_STATUS_MAP[result.error.code] ?? 500;
|
||||
const errorCode = result.error.code;
|
||||
log.error(
|
||||
{ ...meta, status, errorCode, err: result.error },
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"typecheck": "tsc --noEmit --emitDeclarationOnly false"
|
||||
},
|
||||
"dependencies": {
|
||||
"@axiomhq/pino": "^1.4.0",
|
||||
"@axiomhq/js": "^1.4.0",
|
||||
"pino": "^9.14.0",
|
||||
"pino-pretty": "^13.1.3"
|
||||
},
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Axiom } from "@axiomhq/js";
|
||||
import pino from "pino";
|
||||
|
||||
const isDev = process.env.NODE_ENV !== "production";
|
||||
@@ -8,34 +9,35 @@ const axiomToken = process.env.AXIOM_TOKEN;
|
||||
const axiomDataset = process.env.AXIOM_DATASET;
|
||||
const useAxiom = isCloud && !!axiomToken && !!axiomDataset;
|
||||
|
||||
const targets: pino.TransportTargetOptions[] = [];
|
||||
|
||||
if (isDev) {
|
||||
targets.push({
|
||||
target: "pino-pretty",
|
||||
options: {
|
||||
colorize: true,
|
||||
ignore: "pid,hostname",
|
||||
translateTime: "HH:MM:ss",
|
||||
function createAxiomStream(token: string, dataset: string): pino.DestinationStream {
|
||||
const client = new Axiom({ token });
|
||||
return {
|
||||
write(msg: string) {
|
||||
try {
|
||||
client.ingest(dataset, [JSON.parse(msg) as Record<string, unknown>]);
|
||||
} catch {
|
||||
// ignore malformed log lines
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
if (useAxiom) {
|
||||
targets.push({
|
||||
target: "@axiomhq/pino",
|
||||
options: {
|
||||
dataset: axiomDataset,
|
||||
token: axiomToken,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export const logger = pino({
|
||||
level,
|
||||
...(targets.length > 0 && {
|
||||
transport: { targets },
|
||||
}),
|
||||
});
|
||||
export const logger = useAxiom
|
||||
? pino(
|
||||
{ level },
|
||||
pino.multistream([
|
||||
{ stream: process.stdout, level },
|
||||
{ stream: createAxiomStream(axiomToken, axiomDataset), level },
|
||||
]),
|
||||
)
|
||||
: pino({
|
||||
level,
|
||||
...(isDev && {
|
||||
transport: {
|
||||
target: "pino-pretty",
|
||||
options: { colorize: true, ignore: "pid,hostname", translateTime: "HH:MM:ss" },
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
export const createLogger = (module: string) => logger.child({ module });
|
||||
|
||||
51
pnpm-lock.yaml
generated
51
pnpm-lock.yaml
generated
@@ -504,7 +504,7 @@ importers:
|
||||
|
||||
packages/logger:
|
||||
dependencies:
|
||||
'@axiomhq/pino':
|
||||
'@axiomhq/js':
|
||||
specifier: ^1.4.0
|
||||
version: 1.4.0
|
||||
pino:
|
||||
@@ -898,10 +898,6 @@ packages:
|
||||
resolution: {integrity: sha512-wC5x1ud/QJMstrjpicATkyY8+ZVWEl4WlXMtA5EZf7hkj0+b191yv4yynLxLEfr/MveXora9m6CWdJq4DsbcAg==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
'@axiomhq/pino@1.4.0':
|
||||
resolution: {integrity: sha512-7ujZM1kqbA98BWl8ltWdTLSDE7+67nOvR30/hm8P6omISjaQV0xgtdtZtDGe/BH2VmZeQWPGfAI1FnUNYC3CtQ==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
'@babel/code-frame@7.27.1':
|
||||
resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@@ -4349,10 +4345,6 @@ packages:
|
||||
'@xtuc/long@4.2.2':
|
||||
resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==}
|
||||
|
||||
abort-controller@3.0.0:
|
||||
resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
|
||||
engines: {node: '>=6.5'}
|
||||
|
||||
accepts@1.3.8:
|
||||
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
@@ -5572,10 +5564,6 @@ packages:
|
||||
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
event-target-shim@5.0.1:
|
||||
resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
events@3.3.0:
|
||||
resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
|
||||
engines: {node: '>=0.8.x'}
|
||||
@@ -7228,9 +7216,6 @@ packages:
|
||||
resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
pino-abstract-transport@1.2.0:
|
||||
resolution: {integrity: sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==}
|
||||
|
||||
pino-abstract-transport@2.0.0:
|
||||
resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==}
|
||||
|
||||
@@ -7422,10 +7407,6 @@ packages:
|
||||
process-warning@5.0.0:
|
||||
resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==}
|
||||
|
||||
process@0.11.10:
|
||||
resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==}
|
||||
engines: {node: '>= 0.6.0'}
|
||||
|
||||
prompts@2.4.2:
|
||||
resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==}
|
||||
engines: {node: '>= 6'}
|
||||
@@ -7629,10 +7610,6 @@ packages:
|
||||
resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
readable-stream@4.7.0:
|
||||
resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
|
||||
readdirp@3.5.0:
|
||||
resolution: {integrity: sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==}
|
||||
engines: {node: '>=8.10.0'}
|
||||
@@ -9421,11 +9398,6 @@ snapshots:
|
||||
dependencies:
|
||||
fetch-retry: 6.0.0
|
||||
|
||||
'@axiomhq/pino@1.4.0':
|
||||
dependencies:
|
||||
'@axiomhq/js': 1.4.0
|
||||
pino-abstract-transport: 1.2.0
|
||||
|
||||
'@babel/code-frame@7.27.1':
|
||||
dependencies:
|
||||
'@babel/helper-validator-identifier': 7.27.1
|
||||
@@ -12952,10 +12924,6 @@ snapshots:
|
||||
|
||||
'@xtuc/long@4.2.2': {}
|
||||
|
||||
abort-controller@3.0.0:
|
||||
dependencies:
|
||||
event-target-shim: 5.0.1
|
||||
|
||||
accepts@1.3.8:
|
||||
dependencies:
|
||||
mime-types: 2.1.35
|
||||
@@ -14377,8 +14345,6 @@ snapshots:
|
||||
|
||||
esutils@2.0.3: {}
|
||||
|
||||
event-target-shim@5.0.1: {}
|
||||
|
||||
events@3.3.0: {}
|
||||
|
||||
execa@5.1.1:
|
||||
@@ -16495,11 +16461,6 @@ snapshots:
|
||||
|
||||
pify@2.3.0: {}
|
||||
|
||||
pino-abstract-transport@1.2.0:
|
||||
dependencies:
|
||||
readable-stream: 4.7.0
|
||||
split2: 4.2.0
|
||||
|
||||
pino-abstract-transport@2.0.0:
|
||||
dependencies:
|
||||
split2: 4.2.0
|
||||
@@ -16649,8 +16610,6 @@ snapshots:
|
||||
|
||||
process-warning@5.0.0: {}
|
||||
|
||||
process@0.11.10: {}
|
||||
|
||||
prompts@2.4.2:
|
||||
dependencies:
|
||||
kleur: 3.0.3
|
||||
@@ -16946,14 +16905,6 @@ snapshots:
|
||||
string_decoder: 1.3.0
|
||||
util-deprecate: 1.0.2
|
||||
|
||||
readable-stream@4.7.0:
|
||||
dependencies:
|
||||
abort-controller: 3.0.0
|
||||
buffer: 6.0.3
|
||||
events: 3.3.0
|
||||
process: 0.11.10
|
||||
string_decoder: 1.3.0
|
||||
|
||||
readdirp@3.5.0:
|
||||
dependencies:
|
||||
picomatch: 2.3.1
|
||||
|
||||
Reference in New Issue
Block a user