@beignet/cli 0.0.23 → 0.0.24

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/src/make.ts CHANGED
@@ -7188,7 +7188,7 @@ function listUseCaseFile(
7188
7188
  `list-${names.pluralKebab}.ts`,
7189
7189
  );
7190
7190
 
7191
- return `import type { beignetServerOnly } from "@beignet/core/server-only";
7191
+ return `import "@beignet/core/server-only";
7192
7192
  import { normalizeCursorPage } from "@beignet/core/pagination";
7193
7193
  import { useCase } from "${relativeModule(filePath, config.paths.useCaseBuilder)}";
7194
7194
  import {
@@ -7228,7 +7228,7 @@ function createUseCaseFile(
7228
7228
  `create-${names.singularKebab}.ts`,
7229
7229
  );
7230
7230
 
7231
- return `import type { beignetServerOnly } from "@beignet/core/server-only";
7231
+ return `import "@beignet/core/server-only";
7232
7232
  import { useCase } from "${relativeModule(filePath, config.paths.useCaseBuilder)}";
7233
7233
  import {
7234
7234
  Create${names.singularPascal}InputSchema,
@@ -7260,7 +7260,7 @@ function getUseCaseFile(
7260
7260
  `get-${names.singularKebab}.ts`,
7261
7261
  );
7262
7262
 
7263
- return `import type { beignetServerOnly } from "@beignet/core/server-only";
7263
+ return `import "@beignet/core/server-only";
7264
7264
  import { appError } from "${relativeModule(filePath, resourceSharedErrorsPath(config))}";
7265
7265
  import { useCase } from "${relativeModule(filePath, config.paths.useCaseBuilder)}";
7266
7266
  import {
@@ -7295,7 +7295,7 @@ function updateUseCaseFile(
7295
7295
  `update-${names.singularKebab}.ts`,
7296
7296
  );
7297
7297
 
7298
- return `import type { beignetServerOnly } from "@beignet/core/server-only";
7298
+ return `import "@beignet/core/server-only";
7299
7299
  import { appError } from "${relativeModule(filePath, resourceSharedErrorsPath(config))}";
7300
7300
  import { useCase } from "${relativeModule(filePath, config.paths.useCaseBuilder)}";
7301
7301
  ${options.events ? `import { ${names.singularPascal}Updated } from "../domain/events";\n` : ""}import {
@@ -7344,7 +7344,7 @@ function deleteUseCaseFile(
7344
7344
  `delete-${names.singularKebab}.ts`,
7345
7345
  );
7346
7346
 
7347
- return `import type { beignetServerOnly } from "@beignet/core/server-only";
7347
+ return `import "@beignet/core/server-only";
7348
7348
  import { z } from "zod";
7349
7349
  import { appError } from "${relativeModule(filePath, resourceSharedErrorsPath(config))}";
7350
7350
  import { useCase } from "${relativeModule(filePath, config.paths.useCaseBuilder)}";
@@ -7454,7 +7454,7 @@ function inMemoryRepositoryFile(
7454
7454
  return true;`
7455
7455
  : `${options.tenant ? `\t\t\tconst existing = ${names.pluralCamel}.get(id);\n\t\t\tif (existing?.tenantId !== filter.tenantId) return false;\n` : ""} return ${names.pluralCamel}.delete(id);`;
7456
7456
 
7457
- return `import type { beignetServerOnly } from "@beignet/core/server-only";
7457
+ return `import "@beignet/core/server-only";
7458
7458
  import { cursorPageResult } from "@beignet/core/pagination";
7459
7459
  import type { ${names.singularPascal}Repository } from "${aliasModule(repositoryPortPath)}";
7460
7460
  import { encode${names.singularPascal}Cursor } from "${aliasModule(resourceSchemaFilePath(names, config))}";
@@ -7833,7 +7833,7 @@ ${options.softDelete ? `\t\t\tconst now = new Date().toISOString();\n\t\t\tconst
7833
7833
  },
7834
7834
  `;
7835
7835
 
7836
- return `import type { beignetServerOnly } from "@beignet/core/server-only";
7836
+ return `import "@beignet/core/server-only";
7837
7837
  import { cursorPageResult } from "@beignet/core/pagination";
7838
7838
  import type { ${dialect.dbTypeName} } from "@beignet/provider-db-drizzle/${dialect.subpath}";
7839
7839
  import { ${drizzleImports.join(", ")} } from "drizzle-orm";
@@ -8068,7 +8068,7 @@ function standaloneUseCaseFile(
8068
8068
  config: ResolvedBeignetConfig,
8069
8069
  filePath: string,
8070
8070
  ): string {
8071
- return `import type { beignetServerOnly } from "@beignet/core/server-only";
8071
+ return `import "@beignet/core/server-only";
8072
8072
  import { z } from "zod";
8073
8073
  import { useCase } from "${relativeModule(filePath, config.paths.useCaseBuilder)}";
8074
8074
 
@@ -10101,7 +10101,7 @@ function routeGroupFile(
10101
10101
  const contractsPath = resourceContractFilePath(names, config);
10102
10102
  const useCasesPath = resourceUseCaseIndexPath(names, config);
10103
10103
 
10104
- return `import type { beignetServerOnly } from "@beignet/core/server-only";
10104
+ return `import "@beignet/core/server-only";
10105
10105
  import { defineRouteGroup } from "@beignet/next";
10106
10106
  import type { AppContext } from "${relativeModule(routeFilePath, config.paths.appContext)}";
10107
10107
  import {
@@ -10138,12 +10138,12 @@ function testFile(
10138
10138
  path.dirname(config.paths.server),
10139
10139
  "context.ts",
10140
10140
  );
10141
- const requestTarget = options.tenant ? "requester" : "app";
10141
+ const requestTarget = "app";
10142
10142
 
10143
10143
  return `import { describe, expect, it } from "bun:test";
10144
10144
  import { createUseCaseTester } from "@beignet/core/application";
10145
10145
  ${mode === "resource" ? `import { isAppError } from "@beignet/core/errors";\n` : ""}import { defineRoutes } from "@beignet/web";
10146
- import { createTestApp${options.tenant ? ", createTestRequester" : ""} } from "@beignet/web/testing";
10146
+ import { createTestApp } from "@beignet/web/testing";
10147
10147
  import { createInMemoryDevtools } from "@beignet/devtools";
10148
10148
  import { createTestContextFactory, createTestPorts } from "@beignet/core/testing";
10149
10149
  import { ${options.auth ? "createTestUserActor" : "createTestAnonymousActor"}${options.tenant ? ", createTestTenant" : ""} } from "@beignet/core/ports/testing";
@@ -10192,13 +10192,15 @@ ${options.tenant ? `\t\t\t{\n\t\t\t\tid: "00000000-0000-4000-8000-000000000104",
10192
10192
  overrides: {
10193
10193
  ${names.pluralCamel},
10194
10194
  ${
10195
- options.auth
10195
+ options.auth || options.tenant
10196
10196
  ? `\t\t\t\tauth: {
10197
10197
  getSession: async () => ({
10198
- user: { id: "user_test", name: "Test User" },
10198
+ user: { id: "user_test", name: "Test User"${options.tenant ? `, tenantId: "tenant_test"` : ""} },
10199
+ ${options.tenant ? `\t\t\t\t\t\tsession: { tenantId: "tenant_test" },\n` : ""}
10199
10200
  }),
10200
10201
  },
10201
- gate: appPorts.gate,\n`
10202
+ ${options.auth ? `\t\t\t\tgate: appPorts.gate,\n` : ""}
10203
+ `
10202
10204
  : `\t\t\t\tauth: {
10203
10205
  getSession: async () => null,
10204
10206
  },\n`
@@ -10348,7 +10350,6 @@ ${
10348
10350
  routes: defineRoutes<AppContext>([${names.singularCamel}Routes]),
10349
10351
  context: appContext,
10350
10352
  });
10351
- ${options.tenant ? `\t\tconst requester = createTestRequester(app, {\n\t\t\theaders: { "x-tenant-id": "tenant_test" },\n\t\t});\n` : ""}
10352
10353
  const createdViaRoute = await ${requestTarget}.request(create${names.singularPascal}, {
10353
10354
  body: { name: "Second ${names.singularPascal}" },
10354
10355
  });
@@ -419,7 +419,7 @@ export function envExample(ctx: TemplateContext): string {
419
419
  "# Copy to .env.local and fill in values for your app.",
420
420
  "APP_URL=http://localhost:3000",
421
421
  "",
422
- "# Dev-only default; remove in production.",
422
+ "# Dev-only default; remove or protect in production.",
423
423
  "DEVTOOLS_ENABLED=true",
424
424
  "",
425
425
  "LOG_LEVEL=info",
@@ -428,7 +428,8 @@ export function envExample(ctx: TemplateContext): string {
428
428
  "",
429
429
  ...databaseLines,
430
430
  "",
431
- "BETTER_AUTH_SECRET=local-dev-better-auth-secret-change-me",
431
+ "# Optional for local development; required in production.",
432
+ "# BETTER_AUTH_SECRET=replace-with-a-random-32-character-secret",
432
433
  "BETTER_AUTH_URL=http://localhost:3000",
433
434
  "# BETTER_AUTH_TRUSTED_ORIGINS=http://localhost:3000",
434
435
  "",
@@ -115,7 +115,7 @@ export const todos = mysqlTable(
115
115
  }),
116
116
  );
117
117
  `,
118
- drizzleTodoRepository: `import type { beignetServerOnly } from "@beignet/core/server-only";
118
+ drizzleTodoRepository: `import "@beignet/core/server-only";
119
119
  import { offsetPageResult } from "@beignet/core/pagination";
120
120
  import type { DrizzleMysqlDatabase } from "@beignet/provider-db-drizzle/mysql";
121
121
  import { count, desc, eq } from "drizzle-orm";
@@ -255,7 +255,7 @@ async function prepare(pool: Pool): Promise<void> {
255
255
  await migrate(drizzle(pool), { migrationsFolder: "drizzle" });
256
256
  }
257
257
  `,
258
- dbProvider: `import type { beignetServerOnly } from "@beignet/core/server-only";
258
+ dbProvider: `import "@beignet/core/server-only";
259
259
  import { createProvider } from "@beignet/core/providers";
260
260
  import {
261
261
  createDrizzleMysqlIdempotencyPort,
@@ -105,7 +105,7 @@ export const todos = pgTable(
105
105
  }),
106
106
  );
107
107
  `,
108
- drizzleTodoRepository: `import type { beignetServerOnly } from "@beignet/core/server-only";
108
+ drizzleTodoRepository: `import "@beignet/core/server-only";
109
109
  import { offsetPageResult } from "@beignet/core/pagination";
110
110
  import type { DrizzlePostgresDatabase } from "@beignet/provider-db-drizzle/postgres";
111
111
  import { count, desc, eq } from "drizzle-orm";
@@ -243,7 +243,7 @@ async function prepare(pool: Pool): Promise<void> {
243
243
  await migrate(drizzle(pool), { migrationsFolder: "drizzle" });
244
244
  }
245
245
  `,
246
- dbProvider: `import type { beignetServerOnly } from "@beignet/core/server-only";
246
+ dbProvider: `import "@beignet/core/server-only";
247
247
  import { createProvider } from "@beignet/core/providers";
248
248
  import {
249
249
  createDrizzlePostgresIdempotencyPort,
@@ -101,7 +101,7 @@ export const todos = sqliteTable(
101
101
  }),
102
102
  );
103
103
  `,
104
- drizzleTodoRepository: `import type { beignetServerOnly } from "@beignet/core/server-only";
104
+ drizzleTodoRepository: `import "@beignet/core/server-only";
105
105
  import { offsetPageResult } from "@beignet/core/pagination";
106
106
  import type { DrizzleSqliteDatabase } from "@beignet/provider-db-drizzle/sqlite";
107
107
  import { count, desc, eq } from "drizzle-orm";
@@ -242,7 +242,7 @@ async function prepare(client: Client): Promise<void> {
242
242
  await migrate(drizzle(client), { migrationsFolder: "drizzle" });
243
243
  }
244
244
  `,
245
- dbProvider: `import type { beignetServerOnly } from "@beignet/core/server-only";
245
+ dbProvider: `import "@beignet/core/server-only";
246
246
  import { createProvider } from "@beignet/core/providers";
247
247
  import {
248
248
  createDrizzleSqliteIdempotencyPort,
@@ -132,6 +132,7 @@ export function getTemplateFiles(ctx: TemplateContext): TemplateFile[] {
132
132
  { path: "lib/env.ts", content: env(ctx) },
133
133
  { path: "lib/auth.ts", content: serverFiles.authHelpers },
134
134
  { path: "lib/better-auth.ts", content: betterAuth(ctx) },
135
+ { path: "lib/tenant.ts", content: serverFiles.tenantHelper },
135
136
  { path: "lib/use-case.ts", content: serverFiles.useCaseBuilder },
136
137
  { path: "server/index.ts", content: server(ctx) },
137
138
  { path: "server/context.ts", content: serverFiles.serverContext },
@@ -8,7 +8,7 @@ import {
8
8
  export function serverProviders(ctx: TemplateContext): string {
9
9
  const db = databaseDescriptor(ctx);
10
10
  const imports = [
11
- 'import type { beignetServerOnly } from "@beignet/core/server-only";',
11
+ 'import "@beignet/core/server-only";',
12
12
  'import { createDevtoolsProvider } from "@beignet/devtools";',
13
13
  'import { createAuthBetterAuthProvider } from "@beignet/provider-auth-better-auth";',
14
14
  `import { ${db.providerFactory} } from "@beignet/provider-db-drizzle/${db.subpath}";`,
@@ -155,6 +155,19 @@ export function env(ctx: TemplateContext): string {
155
155
  import { z } from "zod";
156
156
 
157
157
  const BooleanEnv = z.enum(["true", "false"]).transform((value) => value === "true");
158
+ const LOCAL_BETTER_AUTH_SECRET = "local-dev-better-auth-secret-change-me";
159
+ const isProductionRuntime =
160
+ process.env.NODE_ENV === "production" &&
161
+ process.env.NEXT_PHASE !== "phase-production-build";
162
+ const BetterAuthSecret = z.string().min(32).superRefine((value, ctx) => {
163
+ if (isProductionRuntime && value === LOCAL_BETTER_AUTH_SECRET) {
164
+ ctx.addIssue({
165
+ code: "custom",
166
+ message:
167
+ "BETTER_AUTH_SECRET must be unique in production. Generate a strong secret instead of using the local development placeholder.",
168
+ });
169
+ }
170
+ });
158
171
 
159
172
  export const env = createEnv({
160
173
  server: {
@@ -163,10 +176,9 @@ export const env = createEnv({
163
176
  .default("development"),
164
177
  APP_URL: z.string().url().default("http://localhost:3000"),
165
178
  DEVTOOLS_ENABLED: BooleanEnv.optional(),
166
- BETTER_AUTH_SECRET: z
167
- .string()
168
- .min(32)
169
- .default("local-dev-better-auth-secret-change-me"),
179
+ BETTER_AUTH_SECRET: isProductionRuntime
180
+ ? BetterAuthSecret
181
+ : BetterAuthSecret.default(LOCAL_BETTER_AUTH_SECRET),
170
182
  BETTER_AUTH_URL: z.string().url().default("http://localhost:3000"),
171
183
  BETTER_AUTH_TRUSTED_ORIGINS: z.string().optional(),
172
184
  ${databaseEnvLines}
@@ -283,7 +295,7 @@ export function server(ctx: TemplateContext): string {
283
295
  \t\t\tDB_URL: env.${db.urlEnvVar},
284
296
  \t\t},`;
285
297
 
286
- return `import type { beignetServerOnly } from "@beignet/core/server-only";
298
+ return `import "@beignet/core/server-only";
287
299
  import { createNextServer } from "@beignet/next";
288
300
  import { createErrorReportingHooks, createIdempotencyHooks } from "@beignet/core/server";
289
301
  import type { AppContext } from "@/app-context";
@@ -369,7 +381,7 @@ export const errors = defineErrors({
369
381
 
370
382
  export const appError = createAppError(errors);
371
383
  `,
372
- useCaseBuilder: `import type { beignetServerOnly } from "@beignet/core/server-only";
384
+ useCaseBuilder: `import "@beignet/core/server-only";
373
385
  import { createUseCase } from "@beignet/core/application";
374
386
  import type { AppContext } from "@/app-context";
375
387
 
@@ -403,10 +415,14 @@ export type AuthUser = {
403
415
  id: string;
404
416
  email?: string;
405
417
  name?: string;
418
+ tenantId?: string;
419
+ organizationId?: string;
406
420
  };
407
421
 
408
422
  export type AuthSessionMetadata = {
409
423
  id?: string;
424
+ tenantId?: string;
425
+ organizationId?: string;
410
426
  };
411
427
 
412
428
  export type AuthSession = BeignetAuthSession<
@@ -420,7 +436,7 @@ export type AuthPort = BeignetAuthPort<
420
436
  AuthRequest
421
437
  >;
422
438
  `,
423
- serverRoutes: `import type { beignetServerOnly } from "@beignet/core/server-only";
439
+ serverRoutes: `import "@beignet/core/server-only";
424
440
  import { contractsFromRoutes, defineRoutes } from "@beignet/next";
425
441
  import type { AppContext } from "@/app-context";
426
442
  import { todoRoutes } from "@/features/todos/routes";
@@ -430,17 +446,17 @@ export const routes = defineRoutes<AppContext>([
430
446
  ]);
431
447
  export const contracts = contractsFromRoutes(routes);
432
448
  `,
433
- serverContext: `import type { beignetServerOnly } from "@beignet/core/server-only";
449
+ serverContext: `import "@beignet/core/server-only";
434
450
  import {
435
451
  type ActivityActor,
436
452
  createAnonymousActor,
437
453
  createServiceActor,
438
- createTenant,
439
454
  createUserActor,
440
455
  } from "@beignet/core/ports";
441
456
  import { defineServerContext } from "@beignet/core/server";
442
457
  import type { TraceContext } from "@beignet/core/tracing";
443
458
  import type { AppContext, AppRuntimePorts } from "@/app-context";
459
+ import { resolveRequestTenant, resolveServiceTenant } from "@/lib/tenant";
444
460
 
445
461
  export type AppServiceContextInput =
446
462
  | {
@@ -456,7 +472,7 @@ export const appContext = defineServerContext<AppContext, AppRuntimePorts>()({
456
472
  gate: (ports) => ports.gate,
457
473
  request: async ({ req, ports, requestId, trace }) => {
458
474
  const auth = await ports.auth.getSession(req);
459
- const tenantId = req.headers.get("x-tenant-id") || undefined;
475
+ const tenant = resolveRequestTenant({ auth });
460
476
 
461
477
  return {
462
478
  requestId,
@@ -466,7 +482,7 @@ export const appContext = defineServerContext<AppContext, AppRuntimePorts>()({
466
482
  auth,
467
483
  ...trace,
468
484
  ports,
469
- tenant: tenantId ? createTenant(tenantId) : undefined,
485
+ ...(tenant ? { tenant } : {}),
470
486
  };
471
487
  },
472
488
  service: ({
@@ -479,15 +495,67 @@ export const appContext = defineServerContext<AppContext, AppRuntimePorts>()({
479
495
  input: AppServiceContextInput;
480
496
  requestId: string;
481
497
  trace: TraceContext;
482
- }) => ({
483
- requestId,
484
- actor: input?.actor ?? createServiceActor("beignet-service"),
485
- auth: null,
486
- ...trace,
487
- ports,
488
- tenant: createTenant(input?.tenantId ?? "tenant_default"),
489
- }),
498
+ }) => {
499
+ const tenant = resolveServiceTenant(input?.tenantId);
500
+
501
+ return {
502
+ requestId,
503
+ actor: input?.actor ?? createServiceActor("beignet-service"),
504
+ auth: null,
505
+ ...trace,
506
+ ports,
507
+ ...(tenant ? { tenant } : {}),
508
+ };
509
+ },
490
510
  });
511
+ `,
512
+ tenantHelper: `import { type ActivityTenant, createTenant } from "@beignet/core/ports";
513
+ import type { AuthSession } from "@/ports/auth";
514
+
515
+ export type TenantResolutionInput = {
516
+ auth: AuthSession | null;
517
+ };
518
+
519
+ export function resolveRequestTenant({
520
+ auth,
521
+ }: TenantResolutionInput): ActivityTenant | undefined {
522
+ const tenantId = auth ? tenantIdFromAuth(auth) : undefined;
523
+
524
+ return tenantId ? createTenant(tenantId) : undefined;
525
+ }
526
+
527
+ export function resolveServiceTenant(
528
+ tenantId: string | undefined,
529
+ ): ActivityTenant | undefined {
530
+ const normalizedTenantId = normalizeTenantId(tenantId);
531
+
532
+ return normalizedTenantId ? createTenant(normalizedTenantId) : undefined;
533
+ }
534
+
535
+ function tenantIdFromAuth(auth: AuthSession) {
536
+ return (
537
+ stringProperty(auth.session, "tenantId") ??
538
+ stringProperty(auth.session, "organizationId") ??
539
+ stringProperty(auth.user, "tenantId") ??
540
+ stringProperty(auth.user, "organizationId")
541
+ );
542
+ }
543
+
544
+ function stringProperty(value: unknown, key: string) {
545
+ if (!isRecord(value)) return undefined;
546
+
547
+ return normalizeTenantId(value[key]);
548
+ }
549
+
550
+ function normalizeTenantId(value: unknown) {
551
+ return typeof value === "string" && value.trim().length > 0
552
+ ? value.trim()
553
+ : undefined;
554
+ }
555
+
556
+ function isRecord(value: unknown): value is Record<string, unknown> {
557
+ return typeof value === "object" && value !== null;
558
+ }
491
559
  `,
492
560
  apiCatchAllRoute: `import { server } from "@/server";
493
561
 
@@ -553,11 +621,13 @@ export const { GET, POST } = createDevtoolsRoute(server.ports.devtools, {
553
621
  });
554
622
  `,
555
623
  openApiRoute: `import { createOpenAPIHandler } from "@beignet/next";
624
+ import { env } from "@/lib/env";
556
625
  import { server } from "@/server";
557
626
 
558
627
  export const GET = createOpenAPIHandler(server.contracts, {
559
628
  title: "Beignet starter API",
560
629
  version: "0.1.0",
630
+ servers: [{ url: env.APP_URL }],
561
631
  });
562
632
  `,
563
633
  authRoute: `import { toNextJsHandler } from "better-auth/next-js";
@@ -174,7 +174,7 @@ export const todoPolicy = definePolicy({
174
174
  authorizeOwner(ctx, todo, "delete"),
175
175
  });
176
176
  `,
177
- routes: `import type { beignetServerOnly } from "@beignet/core/server-only";
177
+ routes: `import "@beignet/core/server-only";
178
178
  import { defineRouteGroup } from "@beignet/next";
179
179
  import type { AppContext } from "@/app-context";
180
180
  import {
@@ -200,7 +200,7 @@ export const todoRoutes = defineRouteGroup<AppContext>()({
200
200
  ],
201
201
  });
202
202
  `,
203
- listTodosUseCase: `import type { beignetServerOnly } from "@beignet/core/server-only";
203
+ listTodosUseCase: `import "@beignet/core/server-only";
204
204
  import { normalizeOffsetPage } from "@beignet/core/pagination";
205
205
  import { requireUser } from "@/lib/auth";
206
206
  import { useCase } from "@/lib/use-case";
@@ -220,7 +220,7 @@ export const listTodosUseCase = useCase
220
220
  return ctx.ports.todos.list(user.id, page);
221
221
  });
222
222
  `,
223
- createTodoUseCase: `import type { beignetServerOnly } from "@beignet/core/server-only";
223
+ createTodoUseCase: `import "@beignet/core/server-only";
224
224
  import { requireUser } from "@/lib/auth";
225
225
  import { useCase } from "@/lib/use-case";
226
226
  import { CreateTodoInputSchema, TodoSchema } from "../schemas";
@@ -238,7 +238,7 @@ export const createTodoUseCase = useCase
238
238
  );
239
239
  });
240
240
  `,
241
- updateTodoUseCase: `import type { beignetServerOnly } from "@beignet/core/server-only";
241
+ updateTodoUseCase: `import "@beignet/core/server-only";
242
242
  import { appError } from "@/features/shared/errors";
243
243
  import { requireUser } from "@/lib/auth";
244
244
  import { useCase } from "@/lib/use-case";
@@ -263,7 +263,7 @@ export const updateTodoUseCase = useCase
263
263
  });
264
264
  });
265
265
  `,
266
- deleteTodoUseCase: `import type { beignetServerOnly } from "@beignet/core/server-only";
266
+ deleteTodoUseCase: `import "@beignet/core/server-only";
267
267
  import { appError } from "@/features/shared/errors";
268
268
  import { requireUser } from "@/lib/auth";
269
269
  import { useCase } from "@/lib/use-case";