memi-board 0.32.0 → 0.36.0
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/composables/boardLookup.d.ts +8 -0
- package/dist/composables/useMemiBoardAuth.d.ts +4 -3
- package/dist/composables/useMemiBoardCommentFeed.d.ts +18 -0
- package/dist/composables/useMemiBoardComments.d.ts +2 -0
- package/dist/composables/useMemiBoardLikes.d.ts +9 -0
- package/dist/composables/useMemiBoardMiniPosts.d.ts +12 -0
- package/dist/composables/useMemiBoardReports.d.ts +114 -0
- package/dist/composables/useMemiBoardSections.d.ts +13 -0
- package/dist/composables/useMemiBoardSettings.d.ts +2 -0
- package/dist/config.d.ts +2 -0
- package/dist/{heic2any-BWRKffWN.js → heic2any-D2QKy06h.js} +2 -2
- package/dist/{heic2any-BWRKffWN.js.map → heic2any-D2QKy06h.js.map} +1 -1
- package/dist/index.d.ts +12 -3
- package/dist/index.js +1161 -647
- package/dist/index.js.map +1 -1
- package/dist/runtime/components/CategorySettings.vue +3 -5
- package/dist/runtime/components/CommentFeed.vue +141 -0
- package/dist/runtime/components/CommentForm.vue +2 -2
- package/dist/runtime/components/CommentItem.vue +55 -5
- package/dist/runtime/components/CommentList.vue +10 -2
- package/dist/runtime/components/Detail.vue +8 -0
- package/dist/runtime/components/Mini.vue +37 -0
- package/dist/runtime/components/MiniCard.vue +51 -0
- package/dist/runtime/components/MiniComments.vue +75 -0
- package/dist/runtime/components/MiniList.vue +36 -0
- package/dist/runtime/components/MiniPicker.vue +131 -0
- package/dist/runtime/components/MiniPost.vue +52 -0
- package/dist/runtime/components/MiniPosts.vue +115 -0
- package/dist/runtime/components/ReportButton.vue +117 -0
- package/dist/runtime/components/ReportList.vue +124 -0
- package/dist/runtime/components/Section.vue +62 -0
- package/dist/runtime/components/Settings.vue +3 -4
- package/dist/runtime/components/UserCommentList.vue +3 -0
- package/dist/{slugify-B5XHr4SZ.js → slugify-Cyq-Gg8X.js} +47 -36
- package/dist/slugify-Cyq-Gg8X.js.map +1 -0
- package/dist/storage.js +11 -11
- package/dist/types.d.ts +54 -3
- package/dist/utils/boardAccess.d.ts +7 -0
- package/dist/utils/boardPaths.d.ts +10 -3
- package/dist/utils/deletePostCascade.d.ts +7 -1
- package/dist/utils/section.d.ts +31 -0
- package/docs/firestore.indexes.json.example +38 -0
- package/docs/firestore.rules.example +78 -22
- package/package.json +1 -1
- package/dist/slugify-B5XHr4SZ.js.map +0 -1
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type BoardLookup = (boardId: string) => {
|
|
2
|
+
allowedStaffUids?: string[];
|
|
3
|
+
} | undefined;
|
|
4
|
+
export declare function registerBoardLookup(fn: BoardLookup): void;
|
|
5
|
+
export declare function resolveBoardLookup(boardId: string): {
|
|
6
|
+
allowedStaffUids?: string[];
|
|
7
|
+
} | undefined;
|
|
8
|
+
export {};
|
|
@@ -8,6 +8,7 @@ export interface UseMemiBoardAuthReturn {
|
|
|
8
8
|
isAdmin: ComputedRef<boolean>;
|
|
9
9
|
isStaff: ComputedRef<boolean>;
|
|
10
10
|
canManageContent: ComputedRef<boolean>;
|
|
11
|
+
canManageBoard: (boardId: string | undefined | null) => boolean;
|
|
11
12
|
rolePending: Ref<boolean>;
|
|
12
13
|
/** 유효 검열 차단 누적 (lazy decay 반영) */
|
|
13
14
|
moderationBlockCount: ComputedRef<number>;
|
|
@@ -20,10 +21,10 @@ export interface UseMemiBoardAuthReturn {
|
|
|
20
21
|
signInWithEmail: (email: string, password: string) => ReturnType<typeof signInWithEmailAndPassword>;
|
|
21
22
|
signUpWithEmail: (email: string, password: string, displayName?: string) => ReturnType<typeof createUserWithEmailAndPassword>;
|
|
22
23
|
signOut: () => Promise<void>;
|
|
23
|
-
canEdit: (post: Pick<PostModel, 'authorUid'>) => boolean;
|
|
24
|
-
canDelete: (post: Pick<PostModel, 'authorUid'>) => boolean;
|
|
24
|
+
canEdit: (post: Pick<PostModel, 'authorUid' | 'boardId'>) => boolean;
|
|
25
|
+
canDelete: (post: Pick<PostModel, 'authorUid' | 'boardId'>) => boolean;
|
|
25
26
|
canEditComment: (comment: Pick<CommentModel, 'authorUid'>) => boolean;
|
|
26
|
-
canDeleteComment: (comment: Pick<CommentModel, 'authorUid'>) => boolean;
|
|
27
|
+
canDeleteComment: (comment: Pick<CommentModel, 'authorUid' | 'boardId'>) => boolean;
|
|
27
28
|
/** 콘텐츠 검열 차단 1회 기록 후 메시지 조각 반환 */
|
|
28
29
|
recordContentModerationBlock: () => Promise<{
|
|
29
30
|
effectiveCount: number;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { MaybeRefOrGetter } from 'vue';
|
|
2
|
+
import { CommentModel } from '../types';
|
|
3
|
+
export type CommentFeedSort = 'latest' | 'likes';
|
|
4
|
+
/**
|
|
5
|
+
* 보드를 가로질러 댓글을 모은다. 최신순은 createdAt, 좋아요순은 likeCount.
|
|
6
|
+
* likeCount 가 없는 예전 댓글은 좋아요순 쿼리에 나오지 않는다(표시 시 0).
|
|
7
|
+
*/
|
|
8
|
+
export declare function useMemiBoardCommentFeed(sort?: MaybeRefOrGetter<CommentFeedSort>, options?: {
|
|
9
|
+
pageSize?: MaybeRefOrGetter<number>;
|
|
10
|
+
}): {
|
|
11
|
+
comments: import('vue').ComputedRef<CommentModel[]>;
|
|
12
|
+
commentsPending: import('vue').Ref<boolean, boolean>;
|
|
13
|
+
hasMore: import('vue').Ref<boolean, boolean>;
|
|
14
|
+
loadingMore: import('vue').Ref<boolean, boolean>;
|
|
15
|
+
loadError: import('vue').Ref<string, string>;
|
|
16
|
+
loadMore: () => Promise<void>;
|
|
17
|
+
sort: import('vue').ComputedRef<CommentFeedSort>;
|
|
18
|
+
};
|
|
@@ -90,6 +90,7 @@ export declare function useMemiBoardReplies(boardId: string, postId: string, roo
|
|
|
90
90
|
replyToName?: string | null | undefined;
|
|
91
91
|
replyCount?: number | undefined;
|
|
92
92
|
isReply?: boolean | undefined;
|
|
93
|
+
likeCount?: number | undefined;
|
|
93
94
|
}[], CommentModel[] | {
|
|
94
95
|
id?: string | undefined;
|
|
95
96
|
postId: string;
|
|
@@ -150,6 +151,7 @@ export declare function useMemiBoardReplies(boardId: string, postId: string, roo
|
|
|
150
151
|
replyToName?: string | null | undefined;
|
|
151
152
|
replyCount?: number | undefined;
|
|
152
153
|
isReply?: boolean | undefined;
|
|
154
|
+
likeCount?: number | undefined;
|
|
153
155
|
}[]>;
|
|
154
156
|
loading: Ref<boolean, boolean>;
|
|
155
157
|
loaded: Ref<boolean, boolean>;
|
|
@@ -1,5 +1,14 @@
|
|
|
1
|
+
import { InjectionKey, MaybeRefOrGetter } from 'vue';
|
|
1
2
|
export declare function useMemiBoardLikes(boardId: string, postId: string): {
|
|
2
3
|
isLiked: import('vue').Ref<boolean, boolean>;
|
|
3
4
|
likePending: import('vue').Ref<boolean, boolean>;
|
|
4
5
|
toggleLike: () => Promise<boolean>;
|
|
5
6
|
};
|
|
7
|
+
export interface MemiBoardCommentLikesApi {
|
|
8
|
+
isLiked: (commentId: string | undefined) => boolean;
|
|
9
|
+
isPending: (commentId: string | undefined) => boolean;
|
|
10
|
+
toggleLike: (commentId: string) => Promise<boolean>;
|
|
11
|
+
}
|
|
12
|
+
export declare const memiBoardCommentLikesKey: InjectionKey<MemiBoardCommentLikesApi>;
|
|
13
|
+
/** 글 하나에서 내가 누른 댓글 좋아요를 쿼리 1번으로 구독한다. 댓글마다 리스너를 달지 않는다. */
|
|
14
|
+
export declare function useMemiBoardCommentLikes(boardId: MaybeRefOrGetter<string>, postId: MaybeRefOrGetter<string>): MemiBoardCommentLikesApi;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { MaybeRefOrGetter } from 'vue';
|
|
2
|
+
import { PostModel } from '../types';
|
|
3
|
+
export declare function useMemiBoardMiniLatest(boardId: MaybeRefOrGetter<string | null>, count: MaybeRefOrGetter<number>): {
|
|
4
|
+
posts: import('vue').ComputedRef<import('vuefire').VueFirestoreQueryData<PostModel>>;
|
|
5
|
+
pending: import('vue').Ref<boolean, boolean>;
|
|
6
|
+
error: import('vue').Ref<import('firebase/firestore').FirestoreError | undefined, import('firebase/firestore').FirestoreError | undefined>;
|
|
7
|
+
};
|
|
8
|
+
export declare function useMemiBoardMiniPicked(postIds: MaybeRefOrGetter<string[]>): {
|
|
9
|
+
posts: import('vue').ComputedRef<PostModel[]>;
|
|
10
|
+
pending: import('vue').Ref<boolean, boolean>;
|
|
11
|
+
error: import('vue').Ref<import('firebase/firestore').FirestoreError | undefined, import('firebase/firestore').FirestoreError | undefined>;
|
|
12
|
+
};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { MaybeRefOrGetter } from 'vue';
|
|
2
|
+
import { BoardReportModel, BoardReportReason, BoardReportStatus } from '../types';
|
|
3
|
+
export declare const REPORT_DETAIL_MAX_LENGTH = 200;
|
|
4
|
+
export declare const REPORT_REASONS: {
|
|
5
|
+
value: BoardReportReason;
|
|
6
|
+
label: string;
|
|
7
|
+
}[];
|
|
8
|
+
export declare function reportReasonLabel(reason: BoardReportReason | string | undefined): string;
|
|
9
|
+
export declare function useMemiBoardReports(boardId: string, postId: string): {
|
|
10
|
+
hasReported: import('vue').Ref<boolean, boolean>;
|
|
11
|
+
pending: import('vue').Ref<boolean, boolean>;
|
|
12
|
+
submitReport: (input: {
|
|
13
|
+
reason: BoardReportReason;
|
|
14
|
+
detail?: string;
|
|
15
|
+
postTitle?: string;
|
|
16
|
+
authorUid?: string;
|
|
17
|
+
authorName?: string | null;
|
|
18
|
+
}) => Promise<void>;
|
|
19
|
+
};
|
|
20
|
+
export declare function useMemiBoardReportQueue(options?: {
|
|
21
|
+
pageSize?: number;
|
|
22
|
+
boardId?: MaybeRefOrGetter<string>;
|
|
23
|
+
}): {
|
|
24
|
+
reports: import('vue').Ref<{
|
|
25
|
+
id?: string | undefined;
|
|
26
|
+
uid: string;
|
|
27
|
+
target: import('..').BoardReportTarget;
|
|
28
|
+
postId: string;
|
|
29
|
+
boardId: string;
|
|
30
|
+
reason: BoardReportReason;
|
|
31
|
+
detail: string;
|
|
32
|
+
status: BoardReportStatus;
|
|
33
|
+
createdAt: {
|
|
34
|
+
readonly seconds: number;
|
|
35
|
+
readonly nanoseconds: number;
|
|
36
|
+
toDate: () => Date;
|
|
37
|
+
toMillis: () => number;
|
|
38
|
+
isEqual: (other: import('firebase/firestore').Timestamp) => boolean;
|
|
39
|
+
toString: () => string;
|
|
40
|
+
toJSON: () => {
|
|
41
|
+
seconds: number;
|
|
42
|
+
nanoseconds: number;
|
|
43
|
+
type: string;
|
|
44
|
+
};
|
|
45
|
+
valueOf: () => string;
|
|
46
|
+
};
|
|
47
|
+
postTitle?: string | undefined;
|
|
48
|
+
authorUid?: string | undefined;
|
|
49
|
+
authorName?: string | null | undefined;
|
|
50
|
+
reviewedAt?: {
|
|
51
|
+
readonly seconds: number;
|
|
52
|
+
readonly nanoseconds: number;
|
|
53
|
+
toDate: () => Date;
|
|
54
|
+
toMillis: () => number;
|
|
55
|
+
isEqual: (other: import('firebase/firestore').Timestamp) => boolean;
|
|
56
|
+
toString: () => string;
|
|
57
|
+
toJSON: () => {
|
|
58
|
+
seconds: number;
|
|
59
|
+
nanoseconds: number;
|
|
60
|
+
type: string;
|
|
61
|
+
};
|
|
62
|
+
valueOf: () => string;
|
|
63
|
+
} | undefined;
|
|
64
|
+
reviewedBy?: string | undefined;
|
|
65
|
+
}[], BoardReportModel[] | {
|
|
66
|
+
id?: string | undefined;
|
|
67
|
+
uid: string;
|
|
68
|
+
target: import('..').BoardReportTarget;
|
|
69
|
+
postId: string;
|
|
70
|
+
boardId: string;
|
|
71
|
+
reason: BoardReportReason;
|
|
72
|
+
detail: string;
|
|
73
|
+
status: BoardReportStatus;
|
|
74
|
+
createdAt: {
|
|
75
|
+
readonly seconds: number;
|
|
76
|
+
readonly nanoseconds: number;
|
|
77
|
+
toDate: () => Date;
|
|
78
|
+
toMillis: () => number;
|
|
79
|
+
isEqual: (other: import('firebase/firestore').Timestamp) => boolean;
|
|
80
|
+
toString: () => string;
|
|
81
|
+
toJSON: () => {
|
|
82
|
+
seconds: number;
|
|
83
|
+
nanoseconds: number;
|
|
84
|
+
type: string;
|
|
85
|
+
};
|
|
86
|
+
valueOf: () => string;
|
|
87
|
+
};
|
|
88
|
+
postTitle?: string | undefined;
|
|
89
|
+
authorUid?: string | undefined;
|
|
90
|
+
authorName?: string | null | undefined;
|
|
91
|
+
reviewedAt?: {
|
|
92
|
+
readonly seconds: number;
|
|
93
|
+
readonly nanoseconds: number;
|
|
94
|
+
toDate: () => Date;
|
|
95
|
+
toMillis: () => number;
|
|
96
|
+
isEqual: (other: import('firebase/firestore').Timestamp) => boolean;
|
|
97
|
+
toString: () => string;
|
|
98
|
+
toJSON: () => {
|
|
99
|
+
seconds: number;
|
|
100
|
+
nanoseconds: number;
|
|
101
|
+
type: string;
|
|
102
|
+
};
|
|
103
|
+
valueOf: () => string;
|
|
104
|
+
} | undefined;
|
|
105
|
+
reviewedBy?: string | undefined;
|
|
106
|
+
}[]>;
|
|
107
|
+
pending: import('vue').Ref<boolean, boolean>;
|
|
108
|
+
loadingMore: import('vue').Ref<boolean, boolean>;
|
|
109
|
+
hasMore: import('vue').Ref<boolean, boolean>;
|
|
110
|
+
loadError: import('vue').Ref<string, string>;
|
|
111
|
+
loadMore: () => Promise<void>;
|
|
112
|
+
dismissReport: (report: BoardReportModel) => Promise<void>;
|
|
113
|
+
actionReport: (report: BoardReportModel) => Promise<void>;
|
|
114
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BoardSection, BoardSectionLayout } from '../types';
|
|
2
|
+
export declare const DEFAULT_BOARD_SECTIONS: BoardSection[];
|
|
3
|
+
export declare function normalizeBoardSection(raw: Record<string, unknown>, order: number): BoardSection;
|
|
4
|
+
/** 호스트 `settings/homeLayout` 문서를 읽는다. 기존 메인 레이아웃 경로를 유지한다. */
|
|
5
|
+
export declare function useMemiBoardSections(): {
|
|
6
|
+
settings: import('vue').Ref<import('vuefire').VueFirestoreDocumentData<BoardSectionLayout> | undefined, import('vuefire').VueFirestoreDocumentData<BoardSectionLayout> | undefined>;
|
|
7
|
+
pending: import('vue').Ref<boolean, boolean>;
|
|
8
|
+
sections: import('vue').ComputedRef<BoardSection[]>;
|
|
9
|
+
blocks: import('vue').ComputedRef<BoardSection[]>;
|
|
10
|
+
hasSavedLayout: import('vue').ComputedRef<boolean>;
|
|
11
|
+
saveSections: (next: BoardSection[]) => Promise<void>;
|
|
12
|
+
saveBlocks: (next: BoardSection[]) => Promise<void>;
|
|
13
|
+
};
|
|
@@ -16,6 +16,8 @@ export declare function useMemiBoardSettings(): {
|
|
|
16
16
|
boardVisibility: (id: string | undefined) => BoardVisibility;
|
|
17
17
|
isBoardHidden: (id: string | undefined) => boolean;
|
|
18
18
|
getBoard: (id: string | undefined) => BoardModel | undefined;
|
|
19
|
+
canManageBoard: (boardId: string | undefined | null) => boolean;
|
|
20
|
+
managedBoards: import('vue').ComputedRef<BoardModel[]>;
|
|
19
21
|
categories: import('vue').ComputedRef<BoardModel[]>;
|
|
20
22
|
publicCategories: import('vue').ComputedRef<BoardModel[]>;
|
|
21
23
|
categoryLabel: (id: string | undefined) => string | undefined;
|
package/dist/config.d.ts
CHANGED
|
@@ -30,6 +30,8 @@ export interface MemiBoardConfig {
|
|
|
30
30
|
commentsCollection: string;
|
|
31
31
|
/** 좋아요 컬렉션. 기본 `memiBoardLikes` */
|
|
32
32
|
likesCollection: string;
|
|
33
|
+
/** 신고 컬렉션. 기본 `memiBoardReports` */
|
|
34
|
+
reportsCollection: string;
|
|
33
35
|
/** 보드 설정 컬렉션. 기본 `memiBoardSettings` */
|
|
34
36
|
settingsCollection: string;
|
|
35
37
|
/** 역할 문서 컬렉션. 기본 `memiBoardUsers` */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { M as e } from "./slugify-Cyq-Gg8X.js";
|
|
2
2
|
//#region node_modules/.pnpm/heic2any@0.0.4/node_modules/heic2any/dist/heic2any.js
|
|
3
3
|
var t = /* @__PURE__ */ e(((e, t) => {
|
|
4
4
|
(function(n, r, i, a) {
|
|
@@ -974,4 +974,4 @@ var t = /* @__PURE__ */ e(((e, t) => {
|
|
|
974
974
|
//#endregion
|
|
975
975
|
export default t();
|
|
976
976
|
|
|
977
|
-
//# sourceMappingURL=heic2any-
|
|
977
|
+
//# sourceMappingURL=heic2any-D2QKy06h.js.map
|