@goscribe/server 1.0.3 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/context.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import type { CreateExpressContextOptions } from "@trpc/server/adapters/express";
2
2
  export declare function createContext({ req, res }: CreateExpressContextOptions): Promise<{
3
- db: import(".prisma/client").PrismaClient<import(".prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
3
+ db: import("@prisma/client").PrismaClient<import("@prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
4
4
  session: any;
5
5
  req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>;
6
6
  res: import("express").Response<any, Record<string, any>>;
7
+ cookies: Record<string, string | undefined>;
7
8
  }>;
8
9
  export type Context = Awaited<ReturnType<typeof createContext>>;
9
- //# sourceMappingURL=context.d.ts.map
package/dist/context.js CHANGED
@@ -1,8 +1,12 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createContext = createContext;
4
- const prisma_1 = require("./lib/prisma");
5
- async function createContext({ req, res }) {
6
- const session = req.auth ?? null;
7
- return { db: prisma_1.prisma, session, req, res };
1
+ import { prisma } from "./lib/prisma.js";
2
+ import { verifyCustomAuthCookie } from "./lib/auth.js";
3
+ import cookie from "cookie";
4
+ export async function createContext({ req, res }) {
5
+ const cookies = cookie.parse(req.headers.cookie ?? "");
6
+ // Only use custom auth cookie
7
+ const custom = verifyCustomAuthCookie(cookies["auth_token"]);
8
+ if (custom) {
9
+ return { db: prisma, session: { user: { id: custom.userId } }, req, res, cookies };
10
+ }
11
+ return { db: prisma, session: null, req, res, cookies };
8
12
  }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- export type { AppRouter } from "./routers/_app";
2
- export type { RouterInputs } from "./routers/_app";
3
- export type { RouterOutputs } from "./routers/_app";
4
- //# sourceMappingURL=index.d.ts.map
1
+ export type { AppRouter } from "./routers/_app.js";
2
+ export type { RouterInputs } from "./routers/_app.js";
3
+ export type { RouterOutputs } from "./routers/_app.js";
package/dist/index.js CHANGED
@@ -1,2 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ export {};
@@ -1,2 +1,3 @@
1
- export declare const authRouter: (req: import("express").Request, res: import("express").Response, next: import("express").NextFunction) => Promise<void>;
2
- //# sourceMappingURL=auth.d.ts.map
1
+ export declare function verifyCustomAuthCookie(cookieValue: string | undefined): {
2
+ userId: string;
3
+ } | null;
package/dist/lib/auth.js CHANGED
@@ -1,37 +1,40 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.authRouter = void 0;
7
1
  // src/server/auth.ts
8
- const express_1 = require("@auth/express");
9
- const prisma_adapter_1 = require("@auth/prisma-adapter");
10
- const prisma_1 = require("../lib/prisma");
11
- const google_1 = __importDefault(require("@auth/core/providers/google"));
12
- const credentials_1 = __importDefault(require("@auth/core/providers/credentials"));
13
- exports.authRouter = (0, express_1.ExpressAuth)({
14
- providers: [
15
- (0, google_1.default)({
16
- clientId: process.env.GOOGLE_CLIENT_ID,
17
- clientSecret: process.env.GOOGLE_CLIENT_SECRET,
18
- }),
19
- (0, credentials_1.default)({
20
- name: "credentials",
21
- credentials: {
22
- email: { label: "Email", type: "email" },
23
- password: { label: "Password", type: "password" },
24
- },
25
- async authorize(credentials) {
26
- if (credentials?.email === "demo@example.com" &&
27
- credentials?.password === "demo") {
28
- return { id: "1", email: "demo@example.com", name: "Demo User" };
29
- }
30
- return null;
31
- },
32
- }),
33
- ],
34
- adapter: (0, prisma_adapter_1.PrismaAdapter)(prisma_1.prisma),
35
- secret: process.env.AUTH_SECRET,
36
- session: { strategy: "jwt" },
37
- });
2
+ import crypto from "node:crypto";
3
+ // Custom HMAC cookie: auth_token = base64(userId).hex(hmacSHA256(base64(userId), secret))
4
+ export function verifyCustomAuthCookie(cookieValue) {
5
+ if (!cookieValue)
6
+ return null;
7
+ const secret = process.env.CUSTOM_AUTH_SECRET;
8
+ if (!secret)
9
+ return null;
10
+ const parts = cookieValue.split(".");
11
+ if (parts.length !== 2)
12
+ return null;
13
+ const [base64UserId, signatureHex] = parts;
14
+ let userId;
15
+ try {
16
+ const buf = Buffer.from(base64UserId, "base64url");
17
+ userId = buf.toString("utf8");
18
+ }
19
+ catch {
20
+ return null;
21
+ }
22
+ const hmac = crypto.createHmac("sha256", secret);
23
+ hmac.update(base64UserId);
24
+ const expected = hmac.digest("hex");
25
+ if (!timingSafeEqualHex(signatureHex, expected))
26
+ return null;
27
+ return { userId };
28
+ }
29
+ function timingSafeEqualHex(a, b) {
30
+ try {
31
+ const ab = Buffer.from(a, "hex");
32
+ const bb = Buffer.from(b, "hex");
33
+ if (ab.length !== bb.length)
34
+ return false;
35
+ return crypto.timingSafeEqual(ab, bb);
36
+ }
37
+ catch {
38
+ return false;
39
+ }
40
+ }
@@ -1 +0,0 @@
1
- //# sourceMappingURL=file.d.ts.map
@@ -1,3 +1,2 @@
1
1
  import { PrismaClient } from "@prisma/client";
2
- export declare const prisma: PrismaClient<import(".prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
3
- //# sourceMappingURL=prisma.d.ts.map
2
+ export declare const prisma: PrismaClient<import("@prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
@@ -1,11 +1,8 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.prisma = void 0;
4
- const client_1 = require("@prisma/client");
1
+ import { PrismaClient } from "@prisma/client";
5
2
  const globalForPrisma = globalThis;
6
- exports.prisma = globalForPrisma.prisma ??
7
- new client_1.PrismaClient({
3
+ export const prisma = globalForPrisma.prisma ??
4
+ new PrismaClient({
8
5
  // log: ["query"], // enable if you want
9
6
  });
10
7
  if (process.env.NODE_ENV !== "production")
11
- globalForPrisma.prisma = exports.prisma;
8
+ globalForPrisma.prisma = prisma;
@@ -1,4 +1,3 @@
1
1
  import { Storage } from "@google-cloud/storage";
2
2
  export declare const storage: Storage;
3
3
  export declare const bucket: import("@google-cloud/storage").Bucket;
4
- //# sourceMappingURL=storage.d.ts.map
@@ -1,13 +1,10 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.bucket = exports.storage = void 0;
4
1
  // src/server/lib/gcs.ts
5
- const storage_1 = require("@google-cloud/storage");
6
- exports.storage = new storage_1.Storage({
2
+ import { Storage } from "@google-cloud/storage";
3
+ export const storage = new Storage({
7
4
  projectId: process.env.GCP_PROJECT_ID,
8
5
  credentials: {
9
6
  client_email: process.env.GCP_CLIENT_EMAIL,
10
7
  private_key: process.env.GCP_PRIVATE_KEY?.replace(/\\n/g, "\n"),
11
8
  },
12
9
  });
13
- exports.bucket = exports.storage.bucket(process.env.GCP_BUCKET);
10
+ export const bucket = storage.bucket(process.env.GCP_BUCKET);
@@ -1,10 +1,11 @@
1
1
  import { inferRouterInputs, inferRouterOutputs } from '@trpc/server';
2
2
  export declare const appRouter: import("@trpc/server").TRPCBuiltRouter<{
3
3
  ctx: {
4
- db: import(".prisma/client").PrismaClient<import(".prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
4
+ db: import("@prisma/client").PrismaClient<import("@prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
5
5
  session: any;
6
6
  req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>;
7
7
  res: import("express").Response<any, Record<string, any>>;
8
+ cookies: Record<string, string | undefined>;
8
9
  };
9
10
  meta: object;
10
11
  errorShape: import("@trpc/server").TRPCDefaultErrorShape;
@@ -12,10 +13,11 @@ export declare const appRouter: import("@trpc/server").TRPCBuiltRouter<{
12
13
  }, import("@trpc/server").TRPCDecorateCreateRouterOptions<{
13
14
  auth: import("@trpc/server").TRPCBuiltRouter<{
14
15
  ctx: {
15
- db: import(".prisma/client").PrismaClient<import(".prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
16
+ db: import("@prisma/client").PrismaClient<import("@prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
16
17
  session: any;
17
18
  req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>;
18
19
  res: import("express").Response<any, Record<string, any>>;
20
+ cookies: Record<string, string | undefined>;
19
21
  };
20
22
  meta: object;
21
23
  errorShape: import("@trpc/server").TRPCDefaultErrorShape;
@@ -34,13 +36,40 @@ export declare const appRouter: import("@trpc/server").TRPCBuiltRouter<{
34
36
  };
35
37
  meta: object;
36
38
  }>;
39
+ login: import("@trpc/server").TRPCMutationProcedure<{
40
+ input: {
41
+ email: string;
42
+ password: string;
43
+ };
44
+ output: {
45
+ id: string;
46
+ email: string | null;
47
+ name: string | null;
48
+ };
49
+ meta: object;
50
+ }>;
51
+ getSession: import("@trpc/server").TRPCQueryProcedure<{
52
+ input: void;
53
+ output: {
54
+ id: string;
55
+ userId: string;
56
+ user: {
57
+ id: string;
58
+ email: string | null;
59
+ name: string | null;
60
+ image: string | null;
61
+ };
62
+ };
63
+ meta: object;
64
+ }>;
37
65
  }>>;
38
66
  workspace: import("@trpc/server").TRPCBuiltRouter<{
39
67
  ctx: {
40
- db: import(".prisma/client").PrismaClient<import(".prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
68
+ db: import("@prisma/client").PrismaClient<import("@prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
41
69
  session: any;
42
70
  req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>;
43
71
  res: import("express").Response<any, Record<string, any>>;
72
+ cookies: Record<string, string | undefined>;
44
73
  };
45
74
  meta: object;
46
75
  errorShape: import("@trpc/server").TRPCDefaultErrorShape;
@@ -134,7 +163,7 @@ export declare const appRouter: import("@trpc/server").TRPCBuiltRouter<{
134
163
  fileId: string[];
135
164
  id: string;
136
165
  };
137
- output: import(".prisma/client").Prisma.BatchPayload;
166
+ output: import("@prisma/client").Prisma.BatchPayload;
138
167
  meta: object;
139
168
  }>;
140
169
  }>>;
@@ -142,4 +171,3 @@ export declare const appRouter: import("@trpc/server").TRPCBuiltRouter<{
142
171
  export type AppRouter = typeof appRouter;
143
172
  export type RouterInputs = inferRouterInputs<AppRouter>;
144
173
  export type RouterOutputs = inferRouterOutputs<AppRouter>;
145
- //# sourceMappingURL=_app.d.ts.map
@@ -1,10 +1,7 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.appRouter = void 0;
4
- const trpc_1 = require("../trpc");
5
- const auth_1 = require("./auth");
6
- const workspace_1 = require("./workspace");
7
- exports.appRouter = (0, trpc_1.router)({
8
- auth: auth_1.auth,
9
- workspace: workspace_1.workspace
1
+ import { router } from '../trpc.js';
2
+ import { auth } from './auth.js';
3
+ import { workspace } from './workspace.js';
4
+ export const appRouter = router({
5
+ auth,
6
+ workspace
10
7
  });
@@ -1,9 +1,10 @@
1
1
  export declare const auth: import("@trpc/server").TRPCBuiltRouter<{
2
2
  ctx: {
3
- db: import(".prisma/client").PrismaClient<import(".prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
3
+ db: import("@prisma/client").PrismaClient<import("@prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
4
4
  session: any;
5
5
  req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>;
6
6
  res: import("express").Response<any, Record<string, any>>;
7
+ cookies: Record<string, string | undefined>;
7
8
  };
8
9
  meta: object;
9
10
  errorShape: import("@trpc/server").TRPCDefaultErrorShape;
@@ -22,5 +23,30 @@ export declare const auth: import("@trpc/server").TRPCBuiltRouter<{
22
23
  };
23
24
  meta: object;
24
25
  }>;
26
+ login: import("@trpc/server").TRPCMutationProcedure<{
27
+ input: {
28
+ email: string;
29
+ password: string;
30
+ };
31
+ output: {
32
+ id: string;
33
+ email: string | null;
34
+ name: string | null;
35
+ };
36
+ meta: object;
37
+ }>;
38
+ getSession: import("@trpc/server").TRPCQueryProcedure<{
39
+ input: void;
40
+ output: {
41
+ id: string;
42
+ userId: string;
43
+ user: {
44
+ id: string;
45
+ email: string | null;
46
+ name: string | null;
47
+ image: string | null;
48
+ };
49
+ };
50
+ meta: object;
51
+ }>;
25
52
  }>>;
26
- //# sourceMappingURL=auth.d.ts.map
@@ -1,18 +1,12 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.auth = void 0;
7
- const zod_1 = require("zod");
8
- const trpc_1 = require("../trpc");
9
- const bcryptjs_1 = __importDefault(require("bcryptjs"));
10
- exports.auth = (0, trpc_1.router)({
11
- signup: trpc_1.publicProcedure
12
- .input(zod_1.z.object({
13
- name: zod_1.z.string().min(1),
14
- email: zod_1.z.string().email(),
15
- password: zod_1.z.string().min(6),
1
+ import { z } from 'zod';
2
+ import { router, publicProcedure } from '../trpc.js';
3
+ import bcrypt from 'bcryptjs';
4
+ export const auth = router({
5
+ signup: publicProcedure
6
+ .input(z.object({
7
+ name: z.string().min(1),
8
+ email: z.string().email(),
9
+ password: z.string().min(6),
16
10
  }))
17
11
  .mutation(async ({ ctx, input }) => {
18
12
  const existing = await ctx.db.user.findUnique({
@@ -21,7 +15,7 @@ exports.auth = (0, trpc_1.router)({
21
15
  if (existing) {
22
16
  throw new Error("Email already registered");
23
17
  }
24
- const hash = await bcryptjs_1.default.hash(input.password, 10);
18
+ const hash = await bcrypt.hash(input.password, 10);
25
19
  const user = await ctx.db.user.create({
26
20
  data: {
27
21
  name: input.name,
@@ -32,4 +26,42 @@ exports.auth = (0, trpc_1.router)({
32
26
  });
33
27
  return { id: user.id, email: user.email, name: user.name };
34
28
  }),
29
+ login: publicProcedure
30
+ .input(z.object({
31
+ email: z.string().email(),
32
+ password: z.string().min(6),
33
+ }))
34
+ .mutation(async ({ ctx, input }) => {
35
+ const user = await ctx.db.user.findUnique({
36
+ where: { email: input.email },
37
+ });
38
+ if (!user) {
39
+ throw new Error("Invalid credentials");
40
+ }
41
+ const valid = await bcrypt.compare(input.password, user.passwordHash);
42
+ if (!valid) {
43
+ throw new Error("Invalid credentials");
44
+ }
45
+ return { id: user.id, email: user.email, name: user.name };
46
+ }),
47
+ getSession: publicProcedure.query(async ({ ctx }) => {
48
+ const session = await ctx.db.session.findUnique({
49
+ where: {
50
+ id: ctx.session?.id,
51
+ },
52
+ });
53
+ if (!session) {
54
+ throw new Error("Session not found");
55
+ }
56
+ if (session.expires < new Date()) {
57
+ throw new Error("Session expired");
58
+ }
59
+ const user = await ctx.db.user.findUnique({
60
+ where: { id: session.userId },
61
+ });
62
+ if (!user) {
63
+ throw new Error("User not found");
64
+ }
65
+ return { id: session.id, userId: session.userId, user: { id: user.id, email: user.email, name: user.name, image: user.image } };
66
+ }),
35
67
  });
@@ -1,9 +1,10 @@
1
1
  export declare const workspace: import("@trpc/server").TRPCBuiltRouter<{
2
2
  ctx: {
3
- db: import(".prisma/client").PrismaClient<import(".prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
3
+ db: import("@prisma/client").PrismaClient<import("@prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
4
4
  session: any;
5
5
  req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>;
6
6
  res: import("express").Response<any, Record<string, any>>;
7
+ cookies: Record<string, string | undefined>;
7
8
  };
8
9
  meta: object;
9
10
  errorShape: import("@trpc/server").TRPCDefaultErrorShape;
@@ -97,8 +98,7 @@ export declare const workspace: import("@trpc/server").TRPCBuiltRouter<{
97
98
  fileId: string[];
98
99
  id: string;
99
100
  };
100
- output: import(".prisma/client").Prisma.BatchPayload;
101
+ output: import("@prisma/client").Prisma.BatchPayload;
101
102
  meta: object;
102
103
  }>;
103
104
  }>>;
104
- //# sourceMappingURL=workspace.d.ts.map
@@ -1,12 +1,9 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.workspace = void 0;
4
- const zod_1 = require("zod");
5
- const trpc_1 = require("../trpc");
6
- const storage_1 = require("src/lib/storage");
7
- exports.workspace = (0, trpc_1.router)({
1
+ import { z } from 'zod';
2
+ import { router, authedProcedure } from '../trpc.js';
3
+ import { bucket } from '../lib/storage.js';
4
+ export const workspace = router({
8
5
  // Mutation with Zod input
9
- list: trpc_1.publicProcedure
6
+ list: authedProcedure
10
7
  .query(async ({ ctx, input }) => {
11
8
  const workspaces = await ctx.db.workspace.findMany({
12
9
  where: {
@@ -15,10 +12,10 @@ exports.workspace = (0, trpc_1.router)({
15
12
  });
16
13
  return workspaces;
17
14
  }),
18
- create: trpc_1.publicProcedure
19
- .input(zod_1.z.object({
20
- name: zod_1.z.string().min(1).max(100),
21
- description: zod_1.z.string().max(500).optional(),
15
+ create: authedProcedure
16
+ .input(z.object({
17
+ name: z.string().min(1).max(100),
18
+ description: z.string().max(500).optional(),
22
19
  }))
23
20
  .mutation(({ ctx, input }) => {
24
21
  return ctx.db.workspace.create({
@@ -29,9 +26,9 @@ exports.workspace = (0, trpc_1.router)({
29
26
  },
30
27
  });
31
28
  }),
32
- get: trpc_1.publicProcedure
33
- .input(zod_1.z.object({
34
- id: zod_1.z.string().uuid(),
29
+ get: authedProcedure
30
+ .input(z.object({
31
+ id: z.string().uuid(),
35
32
  }))
36
33
  .query(({ ctx, input }) => {
37
34
  return ctx.db.workspace.findUnique({
@@ -40,11 +37,11 @@ exports.workspace = (0, trpc_1.router)({
40
37
  },
41
38
  });
42
39
  }),
43
- update: trpc_1.publicProcedure
44
- .input(zod_1.z.object({
45
- id: zod_1.z.string().uuid(),
46
- name: zod_1.z.string().min(1).max(100).optional(),
47
- description: zod_1.z.string().max(500).optional(),
40
+ update: authedProcedure
41
+ .input(z.object({
42
+ id: z.string().uuid(),
43
+ name: z.string().min(1).max(100).optional(),
44
+ description: z.string().max(500).optional(),
48
45
  }))
49
46
  .mutation(({ ctx, input }) => {
50
47
  return ctx.db.workspace.update({
@@ -57,9 +54,9 @@ exports.workspace = (0, trpc_1.router)({
57
54
  },
58
55
  });
59
56
  }),
60
- delete: trpc_1.publicProcedure
61
- .input(zod_1.z.object({
62
- id: zod_1.z.string().uuid(),
57
+ delete: authedProcedure
58
+ .input(z.object({
59
+ id: z.string().uuid(),
63
60
  }))
64
61
  .mutation(({ ctx, input }) => {
65
62
  ctx.db.workspace.delete({
@@ -69,13 +66,13 @@ exports.workspace = (0, trpc_1.router)({
69
66
  });
70
67
  return true;
71
68
  }),
72
- uploadFiles: trpc_1.publicProcedure
73
- .input(zod_1.z.object({
74
- id: zod_1.z.string().uuid(),
75
- files: zod_1.z.array(zod_1.z.object({
76
- filename: zod_1.z.string().min(1).max(255),
77
- contentType: zod_1.z.string().min(1).max(100),
78
- size: zod_1.z.number().min(1), // size in bytes
69
+ uploadFiles: authedProcedure
70
+ .input(z.object({
71
+ id: z.string().uuid(),
72
+ files: z.array(z.object({
73
+ filename: z.string().min(1).max(255),
74
+ contentType: z.string().min(1).max(100),
75
+ size: z.number().min(1), // size in bytes
79
76
  })),
80
77
  }))
81
78
  .mutation(async ({ ctx, input }) => {
@@ -92,7 +89,7 @@ exports.workspace = (0, trpc_1.router)({
92
89
  },
93
90
  });
94
91
  // 2. Generate signed URL for direct upload
95
- const [url] = await storage_1.bucket
92
+ const [url] = await bucket
96
93
  .file(`${ctx.session.user.id}/${record.id}-${file.filename}`)
97
94
  .getSignedUrl({
98
95
  action: "write",
@@ -103,7 +100,7 @@ exports.workspace = (0, trpc_1.router)({
103
100
  await ctx.db.fileAsset.update({
104
101
  where: { id: record.id },
105
102
  data: {
106
- bucket: storage_1.bucket.name,
103
+ bucket: bucket.name,
107
104
  objectKey: `${ctx.session.user.id}/${record.id}-${file.filename}`,
108
105
  },
109
106
  });
@@ -114,10 +111,10 @@ exports.workspace = (0, trpc_1.router)({
114
111
  }
115
112
  return results;
116
113
  }),
117
- deleteFiles: trpc_1.publicProcedure
118
- .input(zod_1.z.object({
119
- fileId: zod_1.z.array(zod_1.z.string().uuid()),
120
- id: zod_1.z.string().uuid(),
114
+ deleteFiles: authedProcedure
115
+ .input(z.object({
116
+ fileId: z.array(z.string().uuid()),
117
+ id: z.string().uuid(),
121
118
  }))
122
119
  .mutation(({ ctx, input }) => {
123
120
  const files = ctx.db.fileAsset.findMany({
@@ -130,7 +127,7 @@ exports.workspace = (0, trpc_1.router)({
130
127
  files.then((fileRecords) => {
131
128
  fileRecords.forEach((file) => {
132
129
  if (file.bucket && file.objectKey) {
133
- const gcsFile = storage_1.bucket.file(file.objectKey);
130
+ const gcsFile = bucket.file(file.objectKey);
134
131
  gcsFile.delete({ ignoreNotFound: true }).catch((err) => {
135
132
  console.error(`Error deleting file ${file.objectKey} from bucket ${file.bucket}:`, err);
136
133
  });
package/dist/server.d.ts CHANGED
@@ -1,2 +1 @@
1
1
  export {};
2
- //# sourceMappingURL=server.d.ts.map
package/dist/server.js CHANGED
@@ -1,71 +1,31 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- const express_1 = __importDefault(require("express"));
40
- const cors_1 = __importDefault(require("cors"));
41
- const helmet_1 = __importDefault(require("helmet"));
42
- const morgan_1 = __importDefault(require("morgan"));
43
- const compression_1 = __importDefault(require("compression"));
44
- const trpcExpress = __importStar(require("@trpc/server/adapters/express"));
45
- const auth_1 = require("./lib/auth");
46
- const _app_1 = require("./routers/_app");
47
- const context_1 = require("./context");
1
+ import express from 'express';
2
+ import cors from 'cors';
3
+ import helmet from 'helmet';
4
+ import morgan from 'morgan';
5
+ import compression from 'compression';
6
+ import * as trpcExpress from '@trpc/server/adapters/express';
7
+ import { appRouter } from './routers/_app.js';
8
+ import { createContext } from './context.js';
48
9
  const PORT = process.env.PORT ? Number(process.env.PORT) : 3001;
49
10
  async function main() {
50
- const app = (0, express_1.default)();
11
+ const app = express();
51
12
  // Middlewares
52
- app.use((0, helmet_1.default)());
53
- app.use((0, cors_1.default)({
13
+ app.use(helmet());
14
+ app.use(cors({
54
15
  origin: "http://localhost:3000", // your Next.js dev URL
55
16
  credentials: true, // allow cookies
56
17
  }));
57
- app.use((0, morgan_1.default)('dev'));
58
- app.use((0, compression_1.default)());
59
- app.use(express_1.default.json());
60
- app.use("/auth", auth_1.authRouter); // Auth routes live under /auth/*
18
+ app.use(morgan('dev'));
19
+ app.use(compression());
20
+ app.use(express.json());
61
21
  // Health (plain Express)
62
22
  app.get('/', (_req, res) => {
63
23
  res.json({ ok: true, service: 'trpc-express', ts: Date.now() });
64
24
  });
65
25
  // tRPC mounted under /trpc
66
26
  app.use('/trpc', trpcExpress.createExpressMiddleware({
67
- router: _app_1.appRouter,
68
- createContext: context_1.createContext,
27
+ router: appRouter,
28
+ createContext,
69
29
  }));
70
30
  app.listen(PORT, () => {
71
31
  console.log(`✅ Server ready on http://localhost:${PORT}`);
package/dist/trpc.d.ts CHANGED
@@ -1,41 +1,42 @@
1
1
  export declare const router: import("@trpc/server").TRPCRouterBuilder<{
2
2
  ctx: {
3
- db: import(".prisma/client").PrismaClient<import(".prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
3
+ db: import("@prisma/client").PrismaClient<import("@prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
4
4
  session: any;
5
5
  req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>;
6
6
  res: import("express").Response<any, Record<string, any>>;
7
+ cookies: Record<string, string | undefined>;
7
8
  };
8
9
  meta: object;
9
10
  errorShape: import("@trpc/server").TRPCDefaultErrorShape;
10
11
  transformer: true;
11
12
  }>;
12
13
  export declare const middleware: <$ContextOverrides>(fn: import("@trpc/server").TRPCMiddlewareFunction<{
13
- db: import(".prisma/client").PrismaClient<import(".prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
14
+ db: import("@prisma/client").PrismaClient<import("@prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
14
15
  session: any;
15
16
  req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>;
16
17
  res: import("express").Response<any, Record<string, any>>;
18
+ cookies: Record<string, string | undefined>;
17
19
  }, object, object, $ContextOverrides, unknown>) => import("@trpc/server").TRPCMiddlewareBuilder<{
18
- db: import(".prisma/client").PrismaClient<import(".prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
20
+ db: import("@prisma/client").PrismaClient<import("@prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
19
21
  session: any;
20
22
  req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>;
21
23
  res: import("express").Response<any, Record<string, any>>;
24
+ cookies: Record<string, string | undefined>;
22
25
  }, object, $ContextOverrides, unknown>;
23
26
  export declare const publicProcedure: import("@trpc/server").TRPCProcedureBuilder<{
24
- db: import(".prisma/client").PrismaClient<import(".prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
27
+ db: import("@prisma/client").PrismaClient<import("@prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
25
28
  session: any;
26
29
  req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>;
27
30
  res: import("express").Response<any, Record<string, any>>;
31
+ cookies: Record<string, string | undefined>;
28
32
  }, object, object, import("@trpc/server").TRPCUnsetMarker, import("@trpc/server").TRPCUnsetMarker, import("@trpc/server").TRPCUnsetMarker, import("@trpc/server").TRPCUnsetMarker, false>;
29
33
  /** Exported authed procedure */
30
34
  export declare const authedProcedure: import("@trpc/server").TRPCProcedureBuilder<{
31
- db: import(".prisma/client").PrismaClient<import(".prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
35
+ db: import("@prisma/client").PrismaClient<import("@prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
32
36
  session: any;
33
37
  req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>;
34
38
  res: import("express").Response<any, Record<string, any>>;
39
+ cookies: Record<string, string | undefined>;
35
40
  }, object, {
36
- req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>;
37
- res: import("express").Response<any, Record<string, any>>;
38
- db: import(".prisma/client").PrismaClient<import(".prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
39
41
  session: any;
40
42
  }, import("@trpc/server").TRPCUnsetMarker, import("@trpc/server").TRPCUnsetMarker, import("@trpc/server").TRPCUnsetMarker, import("@trpc/server").TRPCUnsetMarker, false>;
41
- //# sourceMappingURL=trpc.d.ts.map
package/dist/trpc.js CHANGED
@@ -1,38 +1,25 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.authedProcedure = exports.publicProcedure = exports.middleware = exports.router = void 0;
7
- const server_1 = require("@trpc/server");
8
- const superjson_1 = __importDefault(require("superjson"));
9
- const t = server_1.initTRPC.context().create({
10
- transformer: superjson_1.default,
1
+ import { initTRPC, TRPCError } from "@trpc/server";
2
+ import superjson from "superjson";
3
+ const t = initTRPC.context().create({
4
+ transformer: superjson,
11
5
  errorFormatter({ shape }) {
12
6
  return shape;
13
7
  },
14
8
  });
15
- exports.router = t.router;
16
- exports.middleware = t.middleware;
17
- exports.publicProcedure = t.procedure;
9
+ export const router = t.router;
10
+ export const middleware = t.middleware;
11
+ export const publicProcedure = t.procedure;
18
12
  /** Middleware that enforces authentication */
19
- const isAuthed = (0, exports.middleware)(({ ctx, next }) => {
20
- if (!ctx.session?.user?.id) {
21
- throw new server_1.TRPCError({ code: "UNAUTHORIZED" });
13
+ const isAuthed = middleware(({ ctx, next }) => {
14
+ const hasUser = Boolean(ctx.session?.user?.id);
15
+ if (!ctx.session || !hasUser) {
16
+ throw new TRPCError({ code: "UNAUTHORIZED" });
22
17
  }
23
18
  return next({
24
19
  ctx: {
25
- ...ctx,
26
- // refine ctx: session is guaranteed, user.id is string
27
- session: {
28
- ...ctx.session,
29
- user: {
30
- ...ctx.session.user,
31
- id: ctx.session.user.id, // typed non-null
32
- },
33
- },
20
+ session: ctx.session,
34
21
  },
35
22
  });
36
23
  });
37
24
  /** Exported authed procedure */
38
- exports.authedProcedure = exports.publicProcedure.use(isAuthed);
25
+ export const authedProcedure = publicProcedure.use(isAuthed);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goscribe/server",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -24,8 +24,10 @@
24
24
  "@google-cloud/storage": "^7.17.0",
25
25
  "@prisma/client": "^6.14.0",
26
26
  "@trpc/server": "^11.5.0",
27
+ "@types/cookie": "^1.0.0",
27
28
  "bcryptjs": "^3.0.2",
28
29
  "compression": "^1.8.1",
30
+ "cookie": "^1.0.2",
29
31
  "cors": "^2.8.5",
30
32
  "express": "^5.1.0",
31
33
  "helmet": "^8.1.0",
@@ -6,6 +6,7 @@ generator client {
6
6
  datasource db {
7
7
  provider = "postgresql"
8
8
  url = env("DATABASE_URL")
9
+ directUrl = env("DIRECT_URL") // for shadow db in migrations
9
10
  }
10
11
 
11
12
  //
@@ -35,6 +36,7 @@ model User {
35
36
  emailVerified DateTime?
36
37
  passwordHash String? // for credentials login
37
38
  image String?
39
+ session Session[]
38
40
 
39
41
  // Ownership
40
42
  folders Folder[] @relation("UserFolders")
@@ -43,30 +45,15 @@ model User {
43
45
  artifacts Artifact[] @relation("UserArtifacts")
44
46
  versions ArtifactVersion[] @relation("UserArtifactVersions")
45
47
 
46
- accounts Account[]
47
-
48
48
  createdAt DateTime @default(now())
49
49
  updatedAt DateTime @updatedAt
50
50
  }
51
51
 
52
- model Account {
53
- id String @id @default(cuid())
54
- userId String
55
- type String
56
- provider String
57
- providerAccountId String
58
-
59
- refresh_token String?
60
- access_token String?
61
- expires_at Int?
62
- token_type String?
63
- scope String?
64
- id_token String?
65
- session_state String?
66
-
67
- user User @relation(fields: [userId], references: [id], onDelete: Cascade)
68
-
69
- @@unique([provider, providerAccountId])
52
+ model Session {
53
+ id String @id @default(cuid())
54
+ userId String
55
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
56
+ expires DateTime
70
57
  }
71
58
 
72
59
  model VerificationToken {
package/src/context.ts CHANGED
@@ -1,11 +1,19 @@
1
1
  // src/server/trpc/context.ts
2
2
  import type { CreateExpressContextOptions } from "@trpc/server/adapters/express";
3
3
  import { prisma } from "./lib/prisma.js";
4
+ import { verifyCustomAuthCookie } from "./lib/auth.js";
5
+ import cookie from "cookie";
4
6
 
5
7
  export async function createContext({ req, res }: CreateExpressContextOptions) {
6
- const session = (req as any).auth ?? null;
7
-
8
- return { db: prisma, session, req, res };
8
+ const cookies = cookie.parse(req.headers.cookie ?? "");
9
+
10
+ // Only use custom auth cookie
11
+ const custom = verifyCustomAuthCookie(cookies["auth_token"]);
12
+ if (custom) {
13
+ return { db: prisma, session: { user: { id: custom.userId } } as any, req, res, cookies };
14
+ }
15
+
16
+ return { db: prisma, session: null, req, res, cookies };
9
17
  }
10
18
 
11
19
  export type Context = Awaited<ReturnType<typeof createContext>>;
package/src/lib/auth.ts CHANGED
@@ -1,34 +1,39 @@
1
1
  // src/server/auth.ts
2
- import { ExpressAuth } from "@auth/express";
3
- import { PrismaAdapter } from "@auth/prisma-adapter";
4
- import { prisma } from "../lib/prisma.js";
5
- import Google from "@auth/core/providers/google";
6
- import Credentials from "@auth/core/providers/credentials";
2
+ import crypto from "node:crypto";
7
3
 
8
- export const authRouter = ExpressAuth({
9
- providers: [
10
- Google({
11
- clientId: process.env.GOOGLE_CLIENT_ID!,
12
- clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
13
- }),
14
- Credentials({
15
- name: "credentials",
16
- credentials: {
17
- email: { label: "Email", type: "email" },
18
- password: { label: "Password", type: "password" },
19
- },
20
- async authorize(credentials) {
21
- if (
22
- credentials?.email === "demo@example.com" &&
23
- credentials?.password === "demo"
24
- ) {
25
- return { id: "1", email: "demo@example.com", name: "Demo User" };
26
- }
27
- return null;
28
- },
29
- }),
30
- ],
31
- adapter: PrismaAdapter(prisma),
32
- secret: process.env.AUTH_SECRET!,
33
- session: { strategy: "jwt" },
34
- })
4
+ // Custom HMAC cookie: auth_token = base64(userId).hex(hmacSHA256(base64(userId), secret))
5
+ export function verifyCustomAuthCookie(cookieValue: string | undefined): { userId: string } | null {
6
+ if (!cookieValue) return null;
7
+ const secret = process.env.CUSTOM_AUTH_SECRET;
8
+ if (!secret) return null;
9
+
10
+ const parts = cookieValue.split(".");
11
+ if (parts.length !== 2) return null;
12
+ const [base64UserId, signatureHex] = parts;
13
+
14
+ let userId: string;
15
+ try {
16
+ const buf = Buffer.from(base64UserId, "base64url");
17
+ userId = buf.toString("utf8");
18
+ } catch {
19
+ return null;
20
+ }
21
+
22
+ const hmac = crypto.createHmac("sha256", secret);
23
+ hmac.update(base64UserId);
24
+ const expected = hmac.digest("hex");
25
+ if (!timingSafeEqualHex(signatureHex, expected)) return null;
26
+
27
+ return { userId };
28
+ }
29
+
30
+ function timingSafeEqualHex(a: string, b: string): boolean {
31
+ try {
32
+ const ab = Buffer.from(a, "hex");
33
+ const bb = Buffer.from(b, "hex");
34
+ if (ab.length !== bb.length) return false;
35
+ return crypto.timingSafeEqual(ab, bb);
36
+ } catch {
37
+ return false;
38
+ }
39
+ }
@@ -3,7 +3,7 @@ import { router, publicProcedure, authedProcedure } from '../trpc.js';
3
3
  import bcrypt from 'bcryptjs';
4
4
 
5
5
  export const auth = router({
6
- signup: publicProcedure
6
+ signup: publicProcedure
7
7
  .input(z.object({
8
8
  name: z.string().min(1),
9
9
  email: z.string().email(),
@@ -30,5 +30,50 @@ signup: publicProcedure
30
30
 
31
31
  return { id: user.id, email: user.email, name: user.name };
32
32
  }),
33
+ login: publicProcedure
34
+ .input(z.object({
35
+ email: z.string().email(),
36
+ password: z.string().min(6),
37
+ }))
38
+ .mutation(async ({ ctx, input }) => {
39
+ const user = await ctx.db.user.findUnique({
40
+ where: { email: input.email },
41
+ });
42
+ if (!user) {
43
+ throw new Error("Invalid credentials");
44
+ }
45
+
46
+ const valid = await bcrypt.compare(input.password, user.passwordHash!);
47
+ if (!valid) {
48
+ throw new Error("Invalid credentials");
49
+ }
50
+
51
+ return { id: user.id, email: user.email, name: user.name };
52
+ }),
53
+ getSession: publicProcedure.query(async ({ ctx }) => {
54
+ const session = await ctx.db.session.findUnique({
55
+ where: {
56
+ id: ctx.session?.id,
57
+ },
58
+ });
59
+
60
+ if (!session) {
61
+ throw new Error("Session not found");
62
+ }
63
+
64
+ if (session.expires < new Date()) {
65
+ throw new Error("Session expired");
66
+ }
67
+
68
+ const user = await ctx.db.user.findUnique({
69
+ where: { id: session.userId },
70
+ });
71
+
72
+ if (!user) {
73
+ throw new Error("User not found");
74
+ }
75
+
76
+ return { id: session.id, userId: session.userId, user: { id: user.id, email: user.email, name: user.name, image: user.image } };
77
+ }),
33
78
  });
34
79
 
@@ -5,7 +5,7 @@ import { FileAsset } from '@prisma/client';
5
5
 
6
6
  export const workspace = router({
7
7
  // Mutation with Zod input
8
- list: publicProcedure
8
+ list: authedProcedure
9
9
  .query(async ({ ctx, input }) => {
10
10
  const workspaces = await ctx.db.workspace.findMany({
11
11
  where: {
@@ -15,7 +15,7 @@ export const workspace = router({
15
15
  return workspaces;
16
16
  }),
17
17
 
18
- create: publicProcedure
18
+ create: authedProcedure
19
19
  .input(z.object({
20
20
  name: z.string().min(1).max(100),
21
21
  description: z.string().max(500).optional(),
@@ -29,7 +29,7 @@ export const workspace = router({
29
29
  },
30
30
  });
31
31
  }),
32
- get: publicProcedure
32
+ get: authedProcedure
33
33
  .input(z.object({
34
34
  id: z.string().uuid(),
35
35
  }))
@@ -40,7 +40,7 @@ export const workspace = router({
40
40
  },
41
41
  });
42
42
  }),
43
- update: publicProcedure
43
+ update: authedProcedure
44
44
  .input(z.object({
45
45
  id: z.string().uuid(),
46
46
  name: z.string().min(1).max(100).optional(),
@@ -57,7 +57,7 @@ export const workspace = router({
57
57
  },
58
58
  });
59
59
  }),
60
- delete: publicProcedure
60
+ delete: authedProcedure
61
61
  .input(z.object({
62
62
  id: z.string().uuid(),
63
63
  }))
@@ -69,7 +69,7 @@ export const workspace = router({
69
69
  });
70
70
  return true;
71
71
  }),
72
- uploadFiles: publicProcedure
72
+ uploadFiles: authedProcedure
73
73
  .input(z.object({
74
74
  id: z.string().uuid(),
75
75
  files: z.array(
@@ -122,7 +122,7 @@ export const workspace = router({
122
122
  return results;
123
123
 
124
124
  }),
125
- deleteFiles: publicProcedure
125
+ deleteFiles: authedProcedure
126
126
  .input(z.object({
127
127
  fileId: z.array(z.string().uuid()),
128
128
  id: z.string().uuid(),
package/src/server.ts CHANGED
@@ -4,7 +4,6 @@ import helmet from 'helmet';
4
4
  import morgan from 'morgan';
5
5
  import compression from 'compression';
6
6
  import * as trpcExpress from '@trpc/server/adapters/express';
7
- import { authRouter } from './lib/auth.js';
8
7
 
9
8
  import { appRouter } from './routers/_app.js';
10
9
  import { createContext } from './context.js';
@@ -25,8 +24,6 @@ async function main() {
25
24
  app.use(compression());
26
25
  app.use(express.json());
27
26
 
28
- app.use("/auth", authRouter); // Auth routes live under /auth/*
29
-
30
27
 
31
28
  // Health (plain Express)
32
29
  app.get('/', (_req, res) => {
package/src/trpc.ts CHANGED
@@ -15,20 +15,14 @@ export const publicProcedure = t.procedure;
15
15
 
16
16
  /** Middleware that enforces authentication */
17
17
  const isAuthed = middleware(({ ctx, next }) => {
18
- if (!ctx.session?.user?.id) {
18
+ const hasUser = Boolean((ctx.session as any)?.user?.id);
19
+ if (!ctx.session || !hasUser) {
19
20
  throw new TRPCError({ code: "UNAUTHORIZED" });
20
21
  }
22
+
21
23
  return next({
22
24
  ctx: {
23
- ...ctx,
24
- // refine ctx: session is guaranteed, user.id is string
25
- session: {
26
- ...ctx.session,
27
- user: {
28
- ...ctx.session.user,
29
- id: ctx.session.user.id, // typed non-null
30
- },
31
- },
25
+ session: ctx.session,
32
26
  },
33
27
  });
34
28
  });
@@ -1 +0,0 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAGjF,wBAAsB,aAAa,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,2BAA2B;;;;;GAI5E;AAED,MAAM,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,UAAU,0HA0BnB,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/lib/file.ts"],"names":[],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"prisma.d.ts","sourceRoot":"","sources":["../../src/lib/prisma.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAI9C,eAAO,MAAM,MAAM,gIAIf,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/lib/storage.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAEhD,eAAO,MAAM,OAAO,SAMlB,CAAC;AAEH,eAAO,MAAM,MAAM,wCAA0C,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"_app.d.ts","sourceRoot":"","sources":["../../src/routers/_app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAKrE,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAGpB,CAAC;AAGH,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC;AACzC,MAAM,MAAM,YAAY,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;AACxD,MAAM,MAAM,aAAa,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/routers/auth.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;GA4Bf,CAAC"}
@@ -1,21 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.sampleRouter = void 0;
4
- const zod_1 = require("zod");
5
- const trpc_1 = require("../trpc");
6
- exports.sampleRouter = (0, trpc_1.router)({
7
- // GET-like: query without input
8
- hello: trpc_1.publicProcedure.query(() => {
9
- return { message: 'Hello from tRPC + Express 👋' };
10
- }),
11
- // Mutation with Zod input
12
- echo: trpc_1.publicProcedure
13
- .input(zod_1.z.object({ text: zod_1.z.string().min(1) }))
14
- .mutation(({ input }) => {
15
- return { echoed: input.text };
16
- }),
17
- // Authed query
18
- me: trpc_1.authedProcedure.query(({ ctx }) => {
19
- return { userId: ctx.user.id, role: ctx.user.role };
20
- }),
21
- });
@@ -1 +0,0 @@
1
- {"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../../src/routers/workspace.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuJpB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"trpc.d.ts","sourceRoot":"","sources":["../src/trpc.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,MAAM;;;;;;;;;;EAAW,CAAC;AAC/B,eAAO,MAAM,UAAU;;;;;;;;;;sCAAe,CAAC;AACvC,eAAO,MAAM,eAAe;;;;;yLAAc,CAAC;AAsB3C,gCAAgC;AAChC,eAAO,MAAM,eAAe;;;;;;;;;;yKAAgC,CAAC"}