@dyrected/knowledge 0.2.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/LICENSE.md +50 -0
- package/README.md +17 -0
- package/dist/index.d.ts +78 -0
- package/dist/index.js +2776 -0
- package/generated/SKILL.md +276 -0
- package/generated/ai-rules.md +152 -0
- package/generated/endpoints.json +891 -0
- package/generated/examples-inventory.json +3558 -0
- package/generated/intent-index.json +46 -0
- package/generated/llms-index.json +812 -0
- package/generated/openapi.json +1643 -0
- package/generated/recipes.json +224 -0
- package/generated/references.json +1573 -0
- package/package.json +56 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "auto-slug",
|
|
4
|
+
"title": "Generate a slug from a title",
|
|
5
|
+
"description": "Generate stable URL slugs on the server while showing editors the value live in the Admin UI.",
|
|
6
|
+
"category": "data-lifecycle",
|
|
7
|
+
"intents": [
|
|
8
|
+
"make the URL follow the title",
|
|
9
|
+
"automatically generate a slug",
|
|
10
|
+
"create friendly URLs from titles",
|
|
11
|
+
"keep a slug synchronized with a title"
|
|
12
|
+
],
|
|
13
|
+
"concepts": [
|
|
14
|
+
"beforeChange",
|
|
15
|
+
"admin.hooks.onChange",
|
|
16
|
+
"promoted",
|
|
17
|
+
"unique"
|
|
18
|
+
],
|
|
19
|
+
"requires": [],
|
|
20
|
+
"source": "import { defineCollection } from \"@dyrected/core\";\n\nexport const toSlug = (value: unknown) =>\n String(value ?? \"\")\n .toLowerCase()\n .trim()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/(^-|-$)/g, \"\");\n\nexport const Posts = defineCollection({\n slug: \"posts\",\n hooks: {\n beforeChange: [\n ({ data, operation }) => {\n if (operation === \"create\" || data.title !== undefined) {\n return { ...data, slug: toSlug(data.title) };\n }\n return data;\n },\n ],\n },\n fields: [\n { name: \"title\", type: \"text\", label: \"Title\", required: true },\n {\n name: \"slug\",\n type: \"text\",\n label: \"Slug\",\n required: true,\n unique: true,\n promoted: true,\n admin: {\n hooks: {\n onChange: ({ siblingData }) => toSlug(siblingData.title),\n },\n },\n },\n ],\n});",
|
|
21
|
+
"docsPath": "/docs/recipes/auto-slug"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"id": "conditional-admin-field",
|
|
25
|
+
"title": "Show an Admin field only when it is relevant",
|
|
26
|
+
"description": "Use a serializable Admin condition to reveal a field from the editor's current form values.",
|
|
27
|
+
"category": "admin-experience",
|
|
28
|
+
"intents": [
|
|
29
|
+
"show a field conditionally",
|
|
30
|
+
"hide irrelevant form fields",
|
|
31
|
+
"show discount only with a coupon",
|
|
32
|
+
"make the admin form react to another field"
|
|
33
|
+
],
|
|
34
|
+
"concepts": [
|
|
35
|
+
"admin.condition",
|
|
36
|
+
"Jexl",
|
|
37
|
+
"conditional fields"
|
|
38
|
+
],
|
|
39
|
+
"requires": [],
|
|
40
|
+
"source": "import { defineCollection } from \"@dyrected/core\";\n\nexport const Orders = defineCollection({\n slug: \"orders\",\n fields: [\n { name: \"couponCode\", type: \"text\", label: \"Coupon code\" },\n {\n name: \"discountPercent\",\n type: \"number\",\n label: \"Discount percentage\",\n admin: { condition: \"couponCode != null && couponCode != ''\" },\n },\n ],\n});",
|
|
41
|
+
"docsPath": "/docs/recipes/conditional-admin-field"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"id": "cross-field-validation",
|
|
45
|
+
"title": "Validate related fields before saving",
|
|
46
|
+
"description": "Reject invalid combinations of field values before they reach the database.",
|
|
47
|
+
"category": "data-lifecycle",
|
|
48
|
+
"intents": [
|
|
49
|
+
"validate fields before saving",
|
|
50
|
+
"make sure an end date is after the start date",
|
|
51
|
+
"reject invalid form submissions",
|
|
52
|
+
"validate multiple fields together"
|
|
53
|
+
],
|
|
54
|
+
"concepts": [
|
|
55
|
+
"beforeChange",
|
|
56
|
+
"validation",
|
|
57
|
+
"throw to abort"
|
|
58
|
+
],
|
|
59
|
+
"requires": [],
|
|
60
|
+
"source": "import { defineCollection } from \"@dyrected/core\";\n\nexport const Events = defineCollection({\n slug: \"events\",\n hooks: {\n beforeChange: [\n ({ data, doc }) => {\n const startsAt = data.startsAt ?? doc?.startsAt;\n const endsAt = data.endsAt ?? doc?.endsAt;\n\n const start = startsAt ? new Date(startsAt) : undefined;\n const end = endsAt ? new Date(endsAt) : undefined;\n\n if (start && Number.isNaN(start.getTime())) {\n throw new Error(\"The event start time must be a valid date.\");\n }\n if (end && Number.isNaN(end.getTime())) {\n throw new Error(\"The event end time must be a valid date.\");\n }\n if (start && end && end <= start) {\n throw new Error(\"The event end time must be after its start time.\");\n }\n\n return data;\n },\n ],\n },\n fields: [\n { name: \"title\", type: \"text\", label: \"Title\", required: true },\n {\n name: \"startsAt\",\n type: \"datetime\",\n label: \"Starts at\",\n required: true,\n },\n {\n name: \"endsAt\",\n type: \"datetime\",\n label: \"Ends at\",\n required: true,\n },\n ],\n});",
|
|
61
|
+
"docsPath": "/docs/recipes/cross-field-validation"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"id": "dependent-dropdown",
|
|
65
|
+
"title": "Update a dropdown from another field",
|
|
66
|
+
"description": "Change available Admin UI options immediately when an editor changes a related field.",
|
|
67
|
+
"category": "admin-experience",
|
|
68
|
+
"intents": [
|
|
69
|
+
"make one dropdown depend on another",
|
|
70
|
+
"show states based on the selected country",
|
|
71
|
+
"create a cascading dropdown",
|
|
72
|
+
"update select options while editing"
|
|
73
|
+
],
|
|
74
|
+
"concepts": [
|
|
75
|
+
"admin.hooks.options",
|
|
76
|
+
"select",
|
|
77
|
+
"siblingData"
|
|
78
|
+
],
|
|
79
|
+
"requires": [],
|
|
80
|
+
"source": "import { defineCollection } from \"@dyrected/core\";\n\nexport const Locations = defineCollection({\n slug: \"locations\",\n fields: [\n {\n name: \"country\",\n type: \"select\",\n label: \"Country\",\n required: true,\n options: [\n { label: \"Nigeria\", value: \"ng\" },\n { label: \"United States\", value: \"us\" },\n ],\n },\n {\n name: \"region\",\n type: \"select\",\n label: \"State or region\",\n required: true,\n options: [],\n admin: {\n hooks: {\n options: ({ siblingData }) => {\n if (siblingData.country === \"ng\") return [\"Lagos\", \"Abuja\", \"Oyo\"];\n if (siblingData.country === \"us\")\n return [\"California\", \"New York\", \"Texas\"];\n return [];\n },\n },\n },\n },\n ],\n});",
|
|
81
|
+
"docsPath": "/docs/recipes/dependent-dropdown"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"id": "editorial-publishing-workflow",
|
|
85
|
+
"title": "Add draft, review, and publishing states",
|
|
86
|
+
"description": "Attach Dyrected's standard editorial workflow and its capability-aware transitions to a collection.",
|
|
87
|
+
"category": "workflows",
|
|
88
|
+
"intents": [
|
|
89
|
+
"add draft and publish states",
|
|
90
|
+
"require review before publishing",
|
|
91
|
+
"create an editorial workflow",
|
|
92
|
+
"let editors submit content for approval"
|
|
93
|
+
],
|
|
94
|
+
"concepts": [
|
|
95
|
+
"publishingWorkflow",
|
|
96
|
+
"workflow transitions",
|
|
97
|
+
"capabilities"
|
|
98
|
+
],
|
|
99
|
+
"requires": [],
|
|
100
|
+
"source": "import { defineCollection, publishingWorkflow } from \"@dyrected/core\";\n\nexport const Posts = defineCollection({\n slug: \"posts\",\n workflow: publishingWorkflow(),\n fields: [\n { name: \"title\", type: \"text\", label: \"Title\", required: true },\n { name: \"body\", type: \"richText\", label: \"Body\", required: true },\n ],\n});",
|
|
101
|
+
"docsPath": "/docs/recipes/editorial-publishing-workflow"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"id": "owner-scoped-access",
|
|
105
|
+
"title": "Limit documents to their owner",
|
|
106
|
+
"description": "Return a where constraint from access control so authenticated users only read their own records.",
|
|
107
|
+
"category": "access-control",
|
|
108
|
+
"intents": [
|
|
109
|
+
"users should only see their own records",
|
|
110
|
+
"add row level access",
|
|
111
|
+
"scope documents by owner",
|
|
112
|
+
"prevent users reading another user's data"
|
|
113
|
+
],
|
|
114
|
+
"concepts": [
|
|
115
|
+
"access.read",
|
|
116
|
+
"where",
|
|
117
|
+
"row-level access"
|
|
118
|
+
],
|
|
119
|
+
"requires": [],
|
|
120
|
+
"source": "import { defineCollection } from \"@dyrected/core\";\n\nexport const Projects = defineCollection({\n slug: \"projects\",\n access: {\n read: ({ user }) => (user ? { owner: { equals: user.sub } } : false),\n create: ({ user }) => Boolean(user),\n update: ({ user }) => (user ? { owner: { equals: user.sub } } : false),\n delete: ({ user }) => (user ? { owner: { equals: user.sub } } : false),\n },\n hooks: {\n beforeChange: [\n ({ data, operation, user }) => {\n if (operation !== \"create\") return data;\n if (!user) throw new Error(\"Authentication is required to create a project.\");\n return { ...data, owner: user.sub };\n },\n ],\n },\n fields: [\n { name: \"name\", type: \"text\", label: \"Project name\", required: true },\n {\n name: \"owner\",\n type: \"relationship\",\n label: \"Owner\",\n relationTo: \"users\",\n required: true,\n admin: { readOnly: true },\n },\n ],\n});",
|
|
121
|
+
"docsPath": "/docs/recipes/owner-scoped-access"
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"id": "page-builder-blocks",
|
|
125
|
+
"title": "Build flexible pages from reusable blocks",
|
|
126
|
+
"description": "Define labeled hero, rich-text, and call-to-action blocks for an editor-controlled page layout.",
|
|
127
|
+
"category": "content-modeling",
|
|
128
|
+
"intents": [
|
|
129
|
+
"build a page builder",
|
|
130
|
+
"let editors arrange page sections",
|
|
131
|
+
"create reusable content blocks",
|
|
132
|
+
"model flexible landing pages"
|
|
133
|
+
],
|
|
134
|
+
"concepts": [
|
|
135
|
+
"blocks",
|
|
136
|
+
"Block",
|
|
137
|
+
"content modeling"
|
|
138
|
+
],
|
|
139
|
+
"requires": [],
|
|
140
|
+
"source": "import { defineCollection } from \"@dyrected/core\";\nimport type { Block } from \"@dyrected/core\";\n\nexport const HeroBlock = {\n slug: \"hero\",\n labels: { singular: \"Hero\", plural: \"Heroes\" },\n fields: [\n { name: \"heading\", type: \"text\", label: \"Heading\", required: true },\n { name: \"body\", type: \"textarea\", label: \"Body\" },\n ],\n} satisfies Block;\n\nexport const CallToActionBlock = {\n slug: \"callToAction\",\n labels: { singular: \"Call to action\", plural: \"Calls to action\" },\n fields: [\n { name: \"label\", type: \"text\", label: \"Link label\", required: true },\n { name: \"url\", type: \"url\", label: \"URL\", required: true },\n ],\n} satisfies Block;\n\nexport const Pages = defineCollection({\n slug: \"pages\",\n fields: [\n { name: \"title\", type: \"text\", label: \"Title\", required: true },\n {\n name: \"layout\",\n type: \"blocks\",\n label: \"Page layout\",\n blocks: [HeroBlock, CallToActionBlock],\n },\n ],\n});",
|
|
141
|
+
"docsPath": "/docs/recipes/page-builder-blocks"
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"id": "relationship-and-reverse-join",
|
|
145
|
+
"title": "Model a relationship and its reverse lookup",
|
|
146
|
+
"description": "Store an author relationship on posts and expose the author's posts through a virtual join field.",
|
|
147
|
+
"category": "content-modeling",
|
|
148
|
+
"intents": [
|
|
149
|
+
"connect posts to authors",
|
|
150
|
+
"show every post written by a user",
|
|
151
|
+
"create a reverse relationship",
|
|
152
|
+
"model one-to-many content"
|
|
153
|
+
],
|
|
154
|
+
"concepts": [
|
|
155
|
+
"relationship",
|
|
156
|
+
"join",
|
|
157
|
+
"relationTo",
|
|
158
|
+
"depth"
|
|
159
|
+
],
|
|
160
|
+
"requires": [],
|
|
161
|
+
"source": "import { defineCollection } from \"@dyrected/core\";\n\nexport const Users = defineCollection({\n slug: \"users\",\n auth: true,\n fields: [\n { name: \"name\", type: \"text\", label: \"Name\", required: true },\n {\n name: \"posts\",\n type: \"join\",\n label: \"Posts\",\n collection: \"posts\",\n on: \"author\",\n limit: 20,\n },\n ],\n});\n\nexport const Posts = defineCollection({\n slug: \"posts\",\n fields: [\n { name: \"title\", type: \"text\", label: \"Title\", required: true },\n {\n name: \"author\",\n type: \"relationship\",\n label: \"Author\",\n relationTo: \"users\",\n required: true,\n },\n ],\n});",
|
|
162
|
+
"docsPath": "/docs/recipes/relationship-and-reverse-join"
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"id": "role-based-access",
|
|
166
|
+
"title": "Restrict content operations by user role",
|
|
167
|
+
"description": "Allow public reads, editor writes, and administrator deletion with collection access rules.",
|
|
168
|
+
"category": "access-control",
|
|
169
|
+
"intents": [
|
|
170
|
+
"only editors can update content",
|
|
171
|
+
"restrict deletion to admins",
|
|
172
|
+
"make content publicly readable",
|
|
173
|
+
"add role based access"
|
|
174
|
+
],
|
|
175
|
+
"concepts": [
|
|
176
|
+
"access",
|
|
177
|
+
"AuthenticatedUser",
|
|
178
|
+
"roles"
|
|
179
|
+
],
|
|
180
|
+
"requires": [],
|
|
181
|
+
"source": "import { defineCollection } from \"@dyrected/core\";\n\nexport const Articles = defineCollection({\n slug: \"articles\",\n access: {\n read: () => true,\n create: ({ user }) => user?.roles?.some((role) => role === \"editor\" || role === \"admin\") ?? false,\n update: ({ user }) => user?.roles?.some((role) => role === \"editor\" || role === \"admin\") ?? false,\n delete: ({ user }) => user?.roles?.includes(\"admin\") ?? false,\n },\n fields: [{ name: \"title\", type: \"text\", label: \"Title\", required: true }],\n});",
|
|
182
|
+
"docsPath": "/docs/recipes/role-based-access"
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
"id": "safe-field-rename",
|
|
186
|
+
"title": "Rename a field without orphaning existing data",
|
|
187
|
+
"description": "Use renameTo and a safe default while documents migrate lazily to a new field name.",
|
|
188
|
+
"category": "data-lifecycle",
|
|
189
|
+
"intents": [
|
|
190
|
+
"rename a field safely",
|
|
191
|
+
"change a field name without losing data",
|
|
192
|
+
"migrate an existing schema",
|
|
193
|
+
"keep old documents working after a rename"
|
|
194
|
+
],
|
|
195
|
+
"concepts": [
|
|
196
|
+
"renameTo",
|
|
197
|
+
"defaultValue",
|
|
198
|
+
"schema evolution"
|
|
199
|
+
],
|
|
200
|
+
"requires": [],
|
|
201
|
+
"source": "import { defineCollection } from \"@dyrected/core\";\n\nexport const Customers = defineCollection({\n slug: \"customers\",\n fields: [\n {\n name: \"fullName\",\n type: \"text\",\n label: \"Full name\",\n renameTo: \"name\",\n defaultValue: \"\",\n required: true,\n },\n ],\n});",
|
|
202
|
+
"docsPath": "/docs/recipes/safe-field-rename"
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"id": "upload-collection",
|
|
206
|
+
"title": "Create a media upload collection",
|
|
207
|
+
"description": "Enable file uploads and capture accessible metadata in a dedicated media collection.",
|
|
208
|
+
"category": "integrations",
|
|
209
|
+
"intents": [
|
|
210
|
+
"let editors upload images",
|
|
211
|
+
"create a media library",
|
|
212
|
+
"store uploaded files",
|
|
213
|
+
"add image uploads to my project"
|
|
214
|
+
],
|
|
215
|
+
"concepts": [
|
|
216
|
+
"upload",
|
|
217
|
+
"StorageAdapter",
|
|
218
|
+
"media"
|
|
219
|
+
],
|
|
220
|
+
"requires": [],
|
|
221
|
+
"source": "import { defineCollection } from \"@dyrected/core\";\n\nexport const Media = defineCollection({\n slug: \"media\",\n upload: {\n allowedMimeTypes: [\"image/jpeg\", \"image/png\", \"image/webp\"],\n maxFileSize: 10 * 1024 * 1024,\n },\n fields: [\n { name: \"alt\", type: \"text\", label: \"Alternative text\", required: true },\n { name: \"caption\", type: \"textarea\", label: \"Caption\" },\n ],\n});",
|
|
222
|
+
"docsPath": "/docs/recipes/upload-collection"
|
|
223
|
+
}
|
|
224
|
+
]
|