@fuma-content/studio 0.1.0 → 1.0.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/index.d.mts +48 -9
- package/dist/index.mjs +16 -15
- package/dist/mdx/actions.mjs +7 -9
- package/dist/package.mjs +1 -1
- package/dist/src/lib/config.mjs +5 -9
- package/package.json +19 -19
- package/src/app/(dashboard)/collection/[name]/[...slug]/page.tsx +2 -1
- package/src/app/(dashboard)/layout.tsx +4 -4
- package/src/lib/config.ts +9 -27
- package/src/lib/data/actions.ts +15 -20
- package/dist/types.d.mts +0 -50
package/dist/index.d.mts
CHANGED
|
@@ -1,13 +1,52 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import "fuma-content/collections";
|
|
1
|
+
import { DocumentItem } from "./src/lib/data/store.mjs";
|
|
2
|
+
import * as fuma_content_collections0 from "fuma-content/collections";
|
|
3
|
+
import { Collection } from "fuma-content/collections";
|
|
4
|
+
import { FC } from "react";
|
|
4
5
|
|
|
5
6
|
//#region lib/index.d.ts
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
type Awaitable<T> = T | Promise<T>;
|
|
8
|
+
interface StudioDocument {
|
|
9
|
+
id: string;
|
|
10
|
+
name: string;
|
|
10
11
|
}
|
|
11
|
-
|
|
12
|
+
interface MDXStudioDocument extends StudioDocument {
|
|
13
|
+
type: "mdx";
|
|
14
|
+
filePath: string;
|
|
15
|
+
}
|
|
16
|
+
interface CreateDocumentDialogContext {
|
|
17
|
+
collectionId: string;
|
|
18
|
+
useDialog: () => {
|
|
19
|
+
open: boolean;
|
|
20
|
+
setOpen: (v: boolean) => void;
|
|
21
|
+
onCreate: (item: DocumentItem) => void;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
interface StudioHook<Doc extends StudioDocument = StudioDocument> {
|
|
25
|
+
init?: () => Awaitable<void>;
|
|
26
|
+
getDocuments: () => Awaitable<Doc[]>;
|
|
27
|
+
getDocument: (id: string) => Awaitable<Doc | undefined>;
|
|
28
|
+
pages?: {
|
|
29
|
+
edit?: FC<{
|
|
30
|
+
document: Doc;
|
|
31
|
+
collection: Collection;
|
|
32
|
+
}>;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* the properties inside should be exported from a file with "use client".
|
|
36
|
+
*/
|
|
37
|
+
client?: () => Awaitable<ClientContext>;
|
|
38
|
+
actions?: {
|
|
39
|
+
deleteDocument?: (options: {
|
|
40
|
+
collection: Collection;
|
|
41
|
+
document: Doc;
|
|
42
|
+
}) => Awaitable<void>;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
interface ClientContext {
|
|
46
|
+
dialogs?: {
|
|
47
|
+
createDocument?: FC<CreateDocumentDialogContext>;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
declare const studioHook: fuma_content_collections0.CollectionHook<StudioHook<StudioDocument>, StudioHook<StudioDocument> | undefined>;
|
|
12
51
|
//#endregion
|
|
13
|
-
export { ClientContext, CreateDocumentDialogContext, MDXStudioDocument, StudioDocument,
|
|
52
|
+
export { ClientContext, CreateDocumentDialogContext, MDXStudioDocument, StudioDocument, StudioHook, studioHook };
|
package/dist/index.mjs
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import { getJSONSchema } from "fuma-content";
|
|
2
|
-
import "fuma-content/collections";
|
|
2
|
+
import { defineCollectionHook } from "fuma-content/collections";
|
|
3
3
|
import fs from "node:fs/promises";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import grayMatter from "gray-matter";
|
|
6
|
+
import { MDXCollection } from "fuma-content/collections/mdx";
|
|
6
7
|
import { jsx } from "react/jsx-runtime";
|
|
7
8
|
|
|
8
9
|
//#region lib/index.tsx
|
|
9
|
-
|
|
10
|
+
const studioHook = defineCollectionHook((collection, options) => {
|
|
11
|
+
if (options) return options;
|
|
12
|
+
if (collection instanceof MDXCollection) return mdx(collection);
|
|
10
13
|
return {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
14
|
+
getDocuments() {
|
|
15
|
+
return [];
|
|
16
|
+
},
|
|
17
|
+
getDocument() {}
|
|
15
18
|
};
|
|
16
|
-
}
|
|
19
|
+
});
|
|
17
20
|
function mdx(collection) {
|
|
18
|
-
const { mdx: mdxHandler, fs: fsHandler } = collection.handlers;
|
|
19
|
-
if (!mdxHandler || !fsHandler) return;
|
|
20
21
|
async function read(doc) {
|
|
21
22
|
try {
|
|
22
23
|
return (await fs.readFile(doc.filePath)).toString();
|
|
@@ -26,25 +27,25 @@ function mdx(collection) {
|
|
|
26
27
|
}
|
|
27
28
|
return {
|
|
28
29
|
async getDocuments() {
|
|
29
|
-
return (await
|
|
30
|
+
return (await collection.getFiles()).map((file) => {
|
|
30
31
|
return {
|
|
31
32
|
type: "mdx",
|
|
32
33
|
id: file,
|
|
33
34
|
name: file,
|
|
34
|
-
filePath: path.join(
|
|
35
|
+
filePath: path.join(collection.dir, file)
|
|
35
36
|
};
|
|
36
37
|
});
|
|
37
38
|
},
|
|
38
39
|
async getDocument(id) {
|
|
39
40
|
return (await this.getDocuments()).find((doc) => doc.id === id);
|
|
40
41
|
},
|
|
41
|
-
pages: { async edit({ document
|
|
42
|
+
pages: { async edit({ document }) {
|
|
42
43
|
const { MDXDocUpdateEditor } = await import("./mdx/client.mjs");
|
|
43
44
|
const parsed = grayMatter(await read(document) ?? "");
|
|
44
|
-
const jsonSchema =
|
|
45
|
+
const jsonSchema = collection.frontmatterSchema ? JSON.parse(JSON.stringify(getJSONSchema(collection.frontmatterSchema))) : void 0;
|
|
45
46
|
return /* @__PURE__ */ jsx(MDXDocUpdateEditor, {
|
|
46
47
|
documentId: document.id,
|
|
47
|
-
collectionId: collection
|
|
48
|
+
collectionId: collection.name,
|
|
48
49
|
jsonSchema,
|
|
49
50
|
frontmatter: parsed.data,
|
|
50
51
|
content: parsed.content
|
|
@@ -63,4 +64,4 @@ function mdx(collection) {
|
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
//#endregion
|
|
66
|
-
export {
|
|
67
|
+
export { studioHook };
|
package/dist/mdx/actions.mjs
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
|
|
3
|
+
import { studioHook } from "../index.mjs";
|
|
3
4
|
import { requireCollection, requireDocument } from "../src/lib/config.mjs";
|
|
4
5
|
import fs from "node:fs/promises";
|
|
5
6
|
import path from "node:path";
|
|
7
|
+
import { MDXCollection } from "fuma-content/collections/mdx";
|
|
6
8
|
|
|
7
9
|
//#region lib/mdx/actions.ts
|
|
8
10
|
async function saveMDXDocument(collectionId, documentId, value) {
|
|
@@ -10,14 +12,10 @@ async function saveMDXDocument(collectionId, documentId, value) {
|
|
|
10
12
|
if ("type" in doc && doc.type === "mdx") await fs.writeFile(doc.filePath, value);
|
|
11
13
|
}
|
|
12
14
|
async function createMDXDocument(collectionId, name, content) {
|
|
13
|
-
const collection = await requireCollection(collectionId
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
]);
|
|
18
|
-
const fsHandler = collection.handlers.fs;
|
|
19
|
-
const filePath = path.join(fsHandler.dir, `${name}.mdx`);
|
|
20
|
-
const relativeFilePath = path.relative(fsHandler.dir, filePath);
|
|
15
|
+
const collection = await requireCollection(collectionId);
|
|
16
|
+
if (!(collection instanceof MDXCollection)) throw new Error("Invalid collection ID");
|
|
17
|
+
const filePath = path.join(collection.dir, `${name}.mdx`);
|
|
18
|
+
const relativeFilePath = path.relative(collection.dir, filePath);
|
|
21
19
|
if (relativeFilePath.startsWith(`..${path.sep}`)) throw new Error(`invalid collection name: ${name}`);
|
|
22
20
|
if (await fs.access(filePath, fs.constants.R_OK).then(() => true).catch(() => false)) throw new Error(`document ${name} already exists`);
|
|
23
21
|
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
@@ -26,7 +24,7 @@ async function createMDXDocument(collectionId, name, content) {
|
|
|
26
24
|
collectionId,
|
|
27
25
|
id: relativeFilePath,
|
|
28
26
|
name: relativeFilePath,
|
|
29
|
-
permissions: { delete: collection.
|
|
27
|
+
permissions: { delete: collection.pluginHook(studioHook).actions?.deleteDocument !== void 0 }
|
|
30
28
|
};
|
|
31
29
|
}
|
|
32
30
|
|
package/dist/package.mjs
CHANGED
package/dist/src/lib/config.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { studioHook } from "../../index.mjs";
|
|
1
2
|
import { Core } from "fuma-content";
|
|
2
3
|
|
|
3
4
|
//#region src/lib/config.ts
|
|
@@ -14,25 +15,20 @@ async function getCore() {
|
|
|
14
15
|
})();
|
|
15
16
|
return core;
|
|
16
17
|
}
|
|
17
|
-
async function requireCollection(collectionId
|
|
18
|
+
async function requireCollection(collectionId) {
|
|
18
19
|
const collection = (await getCore()).getCollection(collectionId);
|
|
19
20
|
if (!collection) throw new Error(`Missing Collection ${collectionId}`);
|
|
20
|
-
|
|
21
|
-
throw new Error(`Missing ${handlers.join(", ")} handlers for ${collectionId}`);
|
|
21
|
+
return collection;
|
|
22
22
|
}
|
|
23
23
|
async function requireDocument(collectionId, documentId) {
|
|
24
|
-
const collection = await requireCollection(collectionId
|
|
25
|
-
const document = await collection.
|
|
24
|
+
const collection = await requireCollection(collectionId);
|
|
25
|
+
const document = await collection.pluginHook(studioHook).getDocument(documentId);
|
|
26
26
|
if (!document) throw new Error(`Missing Document ${documentId}`);
|
|
27
27
|
return {
|
|
28
28
|
collection,
|
|
29
29
|
document
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
|
-
function hasHandler(collection, handlers) {
|
|
33
|
-
for (const handler of handlers) if (collection.handlers[handler] === void 0) return false;
|
|
34
|
-
return true;
|
|
35
|
-
}
|
|
36
32
|
|
|
37
33
|
//#endregion
|
|
38
34
|
export { requireCollection, requireDocument };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fuma-content/studio",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "The studio integration of Fuma Content",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Contentlayer",
|
|
@@ -31,14 +31,14 @@
|
|
|
31
31
|
"access": "public"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@ai-sdk/gateway": "^3.0.
|
|
35
|
-
"@ai-sdk/react": "3.0.
|
|
36
|
-
"@base-ui/react": "^1.
|
|
37
|
-
"@base-ui/utils": "^0.2.
|
|
34
|
+
"@ai-sdk/gateway": "^3.0.16",
|
|
35
|
+
"@ai-sdk/react": "3.0.41",
|
|
36
|
+
"@base-ui/react": "^1.1.0",
|
|
37
|
+
"@base-ui/utils": "^0.2.4",
|
|
38
38
|
"@clack/prompts": "^1.0.0-alpha.9",
|
|
39
39
|
"@emoji-mart/data": "1.2.1",
|
|
40
40
|
"@monaco-editor/react": "^4.7.0",
|
|
41
|
-
"@platejs/ai": "^52.0
|
|
41
|
+
"@platejs/ai": "^52.1.0",
|
|
42
42
|
"@platejs/autoformat": "^52.0.11",
|
|
43
43
|
"@platejs/basic-nodes": "^52.0.11",
|
|
44
44
|
"@platejs/basic-styles": "^52.0.11",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"@platejs/layout": "^52.0.11",
|
|
56
56
|
"@platejs/link": "^52.0.11",
|
|
57
57
|
"@platejs/list": "^52.0.11",
|
|
58
|
-
"@platejs/markdown": "^52.0
|
|
58
|
+
"@platejs/markdown": "^52.1.0",
|
|
59
59
|
"@platejs/math": "^52.0.11",
|
|
60
60
|
"@platejs/media": "^52.0.11",
|
|
61
61
|
"@platejs/resizable": "^52.0.11",
|
|
@@ -64,11 +64,11 @@
|
|
|
64
64
|
"@platejs/suggestion": "^52.0.11",
|
|
65
65
|
"@platejs/table": "^52.0.11",
|
|
66
66
|
"@standard-schema/spec": "^1.1.0",
|
|
67
|
-
"@tanstack/query-db-collection": "^1.0.
|
|
68
|
-
"@tanstack/react-db": "^0.1.
|
|
69
|
-
"@tanstack/react-query": "^5.90.
|
|
67
|
+
"@tanstack/query-db-collection": "^1.0.17",
|
|
68
|
+
"@tanstack/react-db": "^0.1.64",
|
|
69
|
+
"@tanstack/react-query": "^5.90.19",
|
|
70
70
|
"@uploadthing/react": "7.3.3",
|
|
71
|
-
"ai": "6.0.
|
|
71
|
+
"ai": "6.0.39",
|
|
72
72
|
"ajv": "^8.17.1",
|
|
73
73
|
"class-variance-authority": "^0.7.1",
|
|
74
74
|
"clsx": "^2.1.1",
|
|
@@ -81,17 +81,17 @@
|
|
|
81
81
|
"lodash.debounce": "^4.0.8",
|
|
82
82
|
"lowlight": "^3.3.0",
|
|
83
83
|
"lucide-react": "^0.562.0",
|
|
84
|
-
"next": "16.1.
|
|
84
|
+
"next": "16.1.3",
|
|
85
85
|
"next-themes": "^0.4.6",
|
|
86
86
|
"open": "^11.0.0",
|
|
87
|
-
"platejs": "^52.0.
|
|
87
|
+
"platejs": "^52.0.17",
|
|
88
88
|
"radix-ui": "^1.4.3",
|
|
89
89
|
"react": "19.2.3",
|
|
90
90
|
"react-day-picker": "^9.13.0",
|
|
91
91
|
"react-dnd": "^16.0.1",
|
|
92
92
|
"react-dnd-html5-backend": "^16.0.1",
|
|
93
93
|
"react-dom": "19.2.3",
|
|
94
|
-
"react-hook-form": "^7.
|
|
94
|
+
"react-hook-form": "^7.71.1",
|
|
95
95
|
"react-textarea-autosize": "^8.5.9",
|
|
96
96
|
"remark-gfm": "^4.0.1",
|
|
97
97
|
"remark-math": "^6.0.0",
|
|
@@ -105,21 +105,21 @@
|
|
|
105
105
|
"devDependencies": {
|
|
106
106
|
"@tailwindcss/postcss": "^4",
|
|
107
107
|
"@types/lodash.debounce": "^4.0.9",
|
|
108
|
-
"@types/node": "^25.0.
|
|
109
|
-
"@types/react": "^19",
|
|
108
|
+
"@types/node": "^25.0.9",
|
|
109
|
+
"@types/react": "^19.2.8",
|
|
110
110
|
"@types/react-dom": "^19",
|
|
111
111
|
"babel-plugin-react-compiler": "1.0.0",
|
|
112
112
|
"dedent": "^1.7.1",
|
|
113
113
|
"json-schema-typed": "^8.0.2",
|
|
114
|
-
"shadcn": "^3.
|
|
114
|
+
"shadcn": "^3.7.0",
|
|
115
115
|
"tailwindcss": "^4",
|
|
116
116
|
"tsdown": "^0.18.3",
|
|
117
117
|
"tw-animate-css": "^1.4.0",
|
|
118
118
|
"typescript": "^5",
|
|
119
|
-
"fuma-content": "^1.0
|
|
119
|
+
"fuma-content": "^1.1.0"
|
|
120
120
|
},
|
|
121
121
|
"peerDependencies": {
|
|
122
|
-
"fuma-content": "^1.0
|
|
122
|
+
"fuma-content": "^1.1.0"
|
|
123
123
|
},
|
|
124
124
|
"scripts": {
|
|
125
125
|
"dev": "tsdown --watch",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { notFound } from "next/navigation";
|
|
2
2
|
import { requireDocument } from "@/lib/config";
|
|
3
3
|
import { Header } from "./page.client";
|
|
4
|
+
import { studioHook } from "@lib/index";
|
|
4
5
|
|
|
5
6
|
export default async function Page({ params }: PageProps<"/collection/[name]/[...slug]">) {
|
|
6
7
|
const { name, slug } = await params;
|
|
@@ -10,7 +11,7 @@ export default async function Page({ params }: PageProps<"/collection/[name]/[..
|
|
|
10
11
|
<>
|
|
11
12
|
<Header collectionId={collection.name} documentId={document.id} />
|
|
12
13
|
<div className="flex flex-1 min-w-0 flex-col gap-2 p-2">
|
|
13
|
-
{await collection.
|
|
14
|
+
{await collection.pluginHook(studioHook).pages?.edit?.({ document, collection })}
|
|
14
15
|
</div>
|
|
15
16
|
</>
|
|
16
17
|
);
|
|
@@ -4,7 +4,7 @@ import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar";
|
|
|
4
4
|
import { Toaster } from "@/components/ui/sonner";
|
|
5
5
|
import { getCore } from "@/lib/config";
|
|
6
6
|
import { DataBoundary } from "@/lib/data/boundary";
|
|
7
|
-
import { ClientContext } from "lib";
|
|
7
|
+
import { ClientContext, studioHook } from "lib";
|
|
8
8
|
import type { ReactNode } from "react";
|
|
9
9
|
|
|
10
10
|
export default async function Layout({ children }: { children: ReactNode }) {
|
|
@@ -12,9 +12,9 @@ export default async function Layout({ children }: { children: ReactNode }) {
|
|
|
12
12
|
const collections = core.getCollections(true);
|
|
13
13
|
const clientContexts = new Map<string, ClientContext>();
|
|
14
14
|
for (const collection of collections) {
|
|
15
|
-
const {
|
|
16
|
-
if (
|
|
17
|
-
clientContexts.set(collection.name, await
|
|
15
|
+
const { client } = collection.pluginHook(studioHook);
|
|
16
|
+
if (client) {
|
|
17
|
+
clientContexts.set(collection.name, await client());
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
package/src/lib/config.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import {
|
|
3
|
-
import { Collection
|
|
1
|
+
import { studioHook, type StudioDocument } from "lib";
|
|
2
|
+
import { Core } from "fuma-content";
|
|
3
|
+
import { Collection } from "fuma-content/collections";
|
|
4
4
|
|
|
5
5
|
let core: Promise<Core>;
|
|
6
6
|
|
|
@@ -22,39 +22,21 @@ export async function getCore(): Promise<Core> {
|
|
|
22
22
|
return core;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
export async function requireCollection
|
|
26
|
-
collectionId: string,
|
|
27
|
-
handlers: Handler[],
|
|
28
|
-
): Promise<CollectionWithHandler<Handler>> {
|
|
25
|
+
export async function requireCollection(collectionId: string): Promise<Collection> {
|
|
29
26
|
const core = await getCore();
|
|
30
27
|
const collection = core.getCollection(collectionId);
|
|
31
28
|
if (!collection) throw new Error(`Missing Collection ${collectionId}`);
|
|
32
29
|
|
|
33
|
-
|
|
34
|
-
return collection;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
throw new Error(`Missing ${handlers.join(", ")} handlers for ${collectionId}`);
|
|
30
|
+
return collection;
|
|
38
31
|
}
|
|
39
32
|
|
|
40
33
|
export async function requireDocument<Doc extends StudioDocument = StudioDocument>(
|
|
41
34
|
collectionId: string,
|
|
42
35
|
documentId: string,
|
|
43
|
-
): Promise<{ collection:
|
|
44
|
-
const collection = await requireCollection(collectionId
|
|
45
|
-
const document
|
|
36
|
+
): Promise<{ collection: Collection; document: Doc }> {
|
|
37
|
+
const collection = await requireCollection(collectionId);
|
|
38
|
+
const document = await collection.pluginHook(studioHook).getDocument(documentId);
|
|
46
39
|
if (!document) throw new Error(`Missing Document ${documentId}`);
|
|
47
40
|
|
|
48
|
-
return { collection:
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export function hasHandler<Handler extends keyof CollectionHandlers = never>(
|
|
52
|
-
collection: Collection,
|
|
53
|
-
handlers: Handler[],
|
|
54
|
-
): collection is CollectionWithHandler<Handler> {
|
|
55
|
-
for (const handler of handlers) {
|
|
56
|
-
if (collection.handlers[handler] === undefined) return false;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return true;
|
|
41
|
+
return { collection, document: document as Doc };
|
|
60
42
|
}
|
package/src/lib/data/actions.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
|
|
3
|
+
import { studioHook } from "@lib/index";
|
|
3
4
|
import { getCore, requireDocument } from "../config";
|
|
4
5
|
import type { CollectionItem, DocumentItem } from "./store";
|
|
5
6
|
|
|
@@ -8,8 +9,7 @@ export async function getCollectionItems(): Promise<CollectionItem[]> {
|
|
|
8
9
|
return core.getCollections(true).map<CollectionItem>((collection) => ({
|
|
9
10
|
id: collection.name,
|
|
10
11
|
name: collection.name,
|
|
11
|
-
badge: collection.
|
|
12
|
-
handlers: Object.fromEntries(Object.keys(collection.handlers).map((k) => [k, null])),
|
|
12
|
+
badge: collection.constructor.name,
|
|
13
13
|
}));
|
|
14
14
|
}
|
|
15
15
|
|
|
@@ -17,23 +17,18 @@ export async function getDocumentItems(): Promise<DocumentItem[]> {
|
|
|
17
17
|
const core = await getCore();
|
|
18
18
|
const items = await Promise.all(
|
|
19
19
|
core.getCollections(true).map(async (collection) => {
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
},
|
|
33
|
-
}));
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return [];
|
|
20
|
+
const hook = collection.pluginHook(studioHook);
|
|
21
|
+
const docs = await hook.getDocuments();
|
|
22
|
+
const supportDelete = hook.actions?.deleteDocument !== undefined;
|
|
23
|
+
|
|
24
|
+
return docs.map<DocumentItem>((doc) => ({
|
|
25
|
+
name: doc.name,
|
|
26
|
+
id: doc.id,
|
|
27
|
+
collectionId: collection.name,
|
|
28
|
+
permissions: {
|
|
29
|
+
delete: supportDelete,
|
|
30
|
+
},
|
|
31
|
+
}));
|
|
37
32
|
}),
|
|
38
33
|
);
|
|
39
34
|
|
|
@@ -42,7 +37,7 @@ export async function getDocumentItems(): Promise<DocumentItem[]> {
|
|
|
42
37
|
|
|
43
38
|
export async function deleteDocumentAction(documentId: string, collectionId: string) {
|
|
44
39
|
const { collection, document } = await requireDocument(collectionId, documentId);
|
|
45
|
-
const { deleteDocument } = collection.
|
|
40
|
+
const { deleteDocument } = collection.pluginHook(studioHook).actions ?? {};
|
|
46
41
|
if (deleteDocument) {
|
|
47
42
|
await deleteDocument({ collection, document });
|
|
48
43
|
} else {
|
package/dist/types.d.mts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { DocumentItem } from "./src/lib/data/store.mjs";
|
|
2
|
-
import { Collection } from "fuma-content/collections";
|
|
3
|
-
import { FC } from "react";
|
|
4
|
-
|
|
5
|
-
//#region lib/types.d.ts
|
|
6
|
-
type Awaitable<T> = T | Promise<T>;
|
|
7
|
-
interface StudioDocument {
|
|
8
|
-
id: string;
|
|
9
|
-
name: string;
|
|
10
|
-
}
|
|
11
|
-
interface MDXStudioDocument extends StudioDocument {
|
|
12
|
-
type: "mdx";
|
|
13
|
-
filePath: string;
|
|
14
|
-
}
|
|
15
|
-
interface CreateDocumentDialogContext {
|
|
16
|
-
collectionId: string;
|
|
17
|
-
useDialog: () => {
|
|
18
|
-
open: boolean;
|
|
19
|
-
setOpen: (v: boolean) => void;
|
|
20
|
-
onCreate: (item: DocumentItem) => void;
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
interface ClientContext {
|
|
24
|
-
dialogs?: {
|
|
25
|
-
createDocument?: FC<CreateDocumentDialogContext>;
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
interface StudioHandler<Doc extends StudioDocument> {
|
|
29
|
-
init?: () => Awaitable<void>;
|
|
30
|
-
getDocuments: () => Awaitable<Doc[]>;
|
|
31
|
-
getDocument: (id: string) => Awaitable<Doc | undefined>;
|
|
32
|
-
pages?: {
|
|
33
|
-
edit?: FC<{
|
|
34
|
-
document: Doc;
|
|
35
|
-
collection: Collection;
|
|
36
|
-
}>;
|
|
37
|
-
};
|
|
38
|
-
/**
|
|
39
|
-
* the properties inside should be exported from a file with "use client".
|
|
40
|
-
*/
|
|
41
|
-
client?: () => Awaitable<ClientContext>;
|
|
42
|
-
actions?: {
|
|
43
|
-
deleteDocument?: (options: {
|
|
44
|
-
collection: Collection;
|
|
45
|
-
document: Doc;
|
|
46
|
-
}) => Awaitable<void>;
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
//#endregion
|
|
50
|
-
export { ClientContext, CreateDocumentDialogContext, MDXStudioDocument, StudioDocument, StudioHandler };
|