@yimingliao/cms 0.0.6 → 0.0.8

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/index.d.ts CHANGED
@@ -83,6 +83,20 @@ declare function createCookieService(nextCookies: () => Promise<Awaited<ReturnTy
83
83
  }) => Promise<void>;
84
84
  };
85
85
 
86
+ type SingleItem = {
87
+ id: string;
88
+ } | null;
89
+ type MultiItems = {
90
+ id: string;
91
+ }[];
92
+
93
+ type BaseTranslation<T extends string = string> = {
94
+ locale: T;
95
+ };
96
+ type Translation<T extends string = string> = BaseTranslation<T> & {
97
+ [k: string]: unknown;
98
+ };
99
+
86
100
  declare const ADMIN_ROLES: {
87
101
  SUPER_ADMIN: "SUPER_ADMIN";
88
102
  ADMIN: "ADMIN";
@@ -103,13 +117,6 @@ interface Admin {
103
117
  }
104
118
  type AdminSafe = Omit<Admin, "passwordHash">;
105
119
 
106
- type BaseTranslation<T extends string = string> = {
107
- locale: T;
108
- };
109
- type Translation<T extends string = string> = BaseTranslation<T> & {
110
- [k: string]: unknown;
111
- };
112
-
113
120
  interface AdminTranslation extends Translation {
114
121
  id: string;
115
122
  locale: string;
@@ -163,7 +170,7 @@ declare const FILE_TYPES: {
163
170
  };
164
171
  type FileType = (typeof FILE_TYPES)[keyof typeof FILE_TYPES];
165
172
 
166
- interface File {
173
+ interface File$1 {
167
174
  id: string;
168
175
  key: string;
169
176
  checksum: string;
@@ -205,10 +212,10 @@ interface Folder {
205
212
  type FolderFull = Folder & {
206
213
  parentFolder: (Folder & {
207
214
  subFolders: Folder[];
208
- files: File[];
215
+ files: File$1[];
209
216
  }) | null;
210
217
  subFolders: Folder[];
211
- files: File[];
218
+ files: File$1[];
212
219
  };
213
220
 
214
221
  declare const POST_TYPES: {
@@ -320,7 +327,7 @@ type PostListCard = Post & {
320
327
  postsInTopic: Post[];
321
328
  children: Post[];
322
329
  taggedPosts: Post[];
323
- coverImage: File | null;
330
+ coverImage: File$1 | null;
324
331
  translations: PostTranslation[];
325
332
  };
326
333
 
@@ -344,7 +351,7 @@ type PostFull = Post & {
344
351
  translations: PostTranslation[];
345
352
  };
346
353
 
347
- type FileFull = File & {
354
+ type FileFull = File$1 & {
348
355
  folder: Folder | null;
349
356
  adminAsAvatarImage: Admin[];
350
357
  postsAsCoverImage: Post[];
@@ -358,13 +365,13 @@ type FileFull = File & {
358
365
  translations: FileTranslation[];
359
366
  };
360
367
 
361
- type FileCard = File & {
368
+ type FileCard = File$1 & {
362
369
  translations: FileTranslation[];
363
370
  };
364
371
 
365
372
  type AdminFull = AdminSafe & {
366
373
  adminRefreshTokens: AdminRefreshToken[];
367
- avatarImage: (File & {
374
+ avatarImage: (File$1 & {
368
375
  translations: FileTranslation[];
369
376
  }) | null;
370
377
  posts: Post[];
@@ -375,12 +382,51 @@ type AdminCard = AdminSafe & {
375
382
  translations: AdminTranslation[];
376
383
  };
377
384
 
378
- type SingleItem = {
379
- id: string;
380
- } | null;
381
- type MultiItems = {
385
+ interface Alternate {
386
+ hreflang: string;
387
+ href: string | null;
388
+ }
389
+
390
+ interface SeoMetadata {
382
391
  id: string;
383
- }[];
392
+ locale: string;
393
+ title: string | null;
394
+ description: string | null;
395
+ author: string | null;
396
+ canonical: string | null;
397
+ alternate: Alternate[];
398
+ robots: string | null;
399
+ ogTitle: string | null;
400
+ ogDescription: string | null;
401
+ ogUrl: string | null;
402
+ ogType: string | null;
403
+ ogSiteName: string | null;
404
+ ogImage: string | null;
405
+ ogImageAlt: string | null;
406
+ ogImageType: string | null;
407
+ ogImageWidth: number | null;
408
+ ogImageHeight: number | null;
409
+ ogLocale: string | null;
410
+ ogLocaleAlternate: string[];
411
+ ogArticlePublishedTime: Date | null;
412
+ ogArticleModifiedTime: Date | null;
413
+ ogArticleAuthor: string | null;
414
+ ogArticleSection: string | null;
415
+ ogArticleTag: string[];
416
+ twitterCard: string | null;
417
+ twitterSite: string | null;
418
+ twitterCreator: string | null;
419
+ jsonLd: object[];
420
+ postId: string;
421
+ createdAt: Date;
422
+ updatedAt: Date;
423
+ }
424
+
425
+ declare const ROOT_FOLDER_ID = "01ARZ3NDEKTSV4RRFFQ69G5FAV";
426
+ declare const ROOT_FOLDER_NAME = "ROOT";
427
+ declare const ROOT_FOLDER: FolderFull;
428
+ declare const SIMPLE_UPLOAD_FOLDER_NAME = "simple-upload";
429
+ declare const SIMPLE_UPLOAD_FOLDER_KEY = "simple-upload";
384
430
 
385
431
  interface CreateParams$4 {
386
432
  email: string;
@@ -498,7 +544,7 @@ interface CreateParams$2 {
498
544
  }
499
545
  interface UpdateParams$2 {
500
546
  id: string;
501
- file: File;
547
+ file: File$1;
502
548
  key: string;
503
549
  checksum: string;
504
550
  fileMeta: {
@@ -518,10 +564,10 @@ interface UpdateParams$2 {
518
564
 
519
565
  declare function createFileCommandRepository(prisma: any): {
520
566
  create: ({ fileMeta, folder, translations, ...params }: CreateParams$2) => Promise<FileFull>;
521
- update: ({ file, id, fileMeta, folder, translations, ...params }: UpdateParams$2) => Promise<File>;
567
+ update: ({ file, id, fileMeta, folder, translations, ...params }: UpdateParams$2) => Promise<File$1>;
522
568
  softDelete: ({ id }: {
523
569
  id: string;
524
- }) => Promise<File>;
570
+ }) => Promise<File$1>;
525
571
  softDeleteMany: ({ ids }: {
526
572
  ids: string[];
527
573
  }) => Promise<number>;
@@ -530,7 +576,7 @@ declare function createFileCommandRepository(prisma: any): {
530
576
  }) => Promise<number>;
531
577
  delete: ({ id }: {
532
578
  id: string;
533
- }) => Promise<File>;
579
+ }) => Promise<File$1>;
534
580
  };
535
581
 
536
582
  interface FindListCardsParams$2 {
@@ -756,46 +802,6 @@ declare function createPostCommandRepository(prisma: any): {
756
802
  }) => Promise<Post>;
757
803
  };
758
804
 
759
- interface Alternate {
760
- hreflang: string;
761
- href: string | null;
762
- }
763
-
764
- interface SeoMetadata {
765
- id: string;
766
- locale: string;
767
- title: string | null;
768
- description: string | null;
769
- author: string | null;
770
- canonical: string | null;
771
- alternate: Alternate[];
772
- robots: string | null;
773
- ogTitle: string | null;
774
- ogDescription: string | null;
775
- ogUrl: string | null;
776
- ogType: string | null;
777
- ogSiteName: string | null;
778
- ogImage: string | null;
779
- ogImageAlt: string | null;
780
- ogImageType: string | null;
781
- ogImageWidth: number | null;
782
- ogImageHeight: number | null;
783
- ogLocale: string | null;
784
- ogLocaleAlternate: string[];
785
- ogArticlePublishedTime: Date | null;
786
- ogArticleModifiedTime: Date | null;
787
- ogArticleAuthor: string | null;
788
- ogArticleSection: string | null;
789
- ogArticleTag: string[];
790
- twitterCard: string | null;
791
- twitterSite: string | null;
792
- twitterCreator: string | null;
793
- jsonLd: object[];
794
- postId: string;
795
- createdAt: Date;
796
- updatedAt: Date;
797
- }
798
-
799
805
  interface FindListCardsParams {
800
806
  locale: string;
801
807
  type: PostType | null;
@@ -901,4 +907,24 @@ declare const POST_ORDER_BY: ({
901
907
  index: "asc";
902
908
  })[];
903
909
 
904
- export { ADMIN_ORDER_BY, ADMIN_ROLES, type Admin, type AdminCard, type AdminFull, type AdminRefreshToken, type AdminRole, type AdminSafe, type AdminTranslation, type Alternate, type BaseTranslation, type DeviceInfo, type ExternalLink, FILE_TYPES, type Faq, type File, type FileCard, type FileFull, type FileTranslation, type FileType, type Folder, type FolderFull, type MultiItems, ORDER_BY, POST_ORDER_BY, POST_TYPES, type Post, type PostFull, type PostListCard, type PostTranslation, type PostType, type SeoMetadata, type SingleItem, type TocItem, type Translation, createAdminCommandRepository, createAdminQueryRepository, createAdminRefreshTokenCommandRepository, createAdminRefreshTokenQueryRepository, createArgon2Service, createCookieService, createCryptoService, createFileCommandRepository, createFileQueryRepository, createFolderCommandRepository, createFolderQueryRepository, createJwtService, createPostCommandRepository, createPostQueryRepository, createSeoMetadataCommandRepository };
910
+ declare const mimeToExtension: (mimeType?: string) => string;
911
+
912
+ declare const classifyFileType: (mimeType?: string, extension?: string) => "IMAGE" | "AUDIO" | "VIDEO" | "DOCUMENT" | "ARCHIVE" | "OTHER";
913
+
914
+ interface MediaInfo {
915
+ width: number | null;
916
+ height: number | null;
917
+ duration: number | null;
918
+ }
919
+ declare const getMediaInfo: (file: Blob) => Promise<MediaInfo>;
920
+
921
+ declare const formatFileSize: (size: number, decimals?: number) => string;
922
+
923
+ interface BlobFile extends File {
924
+ id: string;
925
+ width: number | null;
926
+ height: number | null;
927
+ duration: number | null;
928
+ }
929
+
930
+ export { ADMIN_ORDER_BY, ADMIN_ROLES, type Admin, type AdminCard, type AdminFull, type AdminRefreshToken, type AdminRole, type AdminSafe, type AdminTranslation, type Alternate, type BaseTranslation, type BlobFile, type DeviceInfo, type ExternalLink, FILE_TYPES, type Faq, type File$1 as File, type FileCard, type FileFull, type FileTranslation, type FileType, type Folder, type FolderFull, type MultiItems, ORDER_BY, POST_ORDER_BY, POST_TYPES, type Post, type PostFull, type PostListCard, type PostTranslation, type PostType, ROOT_FOLDER, ROOT_FOLDER_ID, ROOT_FOLDER_NAME, SIMPLE_UPLOAD_FOLDER_KEY, SIMPLE_UPLOAD_FOLDER_NAME, type SeoMetadata, type SingleItem, type TocItem, type Translation, classifyFileType, createAdminCommandRepository, createAdminQueryRepository, createAdminRefreshTokenCommandRepository, createAdminRefreshTokenQueryRepository, createArgon2Service, createCookieService, createCryptoService, createFileCommandRepository, createFileQueryRepository, createFolderCommandRepository, createFolderQueryRepository, createJwtService, createPostCommandRepository, createPostQueryRepository, createSeoMetadataCommandRepository, formatFileSize, getMediaInfo, mimeToExtension };
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import 'next/headers';
5
5
  import { extension, lookup } from 'mime-types';
6
6
  import { ulid } from 'ulid';
7
7
 
8
- // src/infrastructure/jwt/jwt.service.ts
8
+ // src/server/infrastructure/jwt/jwt.service.ts
9
9
  function createJwtService(config) {
10
10
  const { defaultSecret, ...options } = config;
11
11
  function sign({
@@ -195,7 +195,7 @@ function createCookieService(nextCookies, cryptoService) {
195
195
  };
196
196
  }
197
197
 
198
- // src/database/utils/connect.ts
198
+ // src/server/infrastructure/database/utils/connect.ts
199
199
  var ids = (items) => items.map(({ id }) => ({ id }));
200
200
  function connectOne(item) {
201
201
  return item ? { connect: { id: item.id } } : {};
@@ -210,7 +210,7 @@ function updateMany(items) {
210
210
  return { set: ids(items) };
211
211
  }
212
212
 
213
- // src/database/admin/command/create-admin-command-repository.ts
213
+ // src/server/infrastructure/database/admin/command/create-admin-command-repository.ts
214
214
  function createAdminCommandRepository(prisma) {
215
215
  async function create({
216
216
  // ------------------------------------
@@ -291,7 +291,7 @@ function createAdminCommandRepository(prisma) {
291
291
  };
292
292
  }
293
293
 
294
- // src/database/constants.ts
294
+ // src/server/infrastructure/database/constants.ts
295
295
  var ORDER_BY = [
296
296
  { updatedAt: "desc" },
297
297
  { createdAt: "desc" },
@@ -306,14 +306,62 @@ var POST_ORDER_BY = [
306
306
  ...ORDER_BY
307
307
  ];
308
308
 
309
- // src/domain/admin/props.ts
309
+ // src/domain/resources/admin/props.ts
310
310
  var ADMIN_ROLES = {
311
311
  SUPER_ADMIN: "SUPER_ADMIN",
312
312
  ADMIN: "ADMIN",
313
313
  EDITOR: "EDITOR"
314
314
  };
315
315
 
316
- // src/database/admin/include.ts
316
+ // src/domain/resources/file/props.ts
317
+ var FILE_TYPES = {
318
+ IMAGE: "IMAGE",
319
+ AUDIO: "AUDIO",
320
+ VIDEO: "VIDEO",
321
+ DOCUMENT: "DOCUMENT",
322
+ ARCHIVE: "ARCHIVE",
323
+ OTHER: "OTHER"
324
+ };
325
+
326
+ // src/domain/resources/post/props.ts
327
+ var POST_TYPES = {
328
+ TOPIC: "TOPIC",
329
+ CATEGORY: "CATEGORY",
330
+ POST: "POST",
331
+ TAG: "TAG",
332
+ PAGE: "PAGE"
333
+ };
334
+
335
+ // src/domain/resources/constants.ts
336
+ var ROOT_FOLDER_ID = "01ARZ3NDEKTSV4RRFFQ69G5FAV";
337
+ var ROOT_FOLDER_NAME = "ROOT";
338
+ var ROOT_FOLDER = {
339
+ id: ROOT_FOLDER_ID,
340
+ // core
341
+ name: ROOT_FOLDER_NAME,
342
+ key: "",
343
+ // states
344
+ isLocked: true,
345
+ // ---------------------------
346
+ // relations: Folder
347
+ // ---------------------------
348
+ parentFolder: null,
349
+ parentFolderId: null,
350
+ subFolders: [],
351
+ // ---------------------------
352
+ // relations: Folder
353
+ // ---------------------------
354
+ files: [],
355
+ // ---------------------------
356
+ // timestamps
357
+ // ---------------------------
358
+ createdAt: "",
359
+ updatedAt: ""
360
+ };
361
+ var SIMPLE_UPLOAD_FOLDER_NAME = "simple-upload";
362
+ var SIMPLE_UPLOAD_FOLDER_KEY = `${SIMPLE_UPLOAD_FOLDER_NAME}`;
363
+
364
+ // src/server/infrastructure/database/admin/include.ts
317
365
  var ADMIN_FULL_INCLUDE = {
318
366
  // ---------------------------
319
367
  // relations: AdminRefreshToken
@@ -333,7 +381,7 @@ var ADMIN_FULL_INCLUDE = {
333
381
  translations: true
334
382
  };
335
383
 
336
- // src/database/utils/create-search.ts
384
+ // src/server/infrastructure/database/utils/create-search.ts
337
385
  function buildContainsOr(fields, value) {
338
386
  return fields.map((field) => ({
339
387
  [field]: { contains: value, mode: "insensitive" }
@@ -365,7 +413,7 @@ function createSearch({
365
413
  return conditions.length > 0 ? { OR: conditions } : {};
366
414
  }
367
415
 
368
- // src/database/utils/create-pagination.ts
416
+ // src/server/infrastructure/database/utils/create-pagination.ts
369
417
  function createPagination(page, pageSize) {
370
418
  if (!page || !pageSize) return {};
371
419
  return {
@@ -374,7 +422,7 @@ function createPagination(page, pageSize) {
374
422
  };
375
423
  }
376
424
 
377
- // src/database/admin/query/create-admin-query-repository.ts
425
+ // src/server/infrastructure/database/admin/query/create-admin-query-repository.ts
378
426
  var OMIT_PASSWORD = { omit: { passwordHash: true } };
379
427
  function buildWhere(params) {
380
428
  if (params.id) return { id: params.id };
@@ -448,7 +496,7 @@ function createAdminQueryRepository(prisma) {
448
496
  };
449
497
  }
450
498
 
451
- // src/database/admin-refresh-token/command/create-admin-refresh-token-command-repository.ts
499
+ // src/server/infrastructure/database/admin-refresh-token/command/create-admin-refresh-token-command-repository.ts
452
500
  function createAdminRefreshTokenCommandRepository(prisma) {
453
501
  async function create({
454
502
  adminId,
@@ -484,7 +532,7 @@ function createAdminRefreshTokenCommandRepository(prisma) {
484
532
  };
485
533
  }
486
534
 
487
- // src/database/admin-refresh-token/query/create-admin-refresh-token-query-repository.ts
535
+ // src/server/infrastructure/database/admin-refresh-token/query/create-admin-refresh-token-query-repository.ts
488
536
  function createAdminRefreshTokenQueryRepository(prisma) {
489
537
  async function findManyByAdminId({
490
538
  adminId
@@ -507,7 +555,7 @@ function createAdminRefreshTokenQueryRepository(prisma) {
507
555
  };
508
556
  }
509
557
 
510
- // src/database/file/include.ts
558
+ // src/server/infrastructure/database/file/include.ts
511
559
  var FILE_FULL_INCLUDE = {
512
560
  // ---------------------------
513
561
  // relations: Folder
@@ -536,53 +584,157 @@ var FILE_FULL_INCLUDE = {
536
584
  // ---------------------------
537
585
  translations: true
538
586
  };
539
-
540
- // src/domain/file/props.ts
541
- var FILE_TYPES = {
542
- IMAGE: "IMAGE",
543
- AUDIO: "AUDIO",
544
- VIDEO: "VIDEO",
545
- DOCUMENT: "DOCUMENT",
546
- ARCHIVE: "ARCHIVE",
547
- OTHER: "OTHER"
587
+ var mimeToExtension = (mimeType) => {
588
+ if (!mimeType) return "unknown";
589
+ return (extension(mimeType) || "unknown").toLowerCase();
548
590
  };
549
-
550
- // src/domain/file/utils/get-file-type.ts
551
- var getFileType = (mimeType, extension2) => {
591
+ var ARCHIVE_MIME = /* @__PURE__ */ new Set([
592
+ "application/zip",
593
+ "application/x-rar-compressed",
594
+ "application/x-7z-compressed",
595
+ "application/gzip",
596
+ "application/x-tar"
597
+ ]);
598
+ var classifyFileType = (mimeType, extension2) => {
552
599
  if (!mimeType && extension2) {
553
- mimeType = lookup(extension2) || "unknown";
554
- }
555
- if (!mimeType) {
556
- return FILE_TYPES.OTHER;
600
+ mimeType = lookup(extension2) || void 0;
557
601
  }
558
- if (mimeType.startsWith("image/")) {
559
- return FILE_TYPES.IMAGE;
560
- }
561
- if (mimeType.startsWith("video/")) {
562
- return FILE_TYPES.VIDEO;
563
- }
564
- if (mimeType.startsWith("audio/")) {
565
- return FILE_TYPES.AUDIO;
566
- }
567
- if (mimeType.startsWith("text/") || mimeType.startsWith("application/")) {
602
+ if (!mimeType) return FILE_TYPES.OTHER;
603
+ if (mimeType.startsWith("image/")) return FILE_TYPES.IMAGE;
604
+ if (mimeType.startsWith("video/")) return FILE_TYPES.VIDEO;
605
+ if (mimeType.startsWith("audio/")) return FILE_TYPES.AUDIO;
606
+ if (ARCHIVE_MIME.has(mimeType)) return FILE_TYPES.ARCHIVE;
607
+ if (mimeType.startsWith("text/") || mimeType === "application/pdf" || mimeType === "application/json" || mimeType === "application/xml") {
568
608
  return FILE_TYPES.DOCUMENT;
569
609
  }
570
- if (mimeType === "application/zip" || mimeType === "application/x-rar-compressed") {
571
- return FILE_TYPES.ARCHIVE;
572
- }
573
- if (mimeType.startsWith("application/x-") || mimeType === "application/octet-stream") {
574
- return FILE_TYPES.OTHER;
575
- }
610
+ if (mimeType.startsWith("application/")) return FILE_TYPES.DOCUMENT;
576
611
  return FILE_TYPES.OTHER;
577
612
  };
578
- var getExtension = (fileType) => {
579
- if (typeof fileType !== "string") {
580
- return "unknown";
613
+
614
+ // src/shared/blob-file/get-media-info/get-audio-info.ts
615
+ function getAudioInfo(file) {
616
+ return new Promise((resolve, reject) => {
617
+ const audio = document.createElement("audio");
618
+ const objectUrl = URL.createObjectURL(file);
619
+ audio.preload = "metadata";
620
+ const cleanup = () => {
621
+ audio.removeEventListener("loadedmetadata", onLoadedMetadata);
622
+ audio.removeEventListener("error", onError);
623
+ URL.revokeObjectURL(objectUrl);
624
+ };
625
+ const onLoadedMetadata = () => {
626
+ const duration = audio.duration;
627
+ cleanup();
628
+ resolve({ duration });
629
+ };
630
+ const onError = () => {
631
+ cleanup();
632
+ reject(new Error("Failed to load audio metadata."));
633
+ };
634
+ audio.addEventListener("loadedmetadata", onLoadedMetadata, { once: true });
635
+ audio.addEventListener("error", onError, { once: true });
636
+ audio.src = objectUrl;
637
+ });
638
+ }
639
+
640
+ // src/shared/blob-file/get-media-info/get-image-info.ts
641
+ function getImageInfo(file) {
642
+ return new Promise((resolve, reject) => {
643
+ const img = new Image();
644
+ const objectUrl = URL.createObjectURL(file);
645
+ const cleanup = () => {
646
+ img.removeEventListener("load", onLoad);
647
+ img.removeEventListener("error", onError);
648
+ URL.revokeObjectURL(objectUrl);
649
+ };
650
+ const onLoad = () => {
651
+ const width = img.naturalWidth;
652
+ const height = img.naturalHeight;
653
+ cleanup();
654
+ resolve({ width, height });
655
+ };
656
+ const onError = () => {
657
+ cleanup();
658
+ reject(new Error("Failed to load image for size detection."));
659
+ };
660
+ img.addEventListener("load", onLoad, { once: true });
661
+ img.addEventListener("error", onError, { once: true });
662
+ img.src = objectUrl;
663
+ });
664
+ }
665
+
666
+ // src/shared/blob-file/get-media-info/get-video-info.ts
667
+ function getVideoInfo(file) {
668
+ return new Promise((resolve, reject) => {
669
+ const video = document.createElement("video");
670
+ const objectUrl = URL.createObjectURL(file);
671
+ video.preload = "metadata";
672
+ const cleanup = () => {
673
+ video.removeEventListener("loadedmetadata", onLoadedMetadata);
674
+ video.removeEventListener("error", onError);
675
+ video.src = "";
676
+ URL.revokeObjectURL(objectUrl);
677
+ };
678
+ const onLoadedMetadata = () => {
679
+ const info = {
680
+ width: video.videoWidth,
681
+ height: video.videoHeight,
682
+ duration: video.duration
683
+ };
684
+ cleanup();
685
+ resolve(info);
686
+ };
687
+ const onError = () => {
688
+ cleanup();
689
+ reject(new Error("Failed to load video metadata."));
690
+ };
691
+ video.addEventListener("loadedmetadata", onLoadedMetadata, { once: true });
692
+ video.addEventListener("error", onError, { once: true });
693
+ video.src = objectUrl;
694
+ });
695
+ }
696
+
697
+ // src/shared/blob-file/get-media-info/get-media-info.ts
698
+ var IMAGE_EXT = /\.(jpe?g|png|gif|webp|bmp|avif)$/i;
699
+ var VIDEO_EXT = /\.(mp4|webm|mov|mkv)$/i;
700
+ var AUDIO_EXT = /\.(mp3|wav|ogg|m4a)$/i;
701
+ var getMediaInfo = async (file) => {
702
+ const fallback = { width: null, height: null, duration: null };
703
+ const mime = file.type || "";
704
+ const name = file instanceof File ? file.name.toLowerCase() : "";
705
+ try {
706
+ if (mime.startsWith("image/") || IMAGE_EXT.test(name)) {
707
+ const { width, height } = await getImageInfo(file);
708
+ return { width, height, duration: null };
709
+ }
710
+ if (mime.startsWith("video/") || VIDEO_EXT.test(name)) {
711
+ const { width, height, duration } = await getVideoInfo(file);
712
+ return { width, height, duration };
713
+ }
714
+ if (mime.startsWith("audio/") || AUDIO_EXT.test(name)) {
715
+ const { duration } = await getAudioInfo(file);
716
+ return { width: null, height: null, duration };
717
+ }
718
+ return fallback;
719
+ } catch {
720
+ return fallback;
581
721
  }
582
- return (extension(fileType) || "unknown").toLowerCase();
583
722
  };
584
723
 
585
- // src/database/file/command/create-file-command-repository.ts
724
+ // src/shared/blob-file/format-file-size.ts
725
+ var formatFileSize = (size, decimals = 2) => {
726
+ const units = ["B", "KB", "MB", "GB", "TB"];
727
+ let value = size;
728
+ let unitIndex = 0;
729
+ while (value >= 1024 && unitIndex < units.length - 1) {
730
+ value /= 1024;
731
+ unitIndex++;
732
+ }
733
+ const display = unitIndex === 0 ? value.toString() : value.toFixed(decimals);
734
+ return `${display} ${units[unitIndex]}`;
735
+ };
736
+
737
+ // src/server/infrastructure/database/file/command/create-file-command-repository.ts
586
738
  function createFileCommandRepository(prisma) {
587
739
  async function create({
588
740
  // meta
@@ -599,7 +751,7 @@ function createFileCommandRepository(prisma) {
599
751
  // rest
600
752
  ...params
601
753
  }) {
602
- const extension2 = getExtension(fileMeta.type);
754
+ const extension2 = mimeToExtension(fileMeta.type);
603
755
  const created = await prisma.file.create({
604
756
  data: {
605
757
  ...params,
@@ -608,7 +760,7 @@ function createFileCommandRepository(prisma) {
608
760
  size: fileMeta.size ?? 0,
609
761
  extension: extension2,
610
762
  mimeType: fileMeta.type || "unknown",
611
- type: getFileType(fileMeta.type, extension2),
763
+ type: classifyFileType(fileMeta.type, extension2),
612
764
  // ------------------------------------------------------------------------
613
765
  // relations
614
766
  // ------------------------------------------------------------------------
@@ -646,7 +798,7 @@ function createFileCommandRepository(prisma) {
646
798
  // rest
647
799
  ...params
648
800
  }) {
649
- const extension2 = getExtension(fileMeta.type);
801
+ const extension2 = mimeToExtension(fileMeta.type);
650
802
  const updated = await prisma.file.update({
651
803
  where: { id: file.id },
652
804
  data: {
@@ -655,7 +807,7 @@ function createFileCommandRepository(prisma) {
655
807
  size: fileMeta.size ?? file.size,
656
808
  extension: fileMeta ? extension2 : file.extension,
657
809
  mimeType: fileMeta.type || file.mimeType,
658
- type: fileMeta.type ? getFileType(fileMeta.type, extension2) : file.type,
810
+ type: fileMeta.type ? classifyFileType(fileMeta.type, extension2) : file.type,
659
811
  // ------------------------------------------------------------------------
660
812
  // relations
661
813
  // ------------------------------------------------------------------------
@@ -712,7 +864,7 @@ function createFileCommandRepository(prisma) {
712
864
  };
713
865
  }
714
866
 
715
- // src/database/utils/build-file-usage.ts
867
+ // src/server/infrastructure/database/utils/build-file-usage.ts
716
868
  function buildFileUsage(isLocked) {
717
869
  const relations = [
718
870
  "adminAsAvatarImage",
@@ -732,10 +884,7 @@ function buildFileUsage(isLocked) {
732
884
  return isLocked ? { OR: condition } : { AND: condition };
733
885
  }
734
886
 
735
- // src/domain/folder/constants/root-folder.ts
736
- var ROOT_FOLDER_ID = "01ARZ3NDEKTSV4RRFFQ69G5FAV";
737
-
738
- // src/database/file/query/create-file-query-repository.ts
887
+ // src/server/infrastructure/database/file/query/create-file-query-repository.ts
739
888
  function createFileQueryRepository(prisma) {
740
889
  async function findListCards({
741
890
  locale,
@@ -801,7 +950,7 @@ function createFileQueryRepository(prisma) {
801
950
  };
802
951
  }
803
952
 
804
- // src/database/folder/command/create-folder-command-repository.ts
953
+ // src/server/infrastructure/database/folder/command/create-folder-command-repository.ts
805
954
  function createFolderCommandRepository(prisma) {
806
955
  async function create({
807
956
  // ------------------------------------
@@ -860,7 +1009,7 @@ function createFolderCommandRepository(prisma) {
860
1009
  };
861
1010
  }
862
1011
 
863
- // src/database/folder/include.ts
1012
+ // src/server/infrastructure/database/folder/include.ts
864
1013
  var FOLDER_FULL_INCLUDE = {
865
1014
  // ---------------------------
866
1015
  // relations: Folder
@@ -873,7 +1022,7 @@ var FOLDER_FULL_INCLUDE = {
873
1022
  files: true
874
1023
  };
875
1024
 
876
- // src/database/folder/query/create-folder-query-repository.ts
1025
+ // src/server/infrastructure/database/folder/query/create-folder-query-repository.ts
877
1026
  function buildWhere2(params) {
878
1027
  if (params.id) return { id: params.id };
879
1028
  if (params.key) return { key: params.key };
@@ -1108,7 +1257,7 @@ function createPostCommandRepository(prisma) {
1108
1257
  };
1109
1258
  }
1110
1259
 
1111
- // src/database/post/include.ts
1260
+ // src/server/infrastructure/database/post/include.ts
1112
1261
  var POST_LIST_CARD_INCLUDE = {
1113
1262
  // ---------------------------
1114
1263
  // relations: Post
@@ -1165,7 +1314,7 @@ var POST_FULL_INCLUDE = {
1165
1314
  translations: true
1166
1315
  };
1167
1316
 
1168
- // src/database/post/query/create-post-query-repository.ts
1317
+ // src/server/infrastructure/database/post/query/create-post-query-repository.ts
1169
1318
  function buildWhere3(params) {
1170
1319
  if (params.id) return { id: params.id };
1171
1320
  if (params.type && params.slug)
@@ -1264,7 +1413,7 @@ function createPostQueryRepository(prisma) {
1264
1413
  };
1265
1414
  }
1266
1415
 
1267
- // src/database/seo-metadata/command/create-seo-metadata-command-repository.ts
1416
+ // src/server/infrastructure/database/seo-metadata/command/create-seo-metadata-command-repository.ts
1268
1417
  function createSeoMetadataCommandRepository(prisma) {
1269
1418
  async function upsert({
1270
1419
  // ------------------------------------
@@ -1295,13 +1444,4 @@ function createSeoMetadataCommandRepository(prisma) {
1295
1444
  };
1296
1445
  }
1297
1446
 
1298
- // src/domain/post/props.ts
1299
- var POST_TYPES = {
1300
- TOPIC: "TOPIC",
1301
- CATEGORY: "CATEGORY",
1302
- POST: "POST",
1303
- TAG: "TAG",
1304
- PAGE: "PAGE"
1305
- };
1306
-
1307
- export { ADMIN_ORDER_BY, ADMIN_ROLES, FILE_TYPES, ORDER_BY, POST_ORDER_BY, POST_TYPES, createAdminCommandRepository, createAdminQueryRepository, createAdminRefreshTokenCommandRepository, createAdminRefreshTokenQueryRepository, createArgon2Service, createCookieService, createCryptoService, createFileCommandRepository, createFileQueryRepository, createFolderCommandRepository, createFolderQueryRepository, createJwtService, createPostCommandRepository, createPostQueryRepository, createSeoMetadataCommandRepository };
1447
+ export { ADMIN_ORDER_BY, ADMIN_ROLES, FILE_TYPES, ORDER_BY, POST_ORDER_BY, POST_TYPES, ROOT_FOLDER, ROOT_FOLDER_ID, ROOT_FOLDER_NAME, SIMPLE_UPLOAD_FOLDER_KEY, SIMPLE_UPLOAD_FOLDER_NAME, classifyFileType, createAdminCommandRepository, createAdminQueryRepository, createAdminRefreshTokenCommandRepository, createAdminRefreshTokenQueryRepository, createArgon2Service, createCookieService, createCryptoService, createFileCommandRepository, createFileQueryRepository, createFolderCommandRepository, createFolderQueryRepository, createJwtService, createPostCommandRepository, createPostQueryRepository, createSeoMetadataCommandRepository, formatFileSize, getMediaInfo, mimeToExtension };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yimingliao/cms",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "author": "Yiming Liao",
5
5
  "license": "MIT",
6
6
  "type": "module",