sanity-plugin-singleton-management 1.0.6 → 1.1.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/README.md +29 -25
- package/dist/index.cjs +34 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -28
- package/dist/index.d.ts +27 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/package.json +64 -44
- package/dist/index.esm.d.ts +0 -44
- package/dist/index.esm.js +0 -56
- package/dist/index.esm.js.map +0 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# sanity-plugin-singleton-tools
|
|
4
4
|
|
|
5
|
-
> This is compatible with
|
|
5
|
+
> This is compatible with Sanity versions 3.x, 4.x, 5.x, and 6.x.
|
|
6
6
|
|
|
7
7
|
## What does this plugin do?
|
|
8
8
|
|
|
@@ -20,23 +20,23 @@ While Sanity Studio supports singleton documents through the Structure Builder A
|
|
|
20
20
|
plugin eliminates the repetitive boilerplate and provides additional safeguards:
|
|
21
21
|
|
|
22
22
|
### Native Sanity Approach
|
|
23
|
+
|
|
23
24
|
```js
|
|
24
25
|
// Requires manual Structure Builder configuration for each singleton
|
|
25
26
|
export const structure = (S) =>
|
|
26
27
|
S.list()
|
|
27
|
-
.title(
|
|
28
|
+
.title("Content")
|
|
28
29
|
.items([
|
|
29
30
|
S.listItem()
|
|
30
|
-
.title(
|
|
31
|
+
.title("Site Settings")
|
|
31
32
|
.child(
|
|
32
|
-
S.document()
|
|
33
|
-
.schemaType('siteSettings')
|
|
34
|
-
.documentId('siteSettings')
|
|
33
|
+
S.document().schemaType("siteSettings").documentId("siteSettings"),
|
|
35
34
|
),
|
|
36
35
|
// Must manually filter out singletons from main list
|
|
37
|
-
...S.documentTypeListItems().filter(
|
|
38
|
-
![
|
|
39
|
-
|
|
36
|
+
...S.documentTypeListItems().filter(
|
|
37
|
+
(listItem) => !["siteSettings"].includes(listItem.getId()),
|
|
38
|
+
),
|
|
39
|
+
]);
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
**Issues:**
|
|
@@ -46,7 +46,6 @@ export const structure = (S) =>
|
|
|
46
46
|
- Users can still create new versions via global Create menu
|
|
47
47
|
- Manual filtering required to prevent duplicates in document lists
|
|
48
48
|
|
|
49
|
-
|
|
50
49
|
**With This Plugin:**
|
|
51
50
|
|
|
52
51
|
```js
|
|
@@ -72,21 +71,21 @@ export const mySingleton = defineType({
|
|
|
72
71
|
```
|
|
73
72
|
|
|
74
73
|
```js
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
])
|
|
74
|
+
// structure.js/ts
|
|
75
|
+
export const structure = (S, context) =>
|
|
76
|
+
S.list().items([
|
|
77
|
+
...singletonDocumentListItems({ S, context }), // Auto-generates all singletons
|
|
78
|
+
...filteredDocumentListItems({ S, context }), // Auto-filters singletons from main list
|
|
79
|
+
]);
|
|
82
80
|
```
|
|
83
81
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
82
|
+
Benefits:
|
|
83
|
+
|
|
84
|
+
- ✅ Minimal configuration with `singleton: true`
|
|
85
|
+
- ✅ Automatic action restrictions (no duplicate creation)
|
|
86
|
+
- ✅ Global Create menu integration
|
|
87
|
+
- ✅ Helper functions eliminate boilerplate
|
|
88
|
+
- ✅ Consistent singleton behavior across your studio
|
|
90
89
|
|
|
91
90
|
## Installation
|
|
92
91
|
|
|
@@ -99,17 +98,21 @@ npm install sanity-plugin-singleton-management
|
|
|
99
98
|
This plugin is a modernized, actively maintained fork of `sanity-plugin-singleton-tools` with identical API compatibility. Migration is straightforward:
|
|
100
99
|
|
|
101
100
|
### Steps
|
|
101
|
+
|
|
102
102
|
1. **Uninstall the old package**:
|
|
103
|
+
|
|
103
104
|
```sh
|
|
104
105
|
npm uninstall sanity-plugin-singleton-tools
|
|
105
106
|
```
|
|
106
107
|
|
|
107
108
|
2. **Install this package**:
|
|
109
|
+
|
|
108
110
|
```sh
|
|
109
111
|
npm install sanity-plugin-singleton-management
|
|
110
112
|
```
|
|
111
113
|
|
|
112
114
|
3. **Update your import statements**:
|
|
115
|
+
|
|
113
116
|
```diff
|
|
114
117
|
// sanity.config.js
|
|
115
118
|
- import { singletonTools } from 'sanity-plugin-singleton-tools'
|
|
@@ -123,6 +126,7 @@ This plugin is a modernized, actively maintained fork of `sanity-plugin-singleto
|
|
|
123
126
|
**That's it!** No other code changes are required. Your existing schema configurations and structure customizations will work exactly the same.
|
|
124
127
|
|
|
125
128
|
### What's New
|
|
129
|
+
|
|
126
130
|
- ✅ **React 18/19 Support**: Compatible with modern React versions
|
|
127
131
|
- ✅ **Sanity v3/v4 Support**: Works with both Sanity Studio versions
|
|
128
132
|
- ✅ **Modern Tooling**: ESM/CommonJS dual package, better TypeScript support
|
|
@@ -205,7 +209,7 @@ Other reading (Sanity docs):
|
|
|
205
209
|
|
|
206
210
|
## Credits
|
|
207
211
|
|
|
208
|
-
This project is a fork of [sanity-plugin-singleton-tools](https://github.com/plsrd/sanity-plugin-singleton-tools)
|
|
212
|
+
This project is a fork of [sanity-plugin-singleton-tools](https://github.com/plsrd/sanity-plugin-singleton-tools)
|
|
209
213
|
originally created by [RD Pennell](https://github.com/plsrd).
|
|
210
214
|
|
|
211
215
|
## License
|
|
@@ -216,4 +220,4 @@ MIT License \
|
|
|
216
220
|
<div style="text-align: right">
|
|
217
221
|
Copyright © 2025 <a href="https://github.com/rcmaples" target="_blank">RC Maples</a> </br>
|
|
218
222
|
Copyright © 2024-2025 <a href="https://github.com/plsrd" target="_blank">RD Pennell</a>
|
|
219
|
-
</div>
|
|
223
|
+
</div>
|
package/dist/index.cjs
CHANGED
|
@@ -1,55 +1,39 @@
|
|
|
1
|
-
"
|
|
2
|
-
|
|
3
|
-
var sanity = require("sanity"), icons = require("@sanity/icons");
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
let sanity = require("sanity"), _sanity_icons = require("@sanity/icons");
|
|
4
3
|
const getSingletonDocuments = (schema) => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
4
|
+
if (schema?._original?.types) return schema._original.types.filter(({ options }) => options?.singleton).map((s) => s.name);
|
|
5
|
+
}, getIsSingleton = (schema, schemaType) => !schema?._original?.types || !schemaType ? !1 : schema._original.types.find(({ name }) => name === schemaType)?.options?.singleton ?? !1, actions = (prev, { schema, schemaType }) => getIsSingleton(schema, schemaType) ? prev.filter(({ action }) => [
|
|
6
|
+
"publish",
|
|
7
|
+
"discardChanges",
|
|
8
|
+
"restore"
|
|
9
|
+
].includes(action)) : prev, newDocumentOptions = (prev, { schema, creationContext: { type, schemaType } }) => {
|
|
10
|
+
let singletons = getSingletonDocuments(schema), filterSingletons = ({ templateId }) => !singletons?.includes(templateId);
|
|
11
|
+
return type === "global" || singletons?.includes(schemaType ?? "") ? prev.filter(filterSingletons) : prev;
|
|
12
|
+
}, singletonTools = (0, sanity.definePlugin)(() => ({
|
|
13
|
+
name: "singleton-tools",
|
|
14
|
+
document: {
|
|
15
|
+
newDocumentOptions,
|
|
16
|
+
actions
|
|
17
|
+
}
|
|
20
18
|
})), singletonDocumentListItem = (config) => {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (!schema)
|
|
27
|
-
throw new Error(
|
|
28
|
-
"Schema is required in context for singletonDocumentListItem"
|
|
29
|
-
);
|
|
30
|
-
const schemaType = schema.get(type), listTitle = title ?? schemaType?.title ?? type, listIcon = icon ?? schemaType?.icon ?? icons.DocumentIcon, listId = id ?? type;
|
|
31
|
-
return S.listItem().title(listTitle).icon(listIcon).child(S.document().schemaType(type).title(listTitle).id(listId));
|
|
19
|
+
if (!config?.S || !config?.type || !config.context) throw Error("S, context, and type must be provided to singletonDocumentListItem. Example: singletonDocumentListItem({ S, context, type: 'product' })");
|
|
20
|
+
let { S, type, title, icon, id, context } = config, { schema } = context;
|
|
21
|
+
if (!schema) throw Error("Schema is required in context for singletonDocumentListItem");
|
|
22
|
+
let schemaType = schema.get(type), listTitle = title ?? schemaType?.title ?? type, listIcon = icon ?? schemaType?.icon ?? _sanity_icons.DocumentIcon, listId = id ?? type;
|
|
23
|
+
return S.listItem().title(listTitle).icon(listIcon).child(S.document().schemaType(type).title(listTitle).id(listId));
|
|
32
24
|
}, singletonDocumentListItems = (config) => {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
) || [];
|
|
25
|
+
if (!config.S || !config.context) throw Error("S and context must be provided to singletonDocumentListItems. Example: singletonDocumentListItems({ S, context })");
|
|
26
|
+
let { S, context } = config, { schema } = context;
|
|
27
|
+
return getSingletonDocuments(schema)?.map((schemaType) => singletonDocumentListItem({
|
|
28
|
+
S,
|
|
29
|
+
context,
|
|
30
|
+
type: schemaType
|
|
31
|
+
})) || [];
|
|
41
32
|
}, filteredDocumentListItems = (config) => {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
);
|
|
46
|
-
const { S, context } = config, { schema } = context, singletons = getSingletonDocuments(schema);
|
|
47
|
-
return S.documentTypeListItems().filter(
|
|
48
|
-
(type) => !singletons || !singletons.includes(type.getId())
|
|
49
|
-
);
|
|
33
|
+
if (!config.S || !config.context) throw Error("S and context must be provided to filteredDocumentListItems. Example: filteredDocumentListItems({ S, context })");
|
|
34
|
+
let { S, context } = config, { schema } = context, singletons = getSingletonDocuments(schema);
|
|
35
|
+
return S.documentTypeListItems().filter((type) => !singletons || !singletons.includes(type.getId()));
|
|
50
36
|
};
|
|
51
|
-
exports.filteredDocumentListItems = filteredDocumentListItems;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
exports.singletonTools = singletonTools;
|
|
55
|
-
//# sourceMappingURL=index.cjs.map
|
|
37
|
+
exports.filteredDocumentListItems = filteredDocumentListItems, exports.singletonDocumentListItem = singletonDocumentListItem, exports.singletonDocumentListItems = singletonDocumentListItems, exports.singletonTools = singletonTools;
|
|
38
|
+
|
|
39
|
+
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/helpers/index.ts","../src/actions.ts","../src/newDocumentOptions.ts","../src/pluginConfig.ts","../src/structure/index.ts"],"sourcesContent":["import { Schema } from \"sanity\";\n\nimport { SingletonPluginOptions } from \"../types\";\n\nexport const getSingletonDocuments = (schema: Schema): string[] | undefined => {\n if (!schema?._original?.types) {\n return undefined;\n }\n\n return schema._original.types\n .filter(({ options }) => (options as SingletonPluginOptions)?.singleton)\n .map((s: { name: string }) => s.name);\n};\n\nexport const getIsSingleton = (schema: Schema, schemaType: string): boolean => {\n if (!schema?._original?.types || !schemaType) {\n return false;\n }\n\n const documentSchema = schema._original.types.find(\n ({ name }) => name === schemaType,\n );\n\n return (\n (documentSchema?.options as SingletonPluginOptions)?.singleton ?? false\n );\n};\n","import { DocumentActionsContext, DocumentActionsResolver } from \"sanity\";\n\nimport { getIsSingleton } from \"./helpers\";\n\nexport const actions: DocumentActionsResolver = (\n prev,\n { schema, schemaType }: DocumentActionsContext,\n) => {\n return getIsSingleton(schema, schemaType)\n ? prev.filter(({ action }) =>\n [\"publish\", \"discardChanges\", \"restore\"].includes(action as string),\n )\n : prev;\n};\n","import { NewDocumentOptionsContext, NewDocumentOptionsResolver } from \"sanity\";\n\nimport { getSingletonDocuments } from \"./helpers\";\n\nexport const newDocumentOptions: NewDocumentOptionsResolver = (\n prev,\n { schema, creationContext: { type, schemaType } }: NewDocumentOptionsContext,\n) => {\n const singletons = getSingletonDocuments(schema);\n\n const filterSingletons = ({ templateId }: { templateId: string }) =>\n !singletons?.includes(templateId);\n\n if (type === \"global\") return prev.filter(filterSingletons);\n\n return singletons?.includes(schemaType ?? \"\")\n ? prev.filter(filterSingletons)\n : prev;\n};\n","import { definePlugin } from \"sanity\";\n\nimport { actions } from \"./actions\";\nimport { newDocumentOptions } from \"./newDocumentOptions\";\n\nexport const singletonTools = definePlugin(() => {\n return {\n name: \"singleton-tools\",\n document: {\n newDocumentOptions,\n actions,\n },\n };\n});\n","import { DocumentIcon } from \"@sanity/icons\";\nimport type { ListItemBuilder } from \"sanity/structure\";\n\nimport { getSingletonDocuments } from \"../helpers\";\nimport {\n SingletonDocumentListItemConfig,\n SingletonPluginListItemsConfig,\n} from \"../types\";\n\nconst singletonDocumentListItem = (\n config: SingletonDocumentListItemConfig,\n): ListItemBuilder => {\n if (!config?.S || !config?.type || !config.context) {\n throw new Error(\n \"S, context, and type must be provided to singletonDocumentListItem. \" +\n \"Example: singletonDocumentListItem({ S, context, type: 'product' })\",\n );\n }\n const { S, type, title, icon, id, context } = config;\n const { schema } = context;\n\n if (!schema) {\n throw new Error(\n \"Schema is required in context for singletonDocumentListItem\",\n );\n }\n\n const schemaType = schema.get(type);\n const listTitle = title ?? schemaType?.title ?? type;\n const listIcon = icon ?? schemaType?.icon ?? DocumentIcon;\n const listId = id ?? type;\n\n return S.listItem()\n .title(listTitle)\n .icon(listIcon)\n .child(S.document().schemaType(type).title(listTitle).id(listId));\n};\n\nconst singletonDocumentListItems = (\n config: SingletonPluginListItemsConfig,\n): ListItemBuilder[] => {\n if (!config.S || !config.context) {\n throw new Error(\n \"S and context must be provided to singletonDocumentListItems. \" +\n \"Example: singletonDocumentListItems({ S, context })\",\n );\n }\n\n const { S, context } = config;\n const { schema } = context;\n\n const singletons = getSingletonDocuments(schema);\n\n return (\n singletons?.map((schemaType) =>\n singletonDocumentListItem({ S, context, type: schemaType }),\n ) || []\n );\n};\n\nconst filteredDocumentListItems = (\n config: SingletonPluginListItemsConfig,\n): ListItemBuilder[] => {\n if (!config.S || !config.context) {\n throw new Error(\n \"S and context must be provided to filteredDocumentListItems. \" +\n \"Example: filteredDocumentListItems({ S, context })\",\n );\n }\n const { S, context } = config;\n const { schema } = context;\n\n const singletons = getSingletonDocuments(schema);\n\n return S.documentTypeListItems().filter(\n (type) => !singletons || !singletons.includes(type.getId() as string),\n );\n};\n\nexport {\n filteredDocumentListItems,\n singletonDocumentListItem,\n singletonDocumentListItems,\n};\n"],"
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["definePlugin","DocumentIcon"],"sources":["../src/helpers/index.ts","../src/actions.ts","../src/newDocumentOptions.ts","../src/pluginConfig.ts","../src/structure/index.ts"],"sourcesContent":["import { Schema } from \"sanity\";\n\nimport { SingletonPluginOptions } from \"../types\";\n\nexport const getSingletonDocuments = (schema: Schema): string[] | undefined => {\n if (!schema?._original?.types) {\n return undefined;\n }\n\n return schema._original.types\n .filter(({ options }) => (options as SingletonPluginOptions)?.singleton)\n .map((s: { name: string }) => s.name);\n};\n\nexport const getIsSingleton = (schema: Schema, schemaType: string): boolean => {\n if (!schema?._original?.types || !schemaType) {\n return false;\n }\n\n const documentSchema = schema._original.types.find(\n ({ name }) => name === schemaType,\n );\n\n return (\n (documentSchema?.options as SingletonPluginOptions)?.singleton ?? false\n );\n};\n","import { DocumentActionsContext, DocumentActionsResolver } from \"sanity\";\n\nimport { getIsSingleton } from \"./helpers\";\n\nexport const actions: DocumentActionsResolver = (\n prev,\n { schema, schemaType }: DocumentActionsContext,\n) => {\n return getIsSingleton(schema, schemaType)\n ? prev.filter(({ action }) =>\n [\"publish\", \"discardChanges\", \"restore\"].includes(action as string),\n )\n : prev;\n};\n","import { NewDocumentOptionsContext, NewDocumentOptionsResolver } from \"sanity\";\n\nimport { getSingletonDocuments } from \"./helpers\";\n\nexport const newDocumentOptions: NewDocumentOptionsResolver = (\n prev,\n { schema, creationContext: { type, schemaType } }: NewDocumentOptionsContext,\n) => {\n const singletons = getSingletonDocuments(schema);\n\n const filterSingletons = ({ templateId }: { templateId: string }) =>\n !singletons?.includes(templateId);\n\n if (type === \"global\") return prev.filter(filterSingletons);\n\n return singletons?.includes(schemaType ?? \"\")\n ? prev.filter(filterSingletons)\n : prev;\n};\n","import { definePlugin } from \"sanity\";\n\nimport { actions } from \"./actions\";\nimport { newDocumentOptions } from \"./newDocumentOptions\";\n\nexport const singletonTools = definePlugin(() => {\n return {\n name: \"singleton-tools\",\n document: {\n newDocumentOptions,\n actions,\n },\n };\n});\n","import { DocumentIcon } from \"@sanity/icons\";\nimport type { ListItemBuilder } from \"sanity/structure\";\n\nimport { getSingletonDocuments } from \"../helpers\";\nimport {\n SingletonDocumentListItemConfig,\n SingletonPluginListItemsConfig,\n} from \"../types\";\n\nconst singletonDocumentListItem = (\n config: SingletonDocumentListItemConfig,\n): ListItemBuilder => {\n if (!config?.S || !config?.type || !config.context) {\n throw new Error(\n \"S, context, and type must be provided to singletonDocumentListItem. \" +\n \"Example: singletonDocumentListItem({ S, context, type: 'product' })\",\n );\n }\n const { S, type, title, icon, id, context } = config;\n const { schema } = context;\n\n if (!schema) {\n throw new Error(\n \"Schema is required in context for singletonDocumentListItem\",\n );\n }\n\n const schemaType = schema.get(type);\n const listTitle = title ?? schemaType?.title ?? type;\n const listIcon = icon ?? schemaType?.icon ?? DocumentIcon;\n const listId = id ?? type;\n\n return S.listItem()\n .title(listTitle)\n .icon(listIcon)\n .child(S.document().schemaType(type).title(listTitle).id(listId));\n};\n\nconst singletonDocumentListItems = (\n config: SingletonPluginListItemsConfig,\n): ListItemBuilder[] => {\n if (!config.S || !config.context) {\n throw new Error(\n \"S and context must be provided to singletonDocumentListItems. \" +\n \"Example: singletonDocumentListItems({ S, context })\",\n );\n }\n\n const { S, context } = config;\n const { schema } = context;\n\n const singletons = getSingletonDocuments(schema);\n\n return (\n singletons?.map((schemaType) =>\n singletonDocumentListItem({ S, context, type: schemaType }),\n ) || []\n );\n};\n\nconst filteredDocumentListItems = (\n config: SingletonPluginListItemsConfig,\n): ListItemBuilder[] => {\n if (!config.S || !config.context) {\n throw new Error(\n \"S and context must be provided to filteredDocumentListItems. \" +\n \"Example: filteredDocumentListItems({ S, context })\",\n );\n }\n const { S, context } = config;\n const { schema } = context;\n\n const singletons = getSingletonDocuments(schema);\n\n return S.documentTypeListItems().filter(\n (type) => !singletons || !singletons.includes(type.getId() as string),\n );\n};\n\nexport {\n filteredDocumentListItems,\n singletonDocumentListItem,\n singletonDocumentListItems,\n};\n"],"mappings":";;AAIA,MAAa,yBAAyB,WAAyC;CACxE,YAAQ,WAAW,OAIxB,OAAO,OAAO,UAAU,MACrB,QAAQ,EAAE,cAAe,SAAoC,SAAS,CAAC,CACvE,KAAK,MAAwB,EAAE,IAAI;AACxC,GAEa,kBAAkB,QAAgB,eACzC,CAAC,QAAQ,WAAW,SAAS,CAAC,aACzB,KAGc,OAAO,UAAU,MAAM,MAC3C,EAAE,WAAW,SAAS,UAIT,CAAC,EAAE,SAAoC,aAAa,ICpBzD,WACX,MACA,EAAE,QAAQ,iBAEH,eAAe,QAAQ,UAAU,IACpC,KAAK,QAAQ,EAAE,aACb;CAAC;CAAW;CAAkB;AAAS,CAAC,CAAC,SAAS,MAAgB,CACpE,IACA,MCRO,sBACX,MACA,EAAE,QAAQ,iBAAiB,EAAE,MAAM,mBAChC;CACH,IAAM,aAAa,sBAAsB,MAAM,GAEzC,oBAAoB,EAAE,iBAC1B,CAAC,YAAY,SAAS,UAAU;CAIlC,OAFI,SAAS,YAEN,YAAY,SAAS,cAAc,EAAE,IAFd,KAAK,OAAO,gBAAgB,IAItD;AACN,GCba,kBAAA,GAAiBA,OAAAA,aAAAA,QACrB;CACL,MAAM;CACN,UAAU;EACR;EACA;CACF;AACF,EACD,GCJK,6BACJ,WACoB;CACpB,IAAI,CAAC,QAAQ,KAAK,CAAC,QAAQ,QAAQ,CAAC,OAAO,SACzC,MAAU,MACR,yIAEF;CAEF,IAAM,EAAE,GAAG,MAAM,OAAO,MAAM,IAAI,YAAY,QACxC,EAAE,WAAW;CAEnB,IAAI,CAAC,QACH,MAAU,MACR,6DACF;CAGF,IAAM,aAAa,OAAO,IAAI,IAAI,GAC5B,YAAY,SAAS,YAAY,SAAS,MAC1C,WAAW,QAAQ,YAAY,QAAQC,cAAAA,cACvC,SAAS,MAAM;CAErB,OAAO,EAAE,SAAS,CAAC,CAChB,MAAM,SAAS,CAAC,CAChB,KAAK,QAAQ,CAAC,CACd,MAAM,EAAE,SAAS,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,MAAM,SAAS,CAAC,CAAC,GAAG,MAAM,CAAC;AACpE,GAEM,8BACJ,WACsB;CACtB,IAAI,CAAC,OAAO,KAAK,CAAC,OAAO,SACvB,MAAU,MACR,mHAEF;CAGF,IAAM,EAAE,GAAG,YAAY,QACjB,EAAE,WAAW;CAInB,OAFmB,sBAAsB,MAG9B,CAAC,EAAE,KAAK,eACf,0BAA0B;EAAE;EAAG;EAAS,MAAM;CAAW,CAAC,CAC5D,KAAK,CAAC;AAEV,GAEM,6BACJ,WACsB;CACtB,IAAI,CAAC,OAAO,KAAK,CAAC,OAAO,SACvB,MAAU,MACR,iHAEF;CAEF,IAAM,EAAE,GAAG,YAAY,QACjB,EAAE,WAAW,SAEb,aAAa,sBAAsB,MAAM;CAE/C,OAAO,EAAE,sBAAsB,CAAC,CAAC,QAC9B,SAAS,CAAC,cAAc,CAAC,WAAW,SAAS,KAAK,MAAM,CAAW,CACtE;AACF"}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,19 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ListItemBuilder, StructureBuilder } from "sanity/structure";
|
|
2
|
+
import { ComponentType, ReactNode } from "react";
|
|
2
3
|
import { ConfigContext } from "sanity";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import { ReactNode } from "react";
|
|
6
|
-
import { StructureBuilder } from "sanity/structure";
|
|
7
|
-
|
|
8
|
-
export declare const filteredDocumentListItems: (
|
|
9
|
-
config: SingletonPluginListItemsConfig,
|
|
10
|
-
) => ListItemBuilder[];
|
|
11
|
-
|
|
12
|
-
export declare const singletonDocumentListItem: (
|
|
13
|
-
config: SingletonDocumentListItemConfig,
|
|
14
|
-
) => ListItemBuilder;
|
|
15
|
-
|
|
16
|
-
declare interface SingletonDocumentListItemConfig {
|
|
4
|
+
declare const singletonTools: import("sanity").Plugin<void>;
|
|
5
|
+
interface SingletonDocumentListItemConfig {
|
|
17
6
|
S: StructureBuilder;
|
|
18
7
|
context: ConfigContext;
|
|
19
8
|
type: string;
|
|
@@ -21,24 +10,18 @@ declare interface SingletonDocumentListItemConfig {
|
|
|
21
10
|
id?: string;
|
|
22
11
|
icon?: ComponentType | ReactNode;
|
|
23
12
|
}
|
|
24
|
-
|
|
25
|
-
export declare const singletonDocumentListItems: (
|
|
26
|
-
config: SingletonPluginListItemsConfig,
|
|
27
|
-
) => ListItemBuilder[];
|
|
28
|
-
|
|
29
|
-
declare interface SingletonPluginListItemsConfig {
|
|
13
|
+
interface SingletonPluginListItemsConfig {
|
|
30
14
|
S: StructureBuilder;
|
|
31
15
|
context: ConfigContext;
|
|
32
16
|
}
|
|
33
|
-
|
|
34
|
-
export declare interface SingletonPluginOptions {
|
|
17
|
+
interface SingletonPluginOptions {
|
|
35
18
|
singleton?: boolean;
|
|
36
19
|
}
|
|
37
|
-
|
|
38
|
-
export declare const singletonTools: Plugin_2<void>;
|
|
39
|
-
|
|
40
|
-
export {};
|
|
41
|
-
|
|
42
20
|
declare module "sanity" {
|
|
43
21
|
interface DocumentOptions extends SingletonPluginOptions {}
|
|
44
22
|
}
|
|
23
|
+
declare const singletonDocumentListItem: (config: SingletonDocumentListItemConfig) => ListItemBuilder;
|
|
24
|
+
declare const singletonDocumentListItems: (config: SingletonPluginListItemsConfig) => ListItemBuilder[];
|
|
25
|
+
declare const filteredDocumentListItems: (config: SingletonPluginListItemsConfig) => ListItemBuilder[];
|
|
26
|
+
export { type SingletonPluginOptions, filteredDocumentListItems, singletonDocumentListItem, singletonDocumentListItems, singletonTools };
|
|
27
|
+
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ConfigContext } from "sanity";
|
|
2
|
+
import { ListItemBuilder, StructureBuilder } from "sanity/structure";
|
|
3
|
+
import { ComponentType, ReactNode } from "react";
|
|
4
|
+
declare const singletonTools: import("sanity").Plugin<void>;
|
|
5
|
+
interface SingletonDocumentListItemConfig {
|
|
6
|
+
S: StructureBuilder;
|
|
7
|
+
context: ConfigContext;
|
|
8
|
+
type: string;
|
|
9
|
+
title?: string;
|
|
10
|
+
id?: string;
|
|
11
|
+
icon?: ComponentType | ReactNode;
|
|
12
|
+
}
|
|
13
|
+
interface SingletonPluginListItemsConfig {
|
|
14
|
+
S: StructureBuilder;
|
|
15
|
+
context: ConfigContext;
|
|
16
|
+
}
|
|
17
|
+
interface SingletonPluginOptions {
|
|
18
|
+
singleton?: boolean;
|
|
19
|
+
}
|
|
20
|
+
declare module "sanity" {
|
|
21
|
+
interface DocumentOptions extends SingletonPluginOptions {}
|
|
22
|
+
}
|
|
23
|
+
declare const singletonDocumentListItem: (config: SingletonDocumentListItemConfig) => ListItemBuilder;
|
|
24
|
+
declare const singletonDocumentListItems: (config: SingletonPluginListItemsConfig) => ListItemBuilder[];
|
|
25
|
+
declare const filteredDocumentListItems: (config: SingletonPluginListItemsConfig) => ListItemBuilder[];
|
|
26
|
+
export { type SingletonPluginOptions, filteredDocumentListItems, singletonDocumentListItem, singletonDocumentListItems, singletonTools };
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { definePlugin } from "sanity";
|
|
2
|
+
import { DocumentIcon } from "@sanity/icons";
|
|
3
|
+
const getSingletonDocuments = (schema) => {
|
|
4
|
+
if (schema?._original?.types) return schema._original.types.filter(({ options }) => options?.singleton).map((s) => s.name);
|
|
5
|
+
}, getIsSingleton = (schema, schemaType) => !schema?._original?.types || !schemaType ? !1 : schema._original.types.find(({ name }) => name === schemaType)?.options?.singleton ?? !1, actions = (prev, { schema, schemaType }) => getIsSingleton(schema, schemaType) ? prev.filter(({ action }) => [
|
|
6
|
+
"publish",
|
|
7
|
+
"discardChanges",
|
|
8
|
+
"restore"
|
|
9
|
+
].includes(action)) : prev, newDocumentOptions = (prev, { schema, creationContext: { type, schemaType } }) => {
|
|
10
|
+
let singletons = getSingletonDocuments(schema), filterSingletons = ({ templateId }) => !singletons?.includes(templateId);
|
|
11
|
+
return type === "global" || singletons?.includes(schemaType ?? "") ? prev.filter(filterSingletons) : prev;
|
|
12
|
+
}, singletonTools = definePlugin(() => ({
|
|
13
|
+
name: "singleton-tools",
|
|
14
|
+
document: {
|
|
15
|
+
newDocumentOptions,
|
|
16
|
+
actions
|
|
17
|
+
}
|
|
18
|
+
})), singletonDocumentListItem = (config) => {
|
|
19
|
+
if (!config?.S || !config?.type || !config.context) throw Error("S, context, and type must be provided to singletonDocumentListItem. Example: singletonDocumentListItem({ S, context, type: 'product' })");
|
|
20
|
+
let { S, type, title, icon, id, context } = config, { schema } = context;
|
|
21
|
+
if (!schema) throw Error("Schema is required in context for singletonDocumentListItem");
|
|
22
|
+
let schemaType = schema.get(type), listTitle = title ?? schemaType?.title ?? type, listIcon = icon ?? schemaType?.icon ?? DocumentIcon, listId = id ?? type;
|
|
23
|
+
return S.listItem().title(listTitle).icon(listIcon).child(S.document().schemaType(type).title(listTitle).id(listId));
|
|
24
|
+
}, singletonDocumentListItems = (config) => {
|
|
25
|
+
if (!config.S || !config.context) throw Error("S and context must be provided to singletonDocumentListItems. Example: singletonDocumentListItems({ S, context })");
|
|
26
|
+
let { S, context } = config, { schema } = context;
|
|
27
|
+
return getSingletonDocuments(schema)?.map((schemaType) => singletonDocumentListItem({
|
|
28
|
+
S,
|
|
29
|
+
context,
|
|
30
|
+
type: schemaType
|
|
31
|
+
})) || [];
|
|
32
|
+
}, filteredDocumentListItems = (config) => {
|
|
33
|
+
if (!config.S || !config.context) throw Error("S and context must be provided to filteredDocumentListItems. Example: filteredDocumentListItems({ S, context })");
|
|
34
|
+
let { S, context } = config, { schema } = context, singletons = getSingletonDocuments(schema);
|
|
35
|
+
return S.documentTypeListItems().filter((type) => !singletons || !singletons.includes(type.getId()));
|
|
36
|
+
};
|
|
37
|
+
export { filteredDocumentListItems, singletonDocumentListItem, singletonDocumentListItems, singletonTools };
|
|
38
|
+
|
|
39
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/helpers/index.ts","../src/actions.ts","../src/newDocumentOptions.ts","../src/pluginConfig.ts","../src/structure/index.ts"],"sourcesContent":["import { Schema } from \"sanity\";\n\nimport { SingletonPluginOptions } from \"../types\";\n\nexport const getSingletonDocuments = (schema: Schema): string[] | undefined => {\n if (!schema?._original?.types) {\n return undefined;\n }\n\n return schema._original.types\n .filter(({ options }) => (options as SingletonPluginOptions)?.singleton)\n .map((s: { name: string }) => s.name);\n};\n\nexport const getIsSingleton = (schema: Schema, schemaType: string): boolean => {\n if (!schema?._original?.types || !schemaType) {\n return false;\n }\n\n const documentSchema = schema._original.types.find(\n ({ name }) => name === schemaType,\n );\n\n return (\n (documentSchema?.options as SingletonPluginOptions)?.singleton ?? false\n );\n};\n","import { DocumentActionsContext, DocumentActionsResolver } from \"sanity\";\n\nimport { getIsSingleton } from \"./helpers\";\n\nexport const actions: DocumentActionsResolver = (\n prev,\n { schema, schemaType }: DocumentActionsContext,\n) => {\n return getIsSingleton(schema, schemaType)\n ? prev.filter(({ action }) =>\n [\"publish\", \"discardChanges\", \"restore\"].includes(action as string),\n )\n : prev;\n};\n","import { NewDocumentOptionsContext, NewDocumentOptionsResolver } from \"sanity\";\n\nimport { getSingletonDocuments } from \"./helpers\";\n\nexport const newDocumentOptions: NewDocumentOptionsResolver = (\n prev,\n { schema, creationContext: { type, schemaType } }: NewDocumentOptionsContext,\n) => {\n const singletons = getSingletonDocuments(schema);\n\n const filterSingletons = ({ templateId }: { templateId: string }) =>\n !singletons?.includes(templateId);\n\n if (type === \"global\") return prev.filter(filterSingletons);\n\n return singletons?.includes(schemaType ?? \"\")\n ? prev.filter(filterSingletons)\n : prev;\n};\n","import { definePlugin } from \"sanity\";\n\nimport { actions } from \"./actions\";\nimport { newDocumentOptions } from \"./newDocumentOptions\";\n\nexport const singletonTools = definePlugin(() => {\n return {\n name: \"singleton-tools\",\n document: {\n newDocumentOptions,\n actions,\n },\n };\n});\n","import { DocumentIcon } from \"@sanity/icons\";\nimport type { ListItemBuilder } from \"sanity/structure\";\n\nimport { getSingletonDocuments } from \"../helpers\";\nimport {\n SingletonDocumentListItemConfig,\n SingletonPluginListItemsConfig,\n} from \"../types\";\n\nconst singletonDocumentListItem = (\n config: SingletonDocumentListItemConfig,\n): ListItemBuilder => {\n if (!config?.S || !config?.type || !config.context) {\n throw new Error(\n \"S, context, and type must be provided to singletonDocumentListItem. \" +\n \"Example: singletonDocumentListItem({ S, context, type: 'product' })\",\n );\n }\n const { S, type, title, icon, id, context } = config;\n const { schema } = context;\n\n if (!schema) {\n throw new Error(\n \"Schema is required in context for singletonDocumentListItem\",\n );\n }\n\n const schemaType = schema.get(type);\n const listTitle = title ?? schemaType?.title ?? type;\n const listIcon = icon ?? schemaType?.icon ?? DocumentIcon;\n const listId = id ?? type;\n\n return S.listItem()\n .title(listTitle)\n .icon(listIcon)\n .child(S.document().schemaType(type).title(listTitle).id(listId));\n};\n\nconst singletonDocumentListItems = (\n config: SingletonPluginListItemsConfig,\n): ListItemBuilder[] => {\n if (!config.S || !config.context) {\n throw new Error(\n \"S and context must be provided to singletonDocumentListItems. \" +\n \"Example: singletonDocumentListItems({ S, context })\",\n );\n }\n\n const { S, context } = config;\n const { schema } = context;\n\n const singletons = getSingletonDocuments(schema);\n\n return (\n singletons?.map((schemaType) =>\n singletonDocumentListItem({ S, context, type: schemaType }),\n ) || []\n );\n};\n\nconst filteredDocumentListItems = (\n config: SingletonPluginListItemsConfig,\n): ListItemBuilder[] => {\n if (!config.S || !config.context) {\n throw new Error(\n \"S and context must be provided to filteredDocumentListItems. \" +\n \"Example: filteredDocumentListItems({ S, context })\",\n );\n }\n const { S, context } = config;\n const { schema } = context;\n\n const singletons = getSingletonDocuments(schema);\n\n return S.documentTypeListItems().filter(\n (type) => !singletons || !singletons.includes(type.getId() as string),\n );\n};\n\nexport {\n filteredDocumentListItems,\n singletonDocumentListItem,\n singletonDocumentListItems,\n};\n"],"mappings":";;AAIA,MAAa,yBAAyB,WAAyC;CACxE,YAAQ,WAAW,OAIxB,OAAO,OAAO,UAAU,MACrB,QAAQ,EAAE,cAAe,SAAoC,SAAS,CAAC,CACvE,KAAK,MAAwB,EAAE,IAAI;AACxC,GAEa,kBAAkB,QAAgB,eACzC,CAAC,QAAQ,WAAW,SAAS,CAAC,aACzB,KAGc,OAAO,UAAU,MAAM,MAC3C,EAAE,WAAW,SAAS,UAIT,CAAC,EAAE,SAAoC,aAAa,ICpBzD,WACX,MACA,EAAE,QAAQ,iBAEH,eAAe,QAAQ,UAAU,IACpC,KAAK,QAAQ,EAAE,aACb;CAAC;CAAW;CAAkB;AAAS,CAAC,CAAC,SAAS,MAAgB,CACpE,IACA,MCRO,sBACX,MACA,EAAE,QAAQ,iBAAiB,EAAE,MAAM,mBAChC;CACH,IAAM,aAAa,sBAAsB,MAAM,GAEzC,oBAAoB,EAAE,iBAC1B,CAAC,YAAY,SAAS,UAAU;CAIlC,OAFI,SAAS,YAEN,YAAY,SAAS,cAAc,EAAE,IAFd,KAAK,OAAO,gBAAgB,IAItD;AACN,GCba,iBAAiB,oBACrB;CACL,MAAM;CACN,UAAU;EACR;EACA;CACF;AACF,EACD,GCJK,6BACJ,WACoB;CACpB,IAAI,CAAC,QAAQ,KAAK,CAAC,QAAQ,QAAQ,CAAC,OAAO,SACzC,MAAU,MACR,yIAEF;CAEF,IAAM,EAAE,GAAG,MAAM,OAAO,MAAM,IAAI,YAAY,QACxC,EAAE,WAAW;CAEnB,IAAI,CAAC,QACH,MAAU,MACR,6DACF;CAGF,IAAM,aAAa,OAAO,IAAI,IAAI,GAC5B,YAAY,SAAS,YAAY,SAAS,MAC1C,WAAW,QAAQ,YAAY,QAAQ,cACvC,SAAS,MAAM;CAErB,OAAO,EAAE,SAAS,CAAC,CAChB,MAAM,SAAS,CAAC,CAChB,KAAK,QAAQ,CAAC,CACd,MAAM,EAAE,SAAS,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,MAAM,SAAS,CAAC,CAAC,GAAG,MAAM,CAAC;AACpE,GAEM,8BACJ,WACsB;CACtB,IAAI,CAAC,OAAO,KAAK,CAAC,OAAO,SACvB,MAAU,MACR,mHAEF;CAGF,IAAM,EAAE,GAAG,YAAY,QACjB,EAAE,WAAW;CAInB,OAFmB,sBAAsB,MAG9B,CAAC,EAAE,KAAK,eACf,0BAA0B;EAAE;EAAG;EAAS,MAAM;CAAW,CAAC,CAC5D,KAAK,CAAC;AAEV,GAEM,6BACJ,WACsB;CACtB,IAAI,CAAC,OAAO,KAAK,CAAC,OAAO,SACvB,MAAU,MACR,iHAEF;CAEF,IAAM,EAAE,GAAG,YAAY,QACjB,EAAE,WAAW,SAEb,aAAa,sBAAsB,MAAM;CAE/C,OAAO,EAAE,sBAAsB,CAAC,CAAC,QAC9B,SAAS,CAAC,cAAc,CAAC,WAAW,SAAS,KAAK,MAAM,CAAW,CACtE;AACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sanity-plugin-singleton-management",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "A plugin to streamline singleton management in your Sanity Studio",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -14,16 +14,16 @@
|
|
|
14
14
|
"exports": {
|
|
15
15
|
".": {
|
|
16
16
|
"source": "./src/index.ts",
|
|
17
|
-
"import": "./dist/index.
|
|
17
|
+
"import": "./dist/index.js",
|
|
18
18
|
"require": "./dist/index.cjs",
|
|
19
|
-
"default": "./dist/index.
|
|
19
|
+
"default": "./dist/index.js"
|
|
20
20
|
},
|
|
21
21
|
"./package.json": "./package.json"
|
|
22
22
|
},
|
|
23
23
|
"type": "module",
|
|
24
24
|
"main": "./dist/index.cjs",
|
|
25
|
-
"module": "./dist/index.
|
|
26
|
-
"types": "./dist/index.
|
|
25
|
+
"module": "./dist/index.js",
|
|
26
|
+
"types": "./dist/index.d.cts",
|
|
27
27
|
"browserslist": "extends @sanity/browserslist-config",
|
|
28
28
|
"files": [
|
|
29
29
|
"dist",
|
|
@@ -49,61 +49,81 @@
|
|
|
49
49
|
"test:coverage": "vitest run --coverage"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@sanity/icons": "^
|
|
52
|
+
"@sanity/icons": "^5.2.1",
|
|
53
53
|
"@sanity/incompatible-plugin": "^1.0.5"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@
|
|
57
|
-
"@
|
|
58
|
-
"@commitlint/
|
|
56
|
+
"@emnapi/core": "^1.11.3",
|
|
57
|
+
"@emnapi/runtime": "^1.11.3",
|
|
58
|
+
"@commitlint/cli": "^21.2.2",
|
|
59
|
+
"@commitlint/config-conventional": "^21.2.2",
|
|
60
|
+
"@commitlint/prompt-cli": "^21.2.2",
|
|
61
|
+
"@eslint-react/eslint-plugin": "^5.18.6",
|
|
62
|
+
"@eslint/js": "^10.0.1",
|
|
59
63
|
"@sanity/browserslist-config": "^1.0.5",
|
|
60
|
-
"@sanity/pkg-utils": "^
|
|
61
|
-
"@sanity/plugin-kit": "^
|
|
62
|
-
"@semantic-release/changelog": "^
|
|
63
|
-
"@semantic-release/git": "^
|
|
64
|
-
"@semantic-release/github": "^
|
|
65
|
-
"@semantic-release/npm": "^13.1.
|
|
66
|
-
"@testing-library/jest-dom": "^
|
|
67
|
-
"@types/react": "^19.2.
|
|
68
|
-
"@
|
|
69
|
-
"@
|
|
70
|
-
"
|
|
71
|
-
"@vitest/ui": "^4.0.1",
|
|
72
|
-
"eslint": "^9.35.0",
|
|
64
|
+
"@sanity/pkg-utils": "^12.1.2",
|
|
65
|
+
"@sanity/plugin-kit": "^10.0.5",
|
|
66
|
+
"@semantic-release/changelog": "^7.0.0",
|
|
67
|
+
"@semantic-release/git": "^11.0.1",
|
|
68
|
+
"@semantic-release/github": "^12.0.9",
|
|
69
|
+
"@semantic-release/npm": "^13.1.5",
|
|
70
|
+
"@testing-library/jest-dom": "^7.0.1",
|
|
71
|
+
"@types/react": "^19.2.18",
|
|
72
|
+
"@vitest/coverage-v8": "^4.1.10",
|
|
73
|
+
"@vitest/ui": "^4.1.10",
|
|
74
|
+
"eslint": "^10.8.1",
|
|
73
75
|
"eslint-config-prettier": "^10.1.8",
|
|
74
|
-
"eslint-
|
|
75
|
-
"eslint-plugin-prettier": "^5.1.3",
|
|
76
|
-
"eslint-plugin-react": "^7.34.0",
|
|
77
|
-
"eslint-plugin-react-hooks": "^7.0.0",
|
|
76
|
+
"eslint-plugin-react-hooks": "7.1.1",
|
|
78
77
|
"husky": "^9.1.7",
|
|
79
|
-
"jsdom": "^27.0.0",
|
|
80
78
|
"npm-run-all": "^4.1.5",
|
|
81
|
-
"prettier": "^3.
|
|
82
|
-
"prettier-plugin-packagejson": "^
|
|
83
|
-
"react": "^19.2.
|
|
84
|
-
"react-dom": "^19.2.
|
|
85
|
-
"react-is": "^19.2.
|
|
86
|
-
"rimraf": "^6.
|
|
87
|
-
"sanity": "^
|
|
88
|
-
"semantic-release": "^25.0.
|
|
89
|
-
"styled-components": "^6.
|
|
90
|
-
"typescript": "^
|
|
91
|
-
"typescript-eslint": "^8.
|
|
92
|
-
"vitest": "^4.
|
|
79
|
+
"prettier": "^3.9.6",
|
|
80
|
+
"prettier-plugin-packagejson": "^3.0.2",
|
|
81
|
+
"react": "^19.2.8",
|
|
82
|
+
"react-dom": "^19.2.8",
|
|
83
|
+
"react-is": "^19.2.8",
|
|
84
|
+
"rimraf": "^6.1.3",
|
|
85
|
+
"sanity": "^6.9.2",
|
|
86
|
+
"semantic-release": "^25.0.9",
|
|
87
|
+
"styled-components": "^6.5.3",
|
|
88
|
+
"typescript": "^6.0.3",
|
|
89
|
+
"typescript-eslint": "^8.67.0",
|
|
90
|
+
"vitest": "^4.1.10"
|
|
93
91
|
},
|
|
94
92
|
"overrides": {
|
|
95
93
|
"esbuild": "0.25.0",
|
|
96
94
|
"prismjs": "1.30.0",
|
|
97
95
|
"tmp": "0.2.4",
|
|
98
96
|
"min-document": "2.19.0",
|
|
99
|
-
"
|
|
97
|
+
"minimatch": "^10.2.1",
|
|
98
|
+
"serialize-javascript": "^7.0.3",
|
|
99
|
+
"glob": "^10.5.0",
|
|
100
|
+
"flatted": "^3.4.2",
|
|
101
|
+
"js-yaml": "^3.14.2",
|
|
102
|
+
"ajv": "^8.18.0",
|
|
103
|
+
"lodash": "^4.18.0",
|
|
104
|
+
"brace-expansion": "^5.0.9",
|
|
105
|
+
"picomatch": "^4.0.4",
|
|
106
|
+
"smol-toml": "^1.6.1",
|
|
107
|
+
"typescript": "^6.0.3",
|
|
108
|
+
"typeid-js": {
|
|
109
|
+
"uuid": "^11.1.1"
|
|
110
|
+
},
|
|
111
|
+
"eslint": {
|
|
112
|
+
"ajv": "^6.14.0"
|
|
113
|
+
},
|
|
114
|
+
"@module-federation/dts-plugin": {
|
|
115
|
+
"undici": "^7.29.0"
|
|
116
|
+
},
|
|
117
|
+
"@sanity/pkg-utils": {
|
|
118
|
+
"typescript": "^6.0.3"
|
|
119
|
+
}
|
|
100
120
|
},
|
|
101
121
|
"peerDependencies": {
|
|
102
122
|
"react": "^18 || ^19.2.1",
|
|
103
|
-
"sanity": "^3 || ^4 || ^5.0.0-0"
|
|
123
|
+
"sanity": "^3 || ^4 || ^5.0.0-0 || ^6"
|
|
104
124
|
},
|
|
105
125
|
"engines": {
|
|
106
|
-
"node": ">=
|
|
126
|
+
"node": ">=24"
|
|
107
127
|
},
|
|
108
128
|
"repository": {
|
|
109
129
|
"type": "git",
|
|
@@ -113,9 +133,9 @@
|
|
|
113
133
|
"publishConfig": {
|
|
114
134
|
"exports": {
|
|
115
135
|
".": {
|
|
116
|
-
"import": "./dist/index.
|
|
136
|
+
"import": "./dist/index.js",
|
|
117
137
|
"require": "./dist/index.cjs",
|
|
118
|
-
"default": "./dist/index.
|
|
138
|
+
"default": "./dist/index.js"
|
|
119
139
|
},
|
|
120
140
|
"./package.json": "./package.json"
|
|
121
141
|
}
|
package/dist/index.esm.d.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { ComponentType } from "react";
|
|
2
|
-
import { ConfigContext } from "sanity";
|
|
3
|
-
import type { ListItemBuilder } from "sanity/structure";
|
|
4
|
-
import { Plugin as Plugin_2 } from "sanity";
|
|
5
|
-
import { ReactNode } from "react";
|
|
6
|
-
import { StructureBuilder } from "sanity/structure";
|
|
7
|
-
|
|
8
|
-
export declare const filteredDocumentListItems: (
|
|
9
|
-
config: SingletonPluginListItemsConfig,
|
|
10
|
-
) => ListItemBuilder[];
|
|
11
|
-
|
|
12
|
-
export declare const singletonDocumentListItem: (
|
|
13
|
-
config: SingletonDocumentListItemConfig,
|
|
14
|
-
) => ListItemBuilder;
|
|
15
|
-
|
|
16
|
-
declare interface SingletonDocumentListItemConfig {
|
|
17
|
-
S: StructureBuilder;
|
|
18
|
-
context: ConfigContext;
|
|
19
|
-
type: string;
|
|
20
|
-
title?: string;
|
|
21
|
-
id?: string;
|
|
22
|
-
icon?: ComponentType | ReactNode;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export declare const singletonDocumentListItems: (
|
|
26
|
-
config: SingletonPluginListItemsConfig,
|
|
27
|
-
) => ListItemBuilder[];
|
|
28
|
-
|
|
29
|
-
declare interface SingletonPluginListItemsConfig {
|
|
30
|
-
S: StructureBuilder;
|
|
31
|
-
context: ConfigContext;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export declare interface SingletonPluginOptions {
|
|
35
|
-
singleton?: boolean;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export declare const singletonTools: Plugin_2<void>;
|
|
39
|
-
|
|
40
|
-
export {};
|
|
41
|
-
|
|
42
|
-
declare module "sanity" {
|
|
43
|
-
interface DocumentOptions extends SingletonPluginOptions {}
|
|
44
|
-
}
|
package/dist/index.esm.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { definePlugin } from "sanity";
|
|
2
|
-
import { DocumentIcon } from "@sanity/icons";
|
|
3
|
-
const getSingletonDocuments = (schema) => {
|
|
4
|
-
if (schema?._original?.types)
|
|
5
|
-
return schema._original.types.filter(({ options }) => options?.singleton).map((s) => s.name);
|
|
6
|
-
}, getIsSingleton = (schema, schemaType) => !schema?._original?.types || !schemaType ? !1 : schema._original.types.find(
|
|
7
|
-
({ name }) => name === schemaType
|
|
8
|
-
)?.options?.singleton ?? !1, actions = (prev, { schema, schemaType }) => getIsSingleton(schema, schemaType) ? prev.filter(
|
|
9
|
-
({ action }) => ["publish", "discardChanges", "restore"].includes(action)
|
|
10
|
-
) : prev, newDocumentOptions = (prev, { schema, creationContext: { type, schemaType } }) => {
|
|
11
|
-
const singletons = getSingletonDocuments(schema), filterSingletons = ({ templateId }) => !singletons?.includes(templateId);
|
|
12
|
-
return type === "global" || singletons?.includes(schemaType ?? "") ? prev.filter(filterSingletons) : prev;
|
|
13
|
-
}, singletonTools = definePlugin(() => ({
|
|
14
|
-
name: "singleton-tools",
|
|
15
|
-
document: {
|
|
16
|
-
newDocumentOptions,
|
|
17
|
-
actions
|
|
18
|
-
}
|
|
19
|
-
})), singletonDocumentListItem = (config) => {
|
|
20
|
-
if (!config?.S || !config?.type || !config.context)
|
|
21
|
-
throw new Error(
|
|
22
|
-
"S, context, and type must be provided to singletonDocumentListItem. Example: singletonDocumentListItem({ S, context, type: 'product' })"
|
|
23
|
-
);
|
|
24
|
-
const { S, type, title, icon, id, context } = config, { schema } = context;
|
|
25
|
-
if (!schema)
|
|
26
|
-
throw new Error(
|
|
27
|
-
"Schema is required in context for singletonDocumentListItem"
|
|
28
|
-
);
|
|
29
|
-
const schemaType = schema.get(type), listTitle = title ?? schemaType?.title ?? type, listIcon = icon ?? schemaType?.icon ?? DocumentIcon, listId = id ?? type;
|
|
30
|
-
return S.listItem().title(listTitle).icon(listIcon).child(S.document().schemaType(type).title(listTitle).id(listId));
|
|
31
|
-
}, singletonDocumentListItems = (config) => {
|
|
32
|
-
if (!config.S || !config.context)
|
|
33
|
-
throw new Error(
|
|
34
|
-
"S and context must be provided to singletonDocumentListItems. Example: singletonDocumentListItems({ S, context })"
|
|
35
|
-
);
|
|
36
|
-
const { S, context } = config, { schema } = context;
|
|
37
|
-
return getSingletonDocuments(schema)?.map(
|
|
38
|
-
(schemaType) => singletonDocumentListItem({ S, context, type: schemaType })
|
|
39
|
-
) || [];
|
|
40
|
-
}, filteredDocumentListItems = (config) => {
|
|
41
|
-
if (!config.S || !config.context)
|
|
42
|
-
throw new Error(
|
|
43
|
-
"S and context must be provided to filteredDocumentListItems. Example: filteredDocumentListItems({ S, context })"
|
|
44
|
-
);
|
|
45
|
-
const { S, context } = config, { schema } = context, singletons = getSingletonDocuments(schema);
|
|
46
|
-
return S.documentTypeListItems().filter(
|
|
47
|
-
(type) => !singletons || !singletons.includes(type.getId())
|
|
48
|
-
);
|
|
49
|
-
};
|
|
50
|
-
export {
|
|
51
|
-
filteredDocumentListItems,
|
|
52
|
-
singletonDocumentListItem,
|
|
53
|
-
singletonDocumentListItems,
|
|
54
|
-
singletonTools
|
|
55
|
-
};
|
|
56
|
-
//# sourceMappingURL=index.esm.js.map
|
package/dist/index.esm.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../src/helpers/index.ts","../src/actions.ts","../src/newDocumentOptions.ts","../src/pluginConfig.ts","../src/structure/index.ts"],"sourcesContent":["import { Schema } from \"sanity\";\n\nimport { SingletonPluginOptions } from \"../types\";\n\nexport const getSingletonDocuments = (schema: Schema): string[] | undefined => {\n if (!schema?._original?.types) {\n return undefined;\n }\n\n return schema._original.types\n .filter(({ options }) => (options as SingletonPluginOptions)?.singleton)\n .map((s: { name: string }) => s.name);\n};\n\nexport const getIsSingleton = (schema: Schema, schemaType: string): boolean => {\n if (!schema?._original?.types || !schemaType) {\n return false;\n }\n\n const documentSchema = schema._original.types.find(\n ({ name }) => name === schemaType,\n );\n\n return (\n (documentSchema?.options as SingletonPluginOptions)?.singleton ?? false\n );\n};\n","import { DocumentActionsContext, DocumentActionsResolver } from \"sanity\";\n\nimport { getIsSingleton } from \"./helpers\";\n\nexport const actions: DocumentActionsResolver = (\n prev,\n { schema, schemaType }: DocumentActionsContext,\n) => {\n return getIsSingleton(schema, schemaType)\n ? prev.filter(({ action }) =>\n [\"publish\", \"discardChanges\", \"restore\"].includes(action as string),\n )\n : prev;\n};\n","import { NewDocumentOptionsContext, NewDocumentOptionsResolver } from \"sanity\";\n\nimport { getSingletonDocuments } from \"./helpers\";\n\nexport const newDocumentOptions: NewDocumentOptionsResolver = (\n prev,\n { schema, creationContext: { type, schemaType } }: NewDocumentOptionsContext,\n) => {\n const singletons = getSingletonDocuments(schema);\n\n const filterSingletons = ({ templateId }: { templateId: string }) =>\n !singletons?.includes(templateId);\n\n if (type === \"global\") return prev.filter(filterSingletons);\n\n return singletons?.includes(schemaType ?? \"\")\n ? prev.filter(filterSingletons)\n : prev;\n};\n","import { definePlugin } from \"sanity\";\n\nimport { actions } from \"./actions\";\nimport { newDocumentOptions } from \"./newDocumentOptions\";\n\nexport const singletonTools = definePlugin(() => {\n return {\n name: \"singleton-tools\",\n document: {\n newDocumentOptions,\n actions,\n },\n };\n});\n","import { DocumentIcon } from \"@sanity/icons\";\nimport type { ListItemBuilder } from \"sanity/structure\";\n\nimport { getSingletonDocuments } from \"../helpers\";\nimport {\n SingletonDocumentListItemConfig,\n SingletonPluginListItemsConfig,\n} from \"../types\";\n\nconst singletonDocumentListItem = (\n config: SingletonDocumentListItemConfig,\n): ListItemBuilder => {\n if (!config?.S || !config?.type || !config.context) {\n throw new Error(\n \"S, context, and type must be provided to singletonDocumentListItem. \" +\n \"Example: singletonDocumentListItem({ S, context, type: 'product' })\",\n );\n }\n const { S, type, title, icon, id, context } = config;\n const { schema } = context;\n\n if (!schema) {\n throw new Error(\n \"Schema is required in context for singletonDocumentListItem\",\n );\n }\n\n const schemaType = schema.get(type);\n const listTitle = title ?? schemaType?.title ?? type;\n const listIcon = icon ?? schemaType?.icon ?? DocumentIcon;\n const listId = id ?? type;\n\n return S.listItem()\n .title(listTitle)\n .icon(listIcon)\n .child(S.document().schemaType(type).title(listTitle).id(listId));\n};\n\nconst singletonDocumentListItems = (\n config: SingletonPluginListItemsConfig,\n): ListItemBuilder[] => {\n if (!config.S || !config.context) {\n throw new Error(\n \"S and context must be provided to singletonDocumentListItems. \" +\n \"Example: singletonDocumentListItems({ S, context })\",\n );\n }\n\n const { S, context } = config;\n const { schema } = context;\n\n const singletons = getSingletonDocuments(schema);\n\n return (\n singletons?.map((schemaType) =>\n singletonDocumentListItem({ S, context, type: schemaType }),\n ) || []\n );\n};\n\nconst filteredDocumentListItems = (\n config: SingletonPluginListItemsConfig,\n): ListItemBuilder[] => {\n if (!config.S || !config.context) {\n throw new Error(\n \"S and context must be provided to filteredDocumentListItems. \" +\n \"Example: filteredDocumentListItems({ S, context })\",\n );\n }\n const { S, context } = config;\n const { schema } = context;\n\n const singletons = getSingletonDocuments(schema);\n\n return S.documentTypeListItems().filter(\n (type) => !singletons || !singletons.includes(type.getId() as string),\n );\n};\n\nexport {\n filteredDocumentListItems,\n singletonDocumentListItem,\n singletonDocumentListItems,\n};\n"],"names":[],"mappings":";;AAIO,MAAM,wBAAwB,CAAC,WAAyC;AAC7E,MAAK,QAAQ,WAAW;AAIxB,WAAO,OAAO,UAAU,MACrB,OAAO,CAAC,EAAE,QAAA,MAAe,SAAoC,SAAS,EACtE,IAAI,CAAC,MAAwB,EAAE,IAAI;AACxC,GAEa,iBAAiB,CAAC,QAAgB,eACzC,CAAC,QAAQ,WAAW,SAAS,CAAC,aACzB,KAGc,OAAO,UAAU,MAAM;AAAA,EAC5C,CAAC,EAAE,KAAA,MAAW,SAAS;AACzB,GAGmB,SAAoC,aAAa,ICpBzD,UAAmC,CAC9C,MACA,EAAE,QAAQ,WAAA,MAEH,eAAe,QAAQ,UAAU,IACpC,KAAK;AAAA,EAAO,CAAC,EAAE,OAAA,MACb,CAAC,WAAW,kBAAkB,SAAS,EAAE,SAAS,MAAgB;AACpE,IACA,MCRO,qBAAiD,CAC5D,MACA,EAAE,QAAQ,iBAAiB,EAAE,MAAM,WAAA,QAChC;AACH,QAAM,aAAa,sBAAsB,MAAM,GAEzC,mBAAmB,CAAC,EAAE,iBAC1B,CAAC,YAAY,SAAS,UAAU;AAElC,SAAI,SAAS,YAEN,YAAY,SAAS,cAAc,EAAE,IAFd,KAAK,OAAO,gBAAgB,IAItD;AACN,GCba,iBAAiB,aAAa,OAClC;AAAA,EACL,MAAM;AAAA,EACN,UAAU;AAAA,IACR;AAAA,IACA;AAAA,EAAA;AAEJ,EACD,GCJK,4BAA4B,CAChC,WACoB;AACpB,MAAI,CAAC,QAAQ,KAAK,CAAC,QAAQ,QAAQ,CAAC,OAAO;AACzC,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAIJ,QAAM,EAAE,GAAG,MAAM,OAAO,MAAM,IAAI,YAAY,QACxC,EAAE,OAAA,IAAW;AAEnB,MAAI,CAAC;AACH,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAIJ,QAAM,aAAa,OAAO,IAAI,IAAI,GAC5B,YAAY,SAAS,YAAY,SAAS,MAC1C,WAAW,QAAQ,YAAY,QAAQ,cACvC,SAAS,MAAM;AAErB,SAAO,EAAE,WACN,MAAM,SAAS,EACf,KAAK,QAAQ,EACb,MAAM,EAAE,SAAA,EAAW,WAAW,IAAI,EAAE,MAAM,SAAS,EAAE,GAAG,MAAM,CAAC;AACpE,GAEM,6BAA6B,CACjC,WACsB;AACtB,MAAI,CAAC,OAAO,KAAK,CAAC,OAAO;AACvB,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAKJ,QAAM,EAAE,GAAG,QAAA,IAAY,QACjB,EAAE,WAAW;AAInB,SAFmB,sBAAsB,MAAM,GAGjC;AAAA,IAAI,CAAC,eACf,0BAA0B,EAAE,GAAG,SAAS,MAAM,YAAY;AAAA,EAAA,KACvD,CAAA;AAET,GAEM,4BAA4B,CAChC,WACsB;AACtB,MAAI,CAAC,OAAO,KAAK,CAAC,OAAO;AACvB,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAIJ,QAAM,EAAE,GAAG,QAAA,IAAY,QACjB,EAAE,OAAA,IAAW,SAEb,aAAa,sBAAsB,MAAM;AAE/C,SAAO,EAAE,wBAAwB;AAAA,IAC/B,CAAC,SAAS,CAAC,cAAc,CAAC,WAAW,SAAS,KAAK,MAAA,CAAiB;AAAA,EAAA;AAExE;"}
|