@yimingliao/cms 0.0.29 → 0.0.31

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.
@@ -153,7 +153,7 @@ interface TocItem {
153
153
  text: string;
154
154
  id: string;
155
155
  level: 2 | 3 | 4 | 5 | 6;
156
- children?: TocItem[];
156
+ children: TocItem[];
157
157
  }
158
158
 
159
159
  interface Post {
@@ -1,4 +1,4 @@
1
- import { mimeToExtension } from './chunk-YX7IPIGU.js';
1
+ import { mimeToExtension } from './chunk-I2DBI3WJ.js';
2
2
  import path from 'path/posix';
3
3
  import { ulid } from 'ulid';
4
4
 
@@ -185,4 +185,24 @@ var result = {
185
185
  error
186
186
  };
187
187
 
188
- export { FILE_TYPES, classifyFileType, formatFileSize, getMediaInfo, mimeToExtension, result };
188
+ // src/shared/units.ts
189
+ var SIZE = {
190
+ BYTE: 1,
191
+ KB: 1024,
192
+ MB: 1024 ** 2,
193
+ GB: 1024 ** 3,
194
+ TB: 1024 ** 4,
195
+ PB: 1024 ** 5
196
+ };
197
+ var TIME = {
198
+ MILLISECOND: 1,
199
+ SECOND: 1e3,
200
+ MINUTE: 60 * 1e3,
201
+ HOUR: 60 * 60 * 1e3,
202
+ DAY: 24 * 60 * 60 * 1e3,
203
+ WEEK: 7 * 24 * 60 * 60 * 1e3,
204
+ MONTH: 30 * 24 * 60 * 60 * 1e3,
205
+ YEAR: 365 * 24 * 60 * 60 * 1e3
206
+ };
207
+
208
+ export { FILE_TYPES, SIZE, TIME, classifyFileType, formatFileSize, getMediaInfo, mimeToExtension, result };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { F as FolderFull } from './base-DbGnfZr6.js';
2
- export { A as ADMIN_ROLES, a as Admin, b as AdminCard, c as AdminFull, d as AdminRefreshToken, e as AdminRole, f as AdminSafe, g as AdminTranslation, h as Alternate, B as BaseTranslation, D as DeviceInfo, E as ExternalLink, i as FILE_TYPES, j as Faq, k as File, l as FileCard, m as FileFull, n as FileTranslation, o as FileType, p as Folder, M as MultiItems, P as POST_TYPES, q as Post, r as PostFull, s as PostListCard, t as PostTranslation, u as PostType, S as SeoMetadata, v as SingleItem, T as TocItem, w as Translation } from './base-DbGnfZr6.js';
1
+ import { F as FolderFull } from './base-BUAGZ2YH.js';
2
+ export { A as ADMIN_ROLES, a as Admin, b as AdminCard, c as AdminFull, d as AdminRefreshToken, e as AdminRole, f as AdminSafe, g as AdminTranslation, h as Alternate, B as BaseTranslation, D as DeviceInfo, E as ExternalLink, i as FILE_TYPES, j as Faq, k as File, l as FileCard, m as FileFull, n as FileTranslation, o as FileType, p as Folder, M as MultiItems, P as POST_TYPES, q as Post, r as PostFull, s as PostListCard, t as PostTranslation, u as PostType, S as SeoMetadata, v as SingleItem, T as TocItem, w as Translation } from './base-BUAGZ2YH.js';
3
3
  export { B as BlobFile } from './types-0oS1A2K5.js';
4
4
  import { E as ErrorDetail, S as SuccessResult, a as ErrorResult } from './types-DHlRoJwv.js';
5
5
  export { R as Result } from './types-DHlRoJwv.js';
@@ -44,4 +44,25 @@ declare const result: {
44
44
  error: typeof error;
45
45
  };
46
46
 
47
- export { ErrorDetail, ErrorResult, type ErrorResultParams, FolderFull, ROOT_FOLDER, ROOT_FOLDER_ID, ROOT_FOLDER_NAME, SIMPLE_UPLOAD_FOLDER_KEY, SIMPLE_UPLOAD_FOLDER_NAME, SuccessResult, type SuccessResultParams, classifyFileType, formatFileSize, getMediaInfo, mimeToExtension, result };
47
+ declare const SIZE: {
48
+ readonly BYTE: 1;
49
+ readonly KB: 1024;
50
+ readonly MB: number;
51
+ readonly GB: number;
52
+ readonly TB: number;
53
+ readonly PB: number;
54
+ };
55
+ type SizeUnit = keyof typeof SIZE;
56
+ declare const TIME: {
57
+ readonly MILLISECOND: 1;
58
+ readonly SECOND: 1000;
59
+ readonly MINUTE: number;
60
+ readonly HOUR: number;
61
+ readonly DAY: number;
62
+ readonly WEEK: number;
63
+ readonly MONTH: number;
64
+ readonly YEAR: number;
65
+ };
66
+ type TimeUnit = keyof typeof TIME;
67
+
68
+ export { ErrorDetail, ErrorResult, type ErrorResultParams, FolderFull, ROOT_FOLDER, ROOT_FOLDER_ID, ROOT_FOLDER_NAME, SIMPLE_UPLOAD_FOLDER_KEY, SIMPLE_UPLOAD_FOLDER_NAME, SIZE, type SizeUnit, SuccessResult, type SuccessResultParams, TIME, type TimeUnit, classifyFileType, formatFileSize, getMediaInfo, mimeToExtension, result };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
1
  export { ADMIN_ROLES, POST_TYPES, ROOT_FOLDER, ROOT_FOLDER_ID, ROOT_FOLDER_NAME, SIMPLE_UPLOAD_FOLDER_KEY, SIMPLE_UPLOAD_FOLDER_NAME } from './chunk-ZCOYQ5BG.js';
2
- export { FILE_TYPES, classifyFileType, formatFileSize, getMediaInfo, mimeToExtension, result } from './chunk-YX7IPIGU.js';
2
+ export { FILE_TYPES, SIZE, TIME, classifyFileType, formatFileSize, getMediaInfo, mimeToExtension, result } from './chunk-I2DBI3WJ.js';
@@ -3,17 +3,21 @@ import { BinaryLike } from 'node:crypto';
3
3
  import { cookies } from 'next/headers';
4
4
  import Keyv from 'keyv';
5
5
  import { Logger } from 'logry';
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';
6
+ import * as zod from 'zod';
7
+ import zod__default, { z, ZodType } from 'zod';
8
+ import { B as BlobFile } from '../types-0oS1A2K5.js';
9
+ import * as zod_v4_core from 'zod/v4/core';
10
+ import { T as TocItem, 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$1, m as FileFull, o as FileType, p as Folder, F as FolderFull, u as PostType, M as MultiItems, E as ExternalLink, j as Faq, 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-BUAGZ2YH.js';
7
11
  import { BaseTranslator, LocaleMessages } from 'intor';
8
12
  import { S as SuccessResult, R as Result } from '../types-DHlRoJwv.js';
9
13
  import { NextResponse } from 'next/server';
10
14
 
11
- interface CreateJwtServiceOptions {
15
+ interface CreateJwtServiceParams {
12
16
  defaultSecret: string;
13
17
  issuer?: string;
14
18
  audience?: string;
15
19
  }
16
- declare function createJwtService({ defaultSecret, ...options }: CreateJwtServiceOptions): {
20
+ declare function createJwtService({ defaultSecret, ...options }: CreateJwtServiceParams): {
17
21
  sign: ({ payload, secret, expiresIn, }: {
18
22
  payload: object;
19
23
  secret: string;
@@ -30,10 +34,10 @@ declare function createArgon2Service(): {
30
34
  verify: (digest: string, password: string) => Promise<boolean>;
31
35
  };
32
36
 
33
- interface CreateCryptoServiceOptions {
37
+ interface CreateCryptoServiceParams {
34
38
  defaultSecret: string;
35
39
  }
36
- declare function createCryptoService({ defaultSecret, }: CreateCryptoServiceOptions): {
40
+ declare function createCryptoService({ defaultSecret, }: CreateCryptoServiceParams): {
37
41
  generateToken: () => string;
38
42
  hash: (value: BinaryLike) => string;
39
43
  hashBuffer: (value: BinaryLike) => Buffer;
@@ -74,12 +78,12 @@ declare function createCookieService(nextCookies: () => Promise<Awaited<ReturnTy
74
78
  }) => Promise<void>;
75
79
  };
76
80
 
77
- interface CreateServerCacheOptions {
81
+ interface CreateServerCacheParams {
78
82
  redisUrl: string;
79
83
  namespace: string;
80
84
  keyDelimiter?: string;
81
85
  }
82
- declare function createCache({ redisUrl, namespace, keyDelimiter, }: CreateServerCacheOptions): Keyv<unknown>;
86
+ declare function createCache({ redisUrl, namespace, keyDelimiter, }: CreateServerCacheParams): Keyv<unknown>;
83
87
 
84
88
  type RawCacheKey = string | Array<string | number | boolean | undefined | null>;
85
89
  declare const normalizeCacheKey: (key?: RawCacheKey, delimiter?: string) => string | null;
@@ -98,6 +102,92 @@ interface RateLimiterOptions {
98
102
  }
99
103
  declare function createIpRateLimiter(cache: Keyv<unknown>, appName: string): ({ key: rawKey, maxAttempts, timeWindow, }: RateLimiterOptions) => Promise<boolean>;
100
104
 
105
+ type Scope = {
106
+ name: string;
107
+ value: string;
108
+ cast?: string;
109
+ };
110
+ type UniqueOptions = {
111
+ table: string;
112
+ column: string;
113
+ scope?: Scope[];
114
+ excludeSelf?: Scope;
115
+ };
116
+ declare function createUnique(prisma: any): (value: string, options: UniqueOptions) => Promise<boolean>;
117
+
118
+ type ExistOptions = {
119
+ table: string;
120
+ column?: string;
121
+ };
122
+ declare function createExist(prisma: any): (value: string | number, options: ExistOptions) => Promise<boolean>;
123
+
124
+ declare module "zod" {
125
+ interface ZodString {
126
+ unique(options: UniqueOptions): this;
127
+ exist(options: ExistOptions): this;
128
+ bcp47(): this;
129
+ ogLocale(): this;
130
+ }
131
+ interface ZodEmail {
132
+ unique(options: UniqueOptions): this;
133
+ }
134
+ }
135
+ declare function createZod({ unique, exist, }: {
136
+ unique: ReturnType<typeof createUnique>;
137
+ exist: ReturnType<typeof createExist>;
138
+ }): typeof z;
139
+
140
+ declare function createSchemas({ z, localeArray, exist, }: {
141
+ z: ReturnType<typeof createZod>;
142
+ localeArray: string[];
143
+ exist: ReturnType<typeof createExist>;
144
+ }): {
145
+ text: () => zod__default.ZodString;
146
+ positiveNumber: () => zod__default.ZodPipe<zod__default.ZodTransform<number | undefined, unknown>, zod__default.ZodNumber>;
147
+ url: () => zod__default.ZodPipe<zod__default.ZodTransform<{} | null | undefined, unknown>, zod__default.ZodNullable<zod__default.ZodURL>>;
148
+ email: () => zod__default.ZodEmail;
149
+ password: () => zod__default.ZodString;
150
+ isoString: () => zod__default.ZodString;
151
+ array: <T extends ZodType>(schema: T) => zod__default.ZodPipe<zod__default.ZodArray<T>, zod__default.ZodTransform<NonNullable<zod__default.core.output<T>>[], zod__default.core.output<T>[]>>;
152
+ id: () => zod__default.ZodString;
153
+ key: () => zod__default.ZodString;
154
+ sha256Hash: () => zod__default.ZodString;
155
+ slug: () => zod__default.ZodString;
156
+ pathSegment: () => zod__default.ZodString;
157
+ locale: () => zod__default.ZodString;
158
+ singleItem: (options: ExistOptions) => zod__default.ZodNullable<zod__default.ZodObject<{
159
+ id: zod__default.ZodString;
160
+ }, zod__default.core.$strip>>;
161
+ multiItems: (options: ExistOptions) => zod__default.ZodPipe<zod__default.ZodArray<zod__default.ZodObject<{
162
+ id: zod__default.ZodString;
163
+ }, zod__default.core.$strip>>, zod__default.ZodTransform<{
164
+ id: string;
165
+ }[], {
166
+ id: string;
167
+ }[]>>;
168
+ };
169
+
170
+ declare function createFileSchema({ z, maxSizeInMb, }: {
171
+ z: ReturnType<typeof createZod>;
172
+ maxSizeInMb: number;
173
+ }): ({ size, extensions, }: {
174
+ size?: number;
175
+ extensions?: string[];
176
+ }) => zod.ZodPipe<zod.ZodCustom<File, File>, zod.ZodTransform<BlobFile, File>>;
177
+ declare function createMultiFileSchema({ z, fileSchema, maxSizeInMb, }: {
178
+ z: ReturnType<typeof createZod>;
179
+ fileSchema: ReturnType<typeof createFileSchema>;
180
+ maxSizeInMb: number;
181
+ }): ({ size, extensions, }?: {
182
+ size?: number;
183
+ extensions?: string[];
184
+ }) => void;
185
+
186
+ declare function createTocItemSchema({ z, schemas, }: {
187
+ z: ReturnType<typeof createZod>;
188
+ schemas: ReturnType<typeof createSchemas>;
189
+ }): ZodType<TocItem, unknown, zod_v4_core.$ZodTypeInternals<TocItem, unknown>>;
190
+
101
191
  interface CreateParams$4 {
102
192
  email: string;
103
193
  role: AdminRole;
@@ -214,7 +304,7 @@ interface CreateParams$2 {
214
304
  }
215
305
  interface UpdateParams$2 {
216
306
  id: string;
217
- file: File;
307
+ file: File$1;
218
308
  key: string;
219
309
  checksum: string;
220
310
  fileMeta: {
@@ -234,10 +324,10 @@ interface UpdateParams$2 {
234
324
 
235
325
  declare function createFileCommandRepository(prisma: any): {
236
326
  create: ({ fileMeta, folder, translations, ...params }: CreateParams$2) => Promise<FileFull>;
237
- update: ({ file, id, fileMeta, folder, translations, ...params }: UpdateParams$2) => Promise<File>;
327
+ update: ({ file, id, fileMeta, folder, translations, ...params }: UpdateParams$2) => Promise<File$1>;
238
328
  softDelete: ({ id }: {
239
329
  id: string;
240
- }) => Promise<File>;
330
+ }) => Promise<File$1>;
241
331
  softDeleteMany: ({ ids }: {
242
332
  ids: string[];
243
333
  }) => Promise<number>;
@@ -246,7 +336,7 @@ declare function createFileCommandRepository(prisma: any): {
246
336
  }) => Promise<number>;
247
337
  delete: ({ id }: {
248
338
  id: string;
249
- }) => Promise<File>;
339
+ }) => Promise<File$1>;
250
340
  };
251
341
 
252
342
  interface FindListCardsParams$2 {
@@ -530,7 +620,7 @@ declare function createPostQueryRepository(prisma: any): {
530
620
  author: AdminSafe & {
531
621
  translations: AdminTranslation[];
532
622
  };
533
- coverImage: File & {
623
+ coverImage: File$1 & {
534
624
  translations: FileTranslation[];
535
625
  };
536
626
  }) | null>;
@@ -602,25 +692,25 @@ declare const POST_ORDER_BY: ({
602
692
  type Action<D> = (translator: BaseTranslator<LocaleMessages>) => Promise<Omit<SuccessResult<D>, "success"> & {
603
693
  i18nKey?: string;
604
694
  }>;
605
- interface CreateExecuteActionOptions {
695
+ interface CreateExecuteActionParams {
606
696
  initI18n: () => Promise<BaseTranslator<LocaleMessages>>;
607
697
  cacheResult: <T>({ key, ttl, load }: CacheResultOptions<T>) => Promise<T>;
608
698
  cache: Keyv<unknown>;
609
699
  logger: Logger;
610
700
  }
611
- interface ServerActionOptions {
701
+ interface ServerActionParams {
612
702
  type?: "command" | "query";
613
703
  key?: RawCacheKey;
614
704
  ttl?: number;
615
705
  }
616
- declare function createExecuteAction({ initI18n, cacheResult, cache, logger, }: CreateExecuteActionOptions): <D = void>(fn: Action<D>, options?: ServerActionOptions) => Promise<Result<D>>;
706
+ declare function createExecuteAction({ initI18n, cacheResult, cache, logger, }: CreateExecuteActionParams): <D = void>(fn: Action<D>, options?: ServerActionParams) => Promise<Result<D>>;
617
707
 
618
708
  type Api = (translator: BaseTranslator<LocaleMessages>) => Promise<NextResponse<unknown>>;
619
- interface CreateExecuteApiOptions {
709
+ interface CreateExecuteApiParams {
620
710
  initI18n: () => Promise<BaseTranslator<LocaleMessages>>;
621
711
  logger: Logger;
622
712
  }
623
- declare function createExecuteApi({ initI18n, logger, }: CreateExecuteApiOptions): (fn: Api) => Promise<NextResponse<unknown>>;
713
+ declare function createExecuteApi({ initI18n, logger }: CreateExecuteApiParams): (fn: Api) => Promise<NextResponse<unknown>>;
624
714
 
625
715
  interface CreateAuthUseCases {
626
716
  prisma: any;
@@ -682,7 +772,7 @@ declare function createAuthUseCases({ prisma, adminQueryRepository, adminRefresh
682
772
  }) => Promise<AdminSafe>;
683
773
  };
684
774
 
685
- interface CreateVerifyAccessTokenOptions {
775
+ interface CreateVerifyAccessTokenParams {
686
776
  adminQueryRepository: ReturnType<typeof createAdminQueryRepository>;
687
777
  jwtService: ReturnType<typeof createJwtService>;
688
778
  cryptoService: ReturnType<typeof createCryptoService>;
@@ -692,11 +782,11 @@ interface CreateVerifyAccessTokenOptions {
692
782
  accessTokenSecret: string;
693
783
  };
694
784
  }
695
- declare function createVerifyAccessToken({ adminQueryRepository, jwtService, cryptoService, cookieService, config, }: CreateVerifyAccessTokenOptions): () => Promise<{
785
+ declare function createVerifyAccessToken({ adminQueryRepository, jwtService, cryptoService, cookieService, config, }: CreateVerifyAccessTokenParams): () => Promise<{
696
786
  admin: AdminFull;
697
787
  } | null>;
698
788
 
699
- interface CreateVerifyRefreshTokenOptions {
789
+ interface CreateVerifyRefreshTokenParams {
700
790
  adminQueryRepository: ReturnType<typeof createAdminQueryRepository>;
701
791
  adminRefreshTokenQueryRepository: ReturnType<typeof createAdminRefreshTokenQueryRepository>;
702
792
  cryptoService: ReturnType<typeof createCryptoService>;
@@ -705,19 +795,19 @@ interface CreateVerifyRefreshTokenOptions {
705
795
  refreshTokenName: string;
706
796
  };
707
797
  }
708
- declare function createVerifyRefreshToken({ adminQueryRepository, adminRefreshTokenQueryRepository, cryptoService, cookieService, config, }: CreateVerifyRefreshTokenOptions): () => Promise<{
798
+ declare function createVerifyRefreshToken({ adminQueryRepository, adminRefreshTokenQueryRepository, cryptoService, cookieService, config, }: CreateVerifyRefreshTokenParams): () => Promise<{
709
799
  adminRefreshToken: AdminRefreshToken;
710
800
  admin: AdminFull;
711
801
  } | null>;
712
802
 
713
- interface CreateAuthMiddlewareOptions {
803
+ interface CreateAuthMiddlewareParams {
714
804
  adminRefreshTokenCommandRepository: ReturnType<typeof createAdminRefreshTokenCommandRepository>;
715
805
  authUseCases: ReturnType<typeof createAuthUseCases>;
716
806
  verifyAccessToken: ReturnType<typeof createVerifyAccessToken>;
717
807
  verifyRefreshToken: ReturnType<typeof createVerifyRefreshToken>;
718
808
  headers: () => Promise<Headers>;
719
809
  }
720
- declare function createAuthMiddleware({ adminRefreshTokenCommandRepository, authUseCases, verifyAccessToken, verifyRefreshToken, headers, }: CreateAuthMiddlewareOptions): {
810
+ declare function createAuthMiddleware({ adminRefreshTokenCommandRepository, authUseCases, verifyAccessToken, verifyRefreshToken, headers, }: CreateAuthMiddlewareParams): {
721
811
  authenticate(): Promise<AdminFull>;
722
812
  };
723
813
 
@@ -739,4 +829,4 @@ declare class ServerError extends Error {
739
829
  static internalServerError(): ServerError;
740
830
  }
741
831
 
742
- export { ADMIN_ORDER_BY, ORDER_BY, POST_ORDER_BY, type RawCacheKey, ServerError, createAdminCommandRepository, createAdminQueryRepository, createAdminRefreshTokenCommandRepository, createAdminRefreshTokenQueryRepository, createArgon2Service, createAuthMiddleware, createAuthUseCases, createCache, createCacheResult, createCookieService, createCryptoService, createExecuteAction, createExecuteApi, createFileCommandRepository, createFileQueryRepository, createFolderCommandRepository, createFolderQueryRepository, createIpRateLimiter, createJwtService, createPostCommandRepository, createPostQueryRepository, createSeoMetadataCommandRepository, createVerifyAccessToken, createVerifyRefreshToken, normalizeCacheKey };
832
+ export { ADMIN_ORDER_BY, ORDER_BY, POST_ORDER_BY, type RawCacheKey, ServerError, createAdminCommandRepository, createAdminQueryRepository, createAdminRefreshTokenCommandRepository, createAdminRefreshTokenQueryRepository, createArgon2Service, createAuthMiddleware, createAuthUseCases, createCache, createCacheResult, createCookieService, createCryptoService, createExecuteAction, createExecuteApi, createExist, createFileCommandRepository, createFileQueryRepository, createFileSchema, createFolderCommandRepository, createFolderQueryRepository, createIpRateLimiter, createJwtService, createMultiFileSchema, createPostCommandRepository, createPostQueryRepository, createSchemas, createSeoMetadataCommandRepository, createTocItemSchema, createUnique, createVerifyAccessToken, createVerifyRefreshToken, createZod, normalizeCacheKey };
@@ -1,13 +1,13 @@
1
1
  import { ADMIN_ROLES, ROOT_FOLDER_ID } from '../chunk-ZCOYQ5BG.js';
2
- import { result, mimeToExtension, classifyFileType } from '../chunk-YX7IPIGU.js';
2
+ import { SIZE, result, mimeToExtension, classifyFileType } from '../chunk-I2DBI3WJ.js';
3
3
  import jwt from 'jsonwebtoken';
4
4
  import argon2 from 'argon2';
5
5
  import crypto, { timingSafeEqual } from 'crypto';
6
6
  import { headers } from 'next/headers';
7
7
  import KeyvRedis from '@keyv/redis';
8
8
  import Keyv from 'keyv';
9
+ import { z, ZodError } from 'zod';
9
10
  import { ulid } from 'ulid';
10
- import { ZodError } from 'zod';
11
11
  import { NextResponse } from 'next/server';
12
12
 
13
13
  function createJwtService({
@@ -310,6 +310,300 @@ function createIpRateLimiter(cache, appName) {
310
310
  };
311
311
  }
312
312
 
313
+ // src/server/infrastructure/zod/rules/unique.ts
314
+ function createUnique(prisma) {
315
+ return async function unique(value, options) {
316
+ if (!value) return true;
317
+ let query = `
318
+ SELECT COUNT(*) AS count
319
+ FROM ${options.table}
320
+ WHERE ${options.column} = $1
321
+ `;
322
+ const params = [value];
323
+ const appendCondition = (op, sc) => {
324
+ const paramIndex = params.length + 1;
325
+ const cast = sc.cast ? `::"${sc.cast}"` : "";
326
+ query += ` AND ${sc.name} ${op} $${paramIndex}${cast}`;
327
+ params.push(sc.value);
328
+ };
329
+ if (options.scope) {
330
+ options.scope.forEach((sc) => appendCondition("=", sc));
331
+ }
332
+ if (options.excludeSelf) {
333
+ appendCondition("!=", options.excludeSelf);
334
+ }
335
+ try {
336
+ const result2 = await prisma.$queryRawUnsafe(
337
+ query,
338
+ ...params
339
+ );
340
+ return Number(result2[0]?.count || 0) === 0;
341
+ } catch (error) {
342
+ console.error("Unique check failed:", error);
343
+ return false;
344
+ }
345
+ };
346
+ }
347
+
348
+ // src/server/infrastructure/zod/rules/exist.ts
349
+ function createExist(prisma) {
350
+ return async function exist(value, options) {
351
+ if (!value) return false;
352
+ const column = options.column || "id";
353
+ const query = `
354
+ SELECT COUNT(*) AS count
355
+ FROM ${options.table}
356
+ WHERE ${column} = $1
357
+ `;
358
+ try {
359
+ const result2 = await prisma.$queryRawUnsafe(
360
+ query,
361
+ value
362
+ );
363
+ const count = Number(result2[0]?.count || 0);
364
+ return count > 0;
365
+ } catch (error) {
366
+ console.error("Exist check failed:", error);
367
+ return false;
368
+ }
369
+ };
370
+ }
371
+
372
+ // src/server/infrastructure/zod/rules/bcp47.ts
373
+ function bcp47(locale) {
374
+ if (typeof locale !== "string") return false;
375
+ const BCP47_REGEX = new RegExp(
376
+ "^[a-zA-Z]{2,3}(?:-[A-Z][a-z]{3})?" + // optional region
377
+ String.raw`(?:-(?:[A-Z]{2}|\d{3}))?` + // optional variants
378
+ String.raw`(?:-(?:[a-zA-Z0-9]{5,8}|\d[a-zA-Z0-9]{3}))*` + // optional extensions
379
+ "(?:-(?:[0-9A-WY-Za-wy-z]-[a-zA-Z0-9]{2,8}(?:-[a-zA-Z0-9]{2,8})*))*(?:-x(?:-[a-zA-Z0-9]{1,8})+)?$"
380
+ );
381
+ return BCP47_REGEX.test(locale);
382
+ }
383
+
384
+ // src/server/infrastructure/zod/rules/og-locale.ts
385
+ function ogLocale(locale) {
386
+ if (typeof locale !== "string") return false;
387
+ const OG_LOCALE_REGEX = /^[a-z]{2}_[A-Z]{2}$/;
388
+ return OG_LOCALE_REGEX.test(locale);
389
+ }
390
+
391
+ // src/server/infrastructure/zod/create-zod.ts
392
+ var patched = false;
393
+ function createZod({
394
+ unique,
395
+ exist
396
+ }) {
397
+ if (patched) return z;
398
+ patched = true;
399
+ const stringProto = z.ZodString.prototype;
400
+ const emailProto = z.ZodEmail.prototype;
401
+ Object.defineProperty(stringProto, "unique", {
402
+ configurable: true,
403
+ writable: false,
404
+ value: function(options) {
405
+ return this.refine(async (v) => unique(v, options), {
406
+ params: { i18nKey: "validator.unique" }
407
+ });
408
+ }
409
+ });
410
+ Object.defineProperty(stringProto, "exist", {
411
+ configurable: true,
412
+ writable: false,
413
+ value: function(options) {
414
+ return this.refine(async (v) => exist(v, options), {
415
+ params: { i18nKey: "validator.exist" }
416
+ });
417
+ }
418
+ });
419
+ Object.defineProperty(stringProto, "bcp47", {
420
+ configurable: true,
421
+ writable: false,
422
+ value: function() {
423
+ return this.refine((v) => bcp47(v), {
424
+ params: { i18nKey: "validator.bcp47" }
425
+ });
426
+ }
427
+ });
428
+ Object.defineProperty(stringProto, "ogLocale", {
429
+ configurable: true,
430
+ writable: false,
431
+ value: function() {
432
+ return this.refine((v) => ogLocale(v), {
433
+ params: { i18nKey: "validator.og-locale" }
434
+ });
435
+ }
436
+ });
437
+ Object.defineProperty(emailProto, "unique", {
438
+ configurable: true,
439
+ writable: false,
440
+ value: function(options) {
441
+ return this.refine(async (v) => unique(v, options), {
442
+ params: { i18nKey: "validator.unique" }
443
+ });
444
+ }
445
+ });
446
+ return z;
447
+ }
448
+
449
+ // src/server/infrastructure/zod/schemas/schemas.ts
450
+ function createSchemas({
451
+ z: z2,
452
+ localeArray,
453
+ exist
454
+ }) {
455
+ const trimmedString = () => z2.string().trim();
456
+ const MAX_NUMBER = 2147483647;
457
+ const MAX_STRING = 1e5;
458
+ const localeSet = new Set(localeArray);
459
+ function text() {
460
+ return trimmedString().max(MAX_STRING);
461
+ }
462
+ function positiveNumber() {
463
+ return z2.preprocess((val) => {
464
+ if (val == null || val === "") return;
465
+ const num = Number(String(val).trim());
466
+ return Number.isNaN(num) ? void 0 : num;
467
+ }, z2.number().min(0).max(MAX_NUMBER));
468
+ }
469
+ function url() {
470
+ return z2.preprocess((val) => {
471
+ if (typeof val === "string" && val.trim() === "" || val === null)
472
+ return null;
473
+ return val;
474
+ }, z2.url().max(2048).nullable());
475
+ }
476
+ function email() {
477
+ return z2.email().max(254).toLowerCase();
478
+ }
479
+ function password() {
480
+ return trimmedString().min(6).max(255);
481
+ }
482
+ function isoString() {
483
+ return trimmedString().regex(
484
+ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/
485
+ );
486
+ }
487
+ function array(schema) {
488
+ return z2.array(schema).max(100).transform(
489
+ (arr) => arr.filter((v) => v != null)
490
+ );
491
+ }
492
+ function id() {
493
+ return trimmedString().length(26).regex(/^[0-9A-Z]{26}$/);
494
+ }
495
+ function key() {
496
+ return trimmedString().max(1024);
497
+ }
498
+ function sha256Hash() {
499
+ return trimmedString().length(64).regex(/^[a-f0-9]{64}$/);
500
+ }
501
+ function slug() {
502
+ return trimmedString().regex(/^$|^[\p{L}0-9-_]+$/u).max(100);
503
+ }
504
+ function pathSegment() {
505
+ return trimmedString().min(1).regex(/^(?!\.\.?$)[^\u0000-\u001F/\\]+$/u).max(255);
506
+ }
507
+ function locale() {
508
+ return trimmedString().refine((val) => localeSet.has(val), {
509
+ error: "Invalid locale"
510
+ });
511
+ }
512
+ function singleItem(options) {
513
+ return z2.object({
514
+ id: id().refine((v) => exist(v, options), {
515
+ error: "Resource does not exist"
516
+ })
517
+ }).nullable();
518
+ }
519
+ function multiItems(options) {
520
+ return array(
521
+ z2.object({
522
+ id: id().refine((v) => exist(v, options), {
523
+ error: "Resource does not exist"
524
+ })
525
+ })
526
+ );
527
+ }
528
+ return {
529
+ // base
530
+ text,
531
+ positiveNumber,
532
+ url,
533
+ email,
534
+ password,
535
+ isoString,
536
+ array,
537
+ // resource related
538
+ id,
539
+ key,
540
+ sha256Hash,
541
+ slug,
542
+ pathSegment,
543
+ locale,
544
+ // item
545
+ singleItem,
546
+ multiItems
547
+ };
548
+ }
549
+
550
+ // src/server/infrastructure/zod/schemas/file.ts
551
+ function createFileSchema({
552
+ z: z2,
553
+ maxSizeInMb
554
+ }) {
555
+ return function fileSchema({
556
+ size = maxSizeInMb * SIZE.MB,
557
+ extensions = []
558
+ }) {
559
+ return z2.instanceof(File, { error: "Invalid file" }).refine((file) => file.size <= size, {
560
+ error: `File is too large, max ${size / SIZE.MB}MB`
561
+ }).refine(
562
+ (file) => {
563
+ if (extensions.length === 0) return true;
564
+ return extensions.some(
565
+ (ext) => file.name.toLocaleLowerCase().endsWith(ext)
566
+ );
567
+ },
568
+ { error: `Only ${extensions.join(", ")} files are allowed` }
569
+ ).transform((file) => file);
570
+ };
571
+ }
572
+ function createMultiFileSchema({
573
+ z: z2,
574
+ fileSchema,
575
+ maxSizeInMb
576
+ }) {
577
+ return function multiFilesSchema({
578
+ size = maxSizeInMb * SIZE.MB,
579
+ extensions = []
580
+ } = {}) {
581
+ z2.array(fileSchema({ size, extensions }));
582
+ };
583
+ }
584
+
585
+ // src/server/infrastructure/zod/schemas/toc-item.ts
586
+ function createTocItemSchema({
587
+ z: z2,
588
+ schemas
589
+ }) {
590
+ const tocItem = z2.lazy(
591
+ () => z2.object({
592
+ text: schemas.text(),
593
+ id: schemas.text(),
594
+ level: z2.union([
595
+ z2.literal(2),
596
+ z2.literal(3),
597
+ z2.literal(4),
598
+ z2.literal(5),
599
+ z2.literal(6)
600
+ ]),
601
+ children: z2.array(tocItem).default([])
602
+ })
603
+ );
604
+ return tocItem;
605
+ }
606
+
313
607
  // src/server/infrastructure/database/utils/connect.ts
314
608
  var ids = (items) => items.map(({ id }) => ({ id }));
315
609
  function connectOne(item) {
@@ -1521,10 +1815,7 @@ function createExecuteAction({
1521
1815
  }
1522
1816
  };
1523
1817
  }
1524
- function createExecuteApi({
1525
- initI18n,
1526
- logger
1527
- }) {
1818
+ function createExecuteApi({ initI18n, logger }) {
1528
1819
  return async function serverApi(fn) {
1529
1820
  const translator = await initI18n();
1530
1821
  try {
@@ -1753,4 +2044,4 @@ function createAuthUseCases({
1753
2044
  };
1754
2045
  }
1755
2046
 
1756
- export { ADMIN_ORDER_BY, ORDER_BY, POST_ORDER_BY, ServerError, createAdminCommandRepository, createAdminQueryRepository, createAdminRefreshTokenCommandRepository, createAdminRefreshTokenQueryRepository, createArgon2Service, createAuthMiddleware, createAuthUseCases, createCache, createCacheResult, createCookieService, createCryptoService, createExecuteAction, createExecuteApi, createFileCommandRepository, createFileQueryRepository, createFolderCommandRepository, createFolderQueryRepository, createIpRateLimiter, createJwtService, createPostCommandRepository, createPostQueryRepository, createSeoMetadataCommandRepository, createVerifyAccessToken, createVerifyRefreshToken, normalizeCacheKey };
2047
+ export { ADMIN_ORDER_BY, ORDER_BY, POST_ORDER_BY, ServerError, createAdminCommandRepository, createAdminQueryRepository, createAdminRefreshTokenCommandRepository, createAdminRefreshTokenQueryRepository, createArgon2Service, createAuthMiddleware, createAuthUseCases, createCache, createCacheResult, createCookieService, createCryptoService, createExecuteAction, createExecuteApi, createExist, createFileCommandRepository, createFileQueryRepository, createFileSchema, createFolderCommandRepository, createFolderQueryRepository, createIpRateLimiter, createJwtService, createMultiFileSchema, createPostCommandRepository, createPostQueryRepository, createSchemas, createSeoMetadataCommandRepository, createTocItemSchema, createUnique, createVerifyAccessToken, createVerifyRefreshToken, createZod, normalizeCacheKey };
@@ -3,11 +3,11 @@ import { Logger } from 'logry';
3
3
  import { S as StorageService } from '../../types-J25u1G6t.js';
4
4
  import '../../types-0oS1A2K5.js';
5
5
 
6
- interface CreateR2ServiceOptions {
6
+ interface CreateR2ServiceParams {
7
7
  r2Client: S3Client;
8
8
  bucketName: string;
9
9
  logger: Logger;
10
10
  }
11
- declare function createR2Service({ r2Client, bucketName, logger, }: CreateR2ServiceOptions): StorageService;
11
+ declare function createR2Service({ r2Client, bucketName, logger, }: CreateR2ServiceParams): StorageService;
12
12
 
13
13
  export { createR2Service };
@@ -1,5 +1,5 @@
1
- import { createObjectKey } from '../../chunk-BTRPDDZJ.js';
2
- import '../../chunk-YX7IPIGU.js';
1
+ import { createObjectKey } from '../../chunk-DWFOB4P3.js';
2
+ import '../../chunk-I2DBI3WJ.js';
3
3
  import { PutObjectCommand, DeleteObjectCommand, CopyObjectCommand } from '@aws-sdk/client-s3';
4
4
 
5
5
  function createR2Service({
@@ -4,17 +4,17 @@ import SFTPClient from 'ssh2-sftp-client';
4
4
  import { S as StorageService } from '../../types-J25u1G6t.js';
5
5
  import '../../types-0oS1A2K5.js';
6
6
 
7
- interface CreateSftpServiceOptions {
7
+ interface CreateSftpServiceParams {
8
8
  sftpPool: Pool<SFTPClient>;
9
9
  basePath: string;
10
10
  logger: Logger;
11
11
  }
12
- declare function createSftpService({ sftpPool, basePath, logger, }: CreateSftpServiceOptions): StorageService;
12
+ declare function createSftpService({ sftpPool, basePath, logger, }: CreateSftpServiceParams): StorageService;
13
13
 
14
- interface CreateSftpPoolOptions {
14
+ interface CreateSftpPoolParams {
15
15
  sftpClientOptions: SFTPClient.ConnectOptions;
16
16
  logger: Logger;
17
17
  }
18
- declare const createSftpPool: ({ sftpClientOptions, logger, }: CreateSftpPoolOptions) => Pool<SFTPClient>;
18
+ declare const createSftpPool: ({ sftpClientOptions, logger, }: CreateSftpPoolParams) => Pool<SFTPClient>;
19
19
 
20
20
  export { createSftpPool, createSftpService };
@@ -1,5 +1,5 @@
1
- import { createObjectKey } from '../../chunk-BTRPDDZJ.js';
2
- import '../../chunk-YX7IPIGU.js';
1
+ import { createObjectKey } from '../../chunk-DWFOB4P3.js';
2
+ import '../../chunk-I2DBI3WJ.js';
3
3
  import path from 'path/posix';
4
4
  import { createPool } from 'generic-pool';
5
5
  import SFTPClient from 'ssh2-sftp-client';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yimingliao/cms",
3
- "version": "0.0.29",
3
+ "version": "0.0.31",
4
4
  "author": "Yiming Liao",
5
5
  "license": "MIT",
6
6
  "type": "module",