@yimingliao/cms 0.0.21 → 0.0.23

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.
@@ -4,6 +4,8 @@ import { cookies } from 'next/headers';
4
4
  import Keyv from 'keyv';
5
5
  import { Logger } from 'logry';
6
6
  import { e as AdminRole, v as SingleItem, B as BaseTranslation, a as Admin, c as AdminFull, f as AdminSafe, D as DeviceInfo, d as AdminRefreshToken, k as File, m as FileFull, o as FileType, p as Folder, F as FolderFull, u as PostType, M as MultiItems, E as ExternalLink, j as Faq, T as TocItem, q as Post, s as PostListCard, t as PostTranslation, r as PostFull, S as SeoMetadata, g as AdminTranslation, n as FileTranslation, h as Alternate } from '../base-DbGnfZr6.js';
7
+ import { BaseTranslator, LocaleMessages } from 'intor';
8
+ import { S as SuccessResult, R as Result, E as ErrorDetail } from '../types-DHlRoJwv.js';
7
9
 
8
10
  interface CreateJwtServiceOptions {
9
11
  defaultSecret: string;
@@ -596,4 +598,37 @@ declare const POST_ORDER_BY: ({
596
598
  index: "asc";
597
599
  })[];
598
600
 
599
- export { ADMIN_ORDER_BY, ORDER_BY, POST_ORDER_BY, type RawCacheKey, createAdminCommandRepository, createAdminQueryRepository, createAdminRefreshTokenCommandRepository, createAdminRefreshTokenQueryRepository, createArgon2Service, createCache, createCacheResult, createCookieService, createCryptoService, createFileCommandRepository, createFileQueryRepository, createFolderCommandRepository, createFolderQueryRepository, createIpRateLimiter, createJwtService, createPostCommandRepository, createPostQueryRepository, createSeoMetadataCommandRepository, normalizeCacheKey };
601
+ type Action<D> = (translator: BaseTranslator<LocaleMessages>) => Promise<Omit<SuccessResult<D>, "success"> & {
602
+ i18nKey?: string;
603
+ }>;
604
+ interface CreateServerActionOptions {
605
+ initI18n: () => Promise<BaseTranslator<LocaleMessages>>;
606
+ cacheResult: <T>({ key, ttl, load }: CacheResultOptions<T>) => Promise<T>;
607
+ cache: Keyv<unknown>;
608
+ logger: Logger;
609
+ }
610
+ interface ServerActionOptions {
611
+ type?: "command" | "query";
612
+ key?: RawCacheKey;
613
+ ttl?: number;
614
+ }
615
+ declare function createExecuteAction({ initI18n, cacheResult, cache, logger, }: CreateServerActionOptions): <D = void>(fn: Action<D>, options?: ServerActionOptions) => Promise<Result<D>>;
616
+
617
+ declare const normalizeError: (error: unknown, translator: BaseTranslator<LocaleMessages>) => {
618
+ message: string;
619
+ errors?: ErrorDetail[];
620
+ statusCode: number;
621
+ isInternal?: boolean;
622
+ };
623
+
624
+ declare class ServerError extends Error {
625
+ readonly i18nKey?: string;
626
+ readonly statusCode?: number;
627
+ constructor({ message, i18nKey, statusCode, }: {
628
+ message?: string;
629
+ i18nKey?: string;
630
+ statusCode?: number;
631
+ });
632
+ }
633
+
634
+ export { ADMIN_ORDER_BY, ORDER_BY, POST_ORDER_BY, type RawCacheKey, ServerError, createAdminCommandRepository, createAdminQueryRepository, createAdminRefreshTokenCommandRepository, createAdminRefreshTokenQueryRepository, createArgon2Service, createCache, createCacheResult, createCookieService, createCryptoService, createExecuteAction, createFileCommandRepository, createFileQueryRepository, createFolderCommandRepository, createFolderQueryRepository, createIpRateLimiter, createJwtService, createPostCommandRepository, createPostQueryRepository, createSeoMetadataCommandRepository, normalizeCacheKey, normalizeError };
@@ -1,5 +1,5 @@
1
1
  import { ADMIN_ROLES, ROOT_FOLDER_ID } from '../chunk-ZCOYQ5BG.js';
2
- import { mimeToExtension, classifyFileType } from '../chunk-YX7IPIGU.js';
2
+ import { result, mimeToExtension, classifyFileType } from '../chunk-YX7IPIGU.js';
3
3
  import jwt from 'jsonwebtoken';
4
4
  import argon2 from 'argon2';
5
5
  import crypto, { timingSafeEqual } from 'crypto';
@@ -7,6 +7,7 @@ import { headers } from 'next/headers';
7
7
  import KeyvRedis from '@keyv/redis';
8
8
  import Keyv from 'keyv';
9
9
  import { ulid } from 'ulid';
10
+ import { ZodError } from 'zod';
10
11
 
11
12
  function createJwtService({
12
13
  defaultSecret,
@@ -1421,4 +1422,84 @@ function createSeoMetadataCommandRepository(prisma) {
1421
1422
  };
1422
1423
  }
1423
1424
 
1424
- export { ADMIN_ORDER_BY, ORDER_BY, POST_ORDER_BY, createAdminCommandRepository, createAdminQueryRepository, createAdminRefreshTokenCommandRepository, createAdminRefreshTokenQueryRepository, createArgon2Service, createCache, createCacheResult, createCookieService, createCryptoService, createFileCommandRepository, createFileQueryRepository, createFolderCommandRepository, createFolderQueryRepository, createIpRateLimiter, createJwtService, createPostCommandRepository, createPostQueryRepository, createSeoMetadataCommandRepository, normalizeCacheKey };
1425
+ // src/server/server-error.ts
1426
+ var ServerError = class extends Error {
1427
+ i18nKey;
1428
+ statusCode;
1429
+ constructor({
1430
+ message,
1431
+ i18nKey,
1432
+ statusCode
1433
+ }) {
1434
+ super(message);
1435
+ this.name = this.constructor.name;
1436
+ if (i18nKey) this.i18nKey = i18nKey;
1437
+ if (statusCode) this.statusCode = statusCode;
1438
+ }
1439
+ };
1440
+
1441
+ // src/server/interfaces/execute-action/normalize-error.ts
1442
+ var normalizeError = (error, translator) => {
1443
+ if (error instanceof ZodError) {
1444
+ const errors = error.issues.map((issue) => {
1445
+ let message = issue.message;
1446
+ if (issue.code === "custom" && issue.params?.["i18nKey"]) {
1447
+ message = translator.t(issue.params["i18nKey"]);
1448
+ }
1449
+ return {
1450
+ field: issue.path.join("."),
1451
+ // e.path: string[] e.g. ["name", "email"]
1452
+ message,
1453
+ code: issue.code
1454
+ };
1455
+ });
1456
+ return { message: "Validation faild", errors, statusCode: 422 };
1457
+ }
1458
+ if (error instanceof ServerError) {
1459
+ const message = translator.t(
1460
+ error.i18nKey ?? "error.internal-server-error"
1461
+ );
1462
+ return { message, statusCode: error.statusCode ?? 500 };
1463
+ }
1464
+ return {
1465
+ message: error instanceof Error ? error.message : JSON.stringify(error),
1466
+ statusCode: 500,
1467
+ isInternal: true
1468
+ };
1469
+ };
1470
+
1471
+ // src/server/interfaces/execute-action/create-execute-action.ts
1472
+ function createExecuteAction({
1473
+ initI18n,
1474
+ cacheResult,
1475
+ cache,
1476
+ logger
1477
+ }) {
1478
+ return async function executeAction(fn, options = {}) {
1479
+ const translator = await initI18n();
1480
+ const withCache = options.key && options.type === "query";
1481
+ try {
1482
+ const { data, i18nKey, message, meta } = withCache ? await cacheResult({
1483
+ key: options.key,
1484
+ ...options.ttl ? { ttl: options.ttl } : {},
1485
+ load: async () => fn(translator)
1486
+ }) : await fn(translator);
1487
+ if (options.type === "command") cache.clear();
1488
+ const finalMessage = i18nKey ? translator.t(i18nKey) : message;
1489
+ return result.success({
1490
+ ...finalMessage ? { message: finalMessage } : {},
1491
+ ...data ? { data: data ?? {} } : {},
1492
+ ...meta ? { meta } : {}
1493
+ });
1494
+ } catch (error) {
1495
+ const { message, errors, isInternal } = normalizeError(error, translator);
1496
+ logger.error({ message, errors });
1497
+ return result.error({
1498
+ message: isInternal ? "Internal server error" : message,
1499
+ ...errors !== void 0 ? { errors } : {}
1500
+ });
1501
+ }
1502
+ };
1503
+ }
1504
+
1505
+ export { ADMIN_ORDER_BY, ORDER_BY, POST_ORDER_BY, ServerError, createAdminCommandRepository, createAdminQueryRepository, createAdminRefreshTokenCommandRepository, createAdminRefreshTokenQueryRepository, createArgon2Service, createCache, createCacheResult, createCookieService, createCryptoService, createExecuteAction, createFileCommandRepository, createFileQueryRepository, createFolderCommandRepository, createFolderQueryRepository, createIpRateLimiter, createJwtService, createPostCommandRepository, createPostQueryRepository, createSeoMetadataCommandRepository, normalizeCacheKey, normalizeError };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yimingliao/cms",
3
- "version": "0.0.21",
3
+ "version": "0.0.23",
4
4
  "author": "Yiming Liao",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -56,10 +56,12 @@
56
56
  "@types/mime-types": "^3.0.1",
57
57
  "@types/ssh2-sftp-client": "^9.0.6",
58
58
  "generic-pool": "^3.9.0",
59
+ "intor": "^2.5.0",
59
60
  "next": "^16.1.6",
60
61
  "prisma": "6.5.0",
61
62
  "tsup": "^8.5.1",
62
- "typescript": "^5.9.3"
63
+ "typescript": "^5.9.3",
64
+ "zod": "^4.3.6"
63
65
  },
64
66
  "peerDependencies": {
65
67
  "@aws-sdk/client-s3": "^3.0.0",