vestrycms 0.0.0-stage → 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 +21 -0
- package/README.md +383 -2
- package/dist/config/fields.d.ts +30 -0
- package/dist/config/fields.js +75 -0
- package/dist/config/index.d.ts +9 -0
- package/dist/config/index.js +18 -0
- package/dist/config/types.d.ts +412 -0
- package/dist/config/types.js +10 -0
- package/dist/core/api.d.ts +67 -0
- package/dist/core/api.js +543 -0
- package/dist/core/auth.d.ts +1597 -0
- package/dist/core/auth.js +264 -0
- package/dist/core/cache.d.ts +27 -0
- package/dist/core/cache.js +52 -0
- package/dist/core/entries.d.ts +19 -0
- package/dist/core/entries.js +127 -0
- package/dist/core/index-types.d.ts +20 -0
- package/dist/core/index-types.js +1 -0
- package/dist/core/index.d.ts +13 -0
- package/dist/core/index.js +13 -0
- package/dist/core/mail.d.ts +28 -0
- package/dist/core/mail.js +62 -0
- package/dist/core/paths.d.ts +35 -0
- package/dist/core/paths.js +148 -0
- package/dist/core/roles.d.ts +24 -0
- package/dist/core/roles.js +15 -0
- package/dist/core/service.d.ts +102 -0
- package/dist/core/service.js +478 -0
- package/dist/core/source.d.ts +82 -0
- package/dist/core/source.js +75 -0
- package/dist/core/sources/github-app.d.ts +26 -0
- package/dist/core/sources/github-app.js +161 -0
- package/dist/core/sources/github.d.ts +40 -0
- package/dist/core/sources/github.js +278 -0
- package/dist/core/sources/local.d.ts +16 -0
- package/dist/core/sources/local.js +98 -0
- package/dist/core/values.d.ts +22 -0
- package/dist/core/values.js +123 -0
- package/dist/env.d.ts +19 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +167 -0
- package/dist/integration/build-index.d.ts +8 -0
- package/dist/integration/build-index.js +67 -0
- package/dist/integration/client-deps.d.ts +10 -0
- package/dist/integration/client-deps.js +43 -0
- package/dist/integration/dev-middleware.d.ts +6 -0
- package/dist/integration/dev-middleware.js +48 -0
- package/dist/integration/formatter.d.ts +7 -0
- package/dist/integration/formatter.js +56 -0
- package/dist/mdx/expressions.d.ts +14 -0
- package/dist/mdx/expressions.js +141 -0
- package/dist/mdx/index.d.ts +4 -0
- package/dist/mdx/index.js +4 -0
- package/dist/mdx/parse.d.ts +6 -0
- package/dist/mdx/parse.js +401 -0
- package/dist/mdx/serialize.d.ts +9 -0
- package/dist/mdx/serialize.js +485 -0
- package/dist/mdx/types.d.ts +42 -0
- package/dist/mdx/types.js +6 -0
- package/dist/pages/admin.astro +27 -0
- package/dist/pages/api.d.ts +3 -0
- package/dist/pages/api.js +31 -0
- package/dist/ui/App.d.ts +4 -0
- package/dist/ui/App.js +70 -0
- package/dist/ui/api.d.ts +83 -0
- package/dist/ui/api.js +97 -0
- package/dist/ui/auth-client.d.ts +27 -0
- package/dist/ui/auth-client.js +29 -0
- package/dist/ui/components/AssetPicker.d.ts +27 -0
- package/dist/ui/components/AssetPicker.js +97 -0
- package/dist/ui/components/Icon.d.ts +11 -0
- package/dist/ui/components/Icon.js +46 -0
- package/dist/ui/components/Layout.d.ts +15 -0
- package/dist/ui/components/Layout.js +87 -0
- package/dist/ui/components/editor/EditorContext.d.ts +15 -0
- package/dist/ui/components/editor/EditorContext.js +9 -0
- package/dist/ui/components/editor/NodeViews.d.ts +4 -0
- package/dist/ui/components/editor/NodeViews.js +127 -0
- package/dist/ui/components/editor/RichTextEditor.d.ts +24 -0
- package/dist/ui/components/editor/RichTextEditor.js +230 -0
- package/dist/ui/components/editor/extensions.d.ts +30 -0
- package/dist/ui/components/editor/extensions.js +248 -0
- package/dist/ui/components/editor/schema.d.ts +12 -0
- package/dist/ui/components/editor/schema.js +37 -0
- package/dist/ui/components/fields/CodeInput.d.ts +10 -0
- package/dist/ui/components/fields/CodeInput.js +8 -0
- package/dist/ui/components/fields/CodeMirrorInput.d.ts +2 -0
- package/dist/ui/components/fields/CodeMirrorInput.js +44 -0
- package/dist/ui/components/fields/FieldRenderer.d.ts +41 -0
- package/dist/ui/components/fields/FieldRenderer.js +299 -0
- package/dist/ui/components/fields/ImageTools.d.ts +31 -0
- package/dist/ui/components/fields/ImageTools.js +296 -0
- package/dist/ui/components/fields/MarkdownField.d.ts +7 -0
- package/dist/ui/components/fields/MarkdownField.js +16 -0
- package/dist/ui/components/fields/TreeInput.d.ts +13 -0
- package/dist/ui/components/fields/TreeInput.js +221 -0
- package/dist/ui/components/ui.d.ts +63 -0
- package/dist/ui/components/ui.js +113 -0
- package/dist/ui/context.d.ts +17 -0
- package/dist/ui/context.js +13 -0
- package/dist/ui/lib/format.d.ts +5 -0
- package/dist/ui/lib/format.js +11 -0
- package/dist/ui/lib/utils.d.ts +24 -0
- package/dist/ui/lib/utils.js +255 -0
- package/dist/ui/main.d.ts +1 -0
- package/dist/ui/main.js +11 -0
- package/dist/ui/pages/Assets.d.ts +1 -0
- package/dist/ui/pages/Assets.js +69 -0
- package/dist/ui/pages/CollectionList.d.ts +6 -0
- package/dist/ui/pages/CollectionList.js +115 -0
- package/dist/ui/pages/Dashboard.d.ts +1 -0
- package/dist/ui/pages/Dashboard.js +57 -0
- package/dist/ui/pages/EntryEditor.d.ts +3 -0
- package/dist/ui/pages/EntryEditor.js +313 -0
- package/dist/ui/pages/Login.d.ts +6 -0
- package/dist/ui/pages/Login.js +88 -0
- package/dist/ui/pages/Users.d.ts +1 -0
- package/dist/ui/pages/Users.js +102 -0
- package/dist/ui/styles.css +2554 -0
- package/package.json +123 -3
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vestry configuration types.
|
|
3
|
+
*
|
|
4
|
+
* Everything here is plain, JSON-serializable data. The integration embeds the
|
|
5
|
+
* config into the server bundle and ships it to the control panel over the
|
|
6
|
+
* API, so field definitions cannot contain functions. Behaviour that would
|
|
7
|
+
* normally be a callback (preview URLs, slug generation, default values) is
|
|
8
|
+
* expressed as small templates or declarative options instead.
|
|
9
|
+
*/
|
|
10
|
+
export type FieldType = "text" | "textarea" | "slug" | "number" | "boolean" | "date" | "datetime" | "select" | "multiselect" | "color" | "image" | "file" | "reference" | "object" | "array" | "markdown" | "code" | "json" | "crop" | "focalPoint" | "tree";
|
|
11
|
+
export interface FieldBase<T extends FieldType = FieldType> {
|
|
12
|
+
type: T;
|
|
13
|
+
/** Human label. Defaults to a title-cased version of the key. */
|
|
14
|
+
label?: string;
|
|
15
|
+
/** Help text rendered under the input. */
|
|
16
|
+
description?: string;
|
|
17
|
+
required?: boolean;
|
|
18
|
+
/** Show in the sidebar rail of the entry editor instead of the main column. */
|
|
19
|
+
sidebar?: boolean;
|
|
20
|
+
/** Hide from the editor entirely (value is preserved on save). */
|
|
21
|
+
hidden?: boolean;
|
|
22
|
+
/** Make the input read-only in the editor. */
|
|
23
|
+
readOnly?: boolean;
|
|
24
|
+
/** Width in the main column: full width or half (two fields per row). */
|
|
25
|
+
width?: "full" | "half" | "third";
|
|
26
|
+
}
|
|
27
|
+
export interface TextField extends FieldBase<"text"> {
|
|
28
|
+
placeholder?: string;
|
|
29
|
+
maxLength?: number;
|
|
30
|
+
/** Validate against a regular expression (source string). */
|
|
31
|
+
pattern?: string;
|
|
32
|
+
default?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface TextareaField extends FieldBase<"textarea"> {
|
|
35
|
+
placeholder?: string;
|
|
36
|
+
rows?: number;
|
|
37
|
+
maxLength?: number;
|
|
38
|
+
default?: string;
|
|
39
|
+
}
|
|
40
|
+
export interface SlugField extends FieldBase<"slug"> {
|
|
41
|
+
/** Field key the slug is generated from while the entry is new. */
|
|
42
|
+
from?: string;
|
|
43
|
+
default?: string;
|
|
44
|
+
}
|
|
45
|
+
export interface NumberField extends FieldBase<"number"> {
|
|
46
|
+
min?: number;
|
|
47
|
+
max?: number;
|
|
48
|
+
step?: number;
|
|
49
|
+
default?: number;
|
|
50
|
+
}
|
|
51
|
+
export interface BooleanField extends FieldBase<"boolean"> {
|
|
52
|
+
default?: boolean;
|
|
53
|
+
}
|
|
54
|
+
export interface DateField extends FieldBase<"date"> {
|
|
55
|
+
/** Use "now" to default new entries to today. */
|
|
56
|
+
default?: string | "now";
|
|
57
|
+
/**
|
|
58
|
+
* Allow an optional wall-clock time. The value stays `YYYY-MM-DD` when no
|
|
59
|
+
* time is set and becomes `YYYY-MM-DDTHH:mm` when one is.
|
|
60
|
+
*/
|
|
61
|
+
time?: "optional";
|
|
62
|
+
/** Hint shown next to the time input when it is empty, e.g. "defaults to 9:00 AM". */
|
|
63
|
+
timeHint?: string;
|
|
64
|
+
}
|
|
65
|
+
export interface DatetimeField extends FieldBase<"datetime"> {
|
|
66
|
+
/**
|
|
67
|
+
* How the value is stored:
|
|
68
|
+
* - "local": wall-clock ISO without zone, e.g. `2026-06-14T09:00`
|
|
69
|
+
* - "iso": full ISO instant in UTC (`toISOString()`)
|
|
70
|
+
*/
|
|
71
|
+
storage?: "local" | "iso";
|
|
72
|
+
/** Use "now" to default new entries to the current time. */
|
|
73
|
+
default?: string | "now";
|
|
74
|
+
/**
|
|
75
|
+
* Automatically set the field to the current time whenever the entry is
|
|
76
|
+
* saved (e.g. `updatedDate`). The field is shown read-only.
|
|
77
|
+
*/
|
|
78
|
+
autoUpdate?: boolean;
|
|
79
|
+
}
|
|
80
|
+
export interface SelectOption {
|
|
81
|
+
label: string;
|
|
82
|
+
value: string;
|
|
83
|
+
/** Optional swatch colour for the option (used by the liturgical colour picker). */
|
|
84
|
+
color?: string;
|
|
85
|
+
}
|
|
86
|
+
export interface SelectField extends FieldBase<"select"> {
|
|
87
|
+
options: SelectOption[];
|
|
88
|
+
default?: string;
|
|
89
|
+
/** Allow clearing the value. */
|
|
90
|
+
clearable?: boolean;
|
|
91
|
+
}
|
|
92
|
+
export interface MultiselectField extends FieldBase<"multiselect"> {
|
|
93
|
+
options: SelectOption[];
|
|
94
|
+
default?: string[];
|
|
95
|
+
}
|
|
96
|
+
export interface ColorField extends FieldBase<"color"> {
|
|
97
|
+
default?: string;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* How an asset reference is written into the content file.
|
|
101
|
+
*
|
|
102
|
+
* - "relative": path relative to the entry file (`../../assets/covers/x.jpg`).
|
|
103
|
+
* This is what Astro's `image()` schema helper expects.
|
|
104
|
+
* - "filename": the bare file name (`x.jpg`). Useful when the site resolves
|
|
105
|
+
* assets itself with `import.meta.glob`.
|
|
106
|
+
* - "public": the URL path under `public/` (`/bulletins/x.pdf`).
|
|
107
|
+
* - "repo": the repository-relative path (`src/assets/covers/x.jpg`).
|
|
108
|
+
*/
|
|
109
|
+
export type AssetStorage = "relative" | "filename" | "public" | "repo";
|
|
110
|
+
export interface AssetFieldOptions {
|
|
111
|
+
/** Repository directory that holds the files, e.g. `src/assets/covers`. */
|
|
112
|
+
directory: string;
|
|
113
|
+
/** How the chosen file is referenced from the content. Defaults to "relative" under src/, "public" under public/. */
|
|
114
|
+
storeAs?: AssetStorage;
|
|
115
|
+
/** Accepted extensions (without the dot). */
|
|
116
|
+
accept?: string[];
|
|
117
|
+
/** Allow uploading new files from the editor. Defaults to true. */
|
|
118
|
+
upload?: boolean;
|
|
119
|
+
}
|
|
120
|
+
export interface ImageField extends FieldBase<"image">, AssetFieldOptions {
|
|
121
|
+
default?: string;
|
|
122
|
+
}
|
|
123
|
+
export interface FileField extends FieldBase<"file">, AssetFieldOptions {
|
|
124
|
+
default?: string;
|
|
125
|
+
}
|
|
126
|
+
export interface ReferenceField extends FieldBase<"reference"> {
|
|
127
|
+
/** Collection key to pick from. */
|
|
128
|
+
collection: string;
|
|
129
|
+
default?: string;
|
|
130
|
+
}
|
|
131
|
+
export interface ObjectField extends FieldBase<"object"> {
|
|
132
|
+
fields: Record<string, Field>;
|
|
133
|
+
/** Render inline instead of as a collapsible group. */
|
|
134
|
+
inline?: boolean;
|
|
135
|
+
}
|
|
136
|
+
export interface ArrayField extends FieldBase<"array"> {
|
|
137
|
+
/** Shape of each item. */
|
|
138
|
+
of: Field;
|
|
139
|
+
/** Field key (for object items) to use as each item's title in the list. */
|
|
140
|
+
itemLabel?: string;
|
|
141
|
+
min?: number;
|
|
142
|
+
max?: number;
|
|
143
|
+
/** Label used on the "Add" button, e.g. "Add item". */
|
|
144
|
+
addLabel?: string;
|
|
145
|
+
}
|
|
146
|
+
export interface MarkdownField extends FieldBase<"markdown"> {
|
|
147
|
+
/** Component names (from `config.components`) that may be inserted. */
|
|
148
|
+
components?: string[];
|
|
149
|
+
/** Height hint for the editor in rows. */
|
|
150
|
+
rows?: number;
|
|
151
|
+
default?: string;
|
|
152
|
+
}
|
|
153
|
+
export interface CodeField extends FieldBase<"code"> {
|
|
154
|
+
language?: "markdown" | "yaml" | "json" | "javascript" | "text";
|
|
155
|
+
rows?: number;
|
|
156
|
+
default?: string;
|
|
157
|
+
}
|
|
158
|
+
export interface JsonField extends FieldBase<"json"> {
|
|
159
|
+
default?: unknown;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* A crop rectangle for a sibling image field, stored in the image's natural
|
|
163
|
+
* pixel coordinates as `{ x, y, width, height }`.
|
|
164
|
+
*/
|
|
165
|
+
export interface CropField extends FieldBase<"crop"> {
|
|
166
|
+
/** Key of the image field (at the same level) this crop applies to. */
|
|
167
|
+
image: string;
|
|
168
|
+
/** Lock the rectangle to an aspect ratio, e.g. `16 / 9` or `8 / 9`. */
|
|
169
|
+
aspect?: number;
|
|
170
|
+
/** Smallest allowed width/height in pixels. Defaults to 16. */
|
|
171
|
+
minSize?: number;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* A focal point for a sibling image field, stored as percentages
|
|
175
|
+
* `{ x, y }` (0–100) suitable for CSS `object-position`.
|
|
176
|
+
*/
|
|
177
|
+
export interface FocalPointField extends FieldBase<"focalPoint"> {
|
|
178
|
+
/** Key of the image field (at the same level) this focal point applies to. */
|
|
179
|
+
image: string;
|
|
180
|
+
/** Aspect ratios previewed next to the picker, e.g. `["16:9", "1:1"]`. */
|
|
181
|
+
previews?: string[];
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* A tree of nodes (e.g. a navigation menu). Each node has the given fields
|
|
185
|
+
* plus a `children` array (the key is configurable) holding nested nodes.
|
|
186
|
+
* The editor supports collapsing, inline editing, adding children, and
|
|
187
|
+
* drag-and-drop to reorder or re-parent (drag sideways to change depth).
|
|
188
|
+
*/
|
|
189
|
+
export interface TreeField extends FieldBase<"tree"> {
|
|
190
|
+
/** Fields of each node (excluding the children array). */
|
|
191
|
+
fields: Schema;
|
|
192
|
+
/** Key that holds nested nodes. Defaults to "children". */
|
|
193
|
+
childrenKey?: string;
|
|
194
|
+
/** Maximum nesting depth; 1 means a flat list. Defaults to unlimited. */
|
|
195
|
+
maxDepth?: number;
|
|
196
|
+
/** Field shown as each node's label. Defaults to "title". */
|
|
197
|
+
itemLabel?: string;
|
|
198
|
+
/** Field shown in muted text after the label, e.g. "url". */
|
|
199
|
+
itemDetail?: string;
|
|
200
|
+
/** Label for the add button. */
|
|
201
|
+
addLabel?: string;
|
|
202
|
+
}
|
|
203
|
+
export type Field = TextField | TextareaField | SlugField | NumberField | BooleanField | DateField | DatetimeField | SelectField | MultiselectField | ColorField | ImageField | FileField | ReferenceField | ObjectField | ArrayField | MarkdownField | CodeField | JsonField | CropField | FocalPointField | TreeField;
|
|
204
|
+
export type Schema = Record<string, Field>;
|
|
205
|
+
/** File formats Vestry knows how to read and write. */
|
|
206
|
+
export type EntryFormat = "mdx" | "md" | "yaml" | "json";
|
|
207
|
+
export interface StatusConfig {
|
|
208
|
+
/** Boolean field that controls published state. */
|
|
209
|
+
field: string;
|
|
210
|
+
/** Value of `field` that means "published". Defaults to `true`. */
|
|
211
|
+
publishedWhen?: boolean;
|
|
212
|
+
}
|
|
213
|
+
export interface SortConfig {
|
|
214
|
+
field: string;
|
|
215
|
+
direction?: "asc" | "desc";
|
|
216
|
+
}
|
|
217
|
+
export interface ListColumn {
|
|
218
|
+
/** Field key, or "slug" / "status" / "updated". */
|
|
219
|
+
field: string;
|
|
220
|
+
label?: string;
|
|
221
|
+
}
|
|
222
|
+
export interface BodyConfig {
|
|
223
|
+
/** Component names (from `config.components`) that may be inserted into the body. */
|
|
224
|
+
components?: string[];
|
|
225
|
+
/** Where images inserted into the body are stored and how they're referenced. */
|
|
226
|
+
images?: AssetFieldOptions;
|
|
227
|
+
/** Label for the body editor. */
|
|
228
|
+
label?: string;
|
|
229
|
+
/** Placeholder shown when empty. */
|
|
230
|
+
placeholder?: string;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* A titled group of fields in the entry editor. Sections in the main column
|
|
234
|
+
* render as cards in the order given; `sidebar: true` puts the card in the
|
|
235
|
+
* rail. The string `"body"` places the content editor among the sections.
|
|
236
|
+
* Fields not named by any section fall into a "Details" card (or the rail,
|
|
237
|
+
* for fields with `sidebar: true`).
|
|
238
|
+
*/
|
|
239
|
+
export interface FieldSection {
|
|
240
|
+
label: string;
|
|
241
|
+
description?: string;
|
|
242
|
+
fields: string[];
|
|
243
|
+
sidebar?: boolean;
|
|
244
|
+
}
|
|
245
|
+
export type EditorSection = FieldSection | "body";
|
|
246
|
+
export interface CollectionConfig {
|
|
247
|
+
label: string;
|
|
248
|
+
/** Singular label, e.g. "Sermon". */
|
|
249
|
+
singular?: string;
|
|
250
|
+
/**
|
|
251
|
+
* Where entries live, relative to the project root. Exactly one `*` (or
|
|
252
|
+
* `**`) stands in for the entry slug:
|
|
253
|
+
*
|
|
254
|
+
* - `src/content/sermons/*.mdx` one file per entry
|
|
255
|
+
* - `src/content/posts/** /index.md` nested folders, folder-per-entry
|
|
256
|
+
* - `src/content/preachers.json` no wildcard: a single JSON/YAML file holding an array of entries
|
|
257
|
+
*/
|
|
258
|
+
path: string;
|
|
259
|
+
/** Defaults to the file extension of `path`. */
|
|
260
|
+
format?: EntryFormat;
|
|
261
|
+
schema: Schema;
|
|
262
|
+
/**
|
|
263
|
+
* Body configuration for `md`/`mdx` collections. Set to `false` to hide the
|
|
264
|
+
* body editor (e.g. for data-only collections).
|
|
265
|
+
*/
|
|
266
|
+
body?: BodyConfig | false;
|
|
267
|
+
/** Field used as the entry title in listings and the editor header. Defaults to "title". */
|
|
268
|
+
titleField?: string;
|
|
269
|
+
/** Group fields into titled cards in the editor. */
|
|
270
|
+
sections?: EditorSection[];
|
|
271
|
+
/** For single-file collections: the field holding the entry id. Defaults to "id". */
|
|
272
|
+
idField?: string;
|
|
273
|
+
/** How slugs are generated for new entries. */
|
|
274
|
+
slug?: {
|
|
275
|
+
/** Field key the slug is derived from; defaults to the title field. */
|
|
276
|
+
from?: string;
|
|
277
|
+
/** Template, e.g. `{date}` or `{date}-{title}`. Field values are slugified. */
|
|
278
|
+
template?: string;
|
|
279
|
+
};
|
|
280
|
+
status?: StatusConfig;
|
|
281
|
+
sort?: SortConfig;
|
|
282
|
+
columns?: (string | ListColumn)[];
|
|
283
|
+
/** Fields searched by the list filter. Defaults to the title field. */
|
|
284
|
+
searchFields?: string[];
|
|
285
|
+
/**
|
|
286
|
+
* Preview URL template, e.g. `/sermons/{slug}`. Any schema field may be
|
|
287
|
+
* referenced in braces.
|
|
288
|
+
*/
|
|
289
|
+
previewUrl?: string;
|
|
290
|
+
/** Lucide icon name used in navigation. */
|
|
291
|
+
icon?: string;
|
|
292
|
+
/** Commit message template. Supports `{action}`, `{collection}`, `{slug}`, `{title}`. */
|
|
293
|
+
commitMessage?: string;
|
|
294
|
+
/**
|
|
295
|
+
* Show a "Recent …" list on the dashboard. Defaults to true when `sort`
|
|
296
|
+
* points at a date/datetime field. A number sets how many entries to show.
|
|
297
|
+
*/
|
|
298
|
+
recent?: boolean | number;
|
|
299
|
+
/** Allow creating new entries in the control panel (default true). */
|
|
300
|
+
create?: boolean;
|
|
301
|
+
/** Allow deleting entries (default true). */
|
|
302
|
+
delete?: boolean;
|
|
303
|
+
}
|
|
304
|
+
export interface SingletonConfig {
|
|
305
|
+
label: string;
|
|
306
|
+
path: string;
|
|
307
|
+
format?: EntryFormat;
|
|
308
|
+
schema: Schema;
|
|
309
|
+
body?: BodyConfig | false;
|
|
310
|
+
/** Group fields into titled cards in the editor. */
|
|
311
|
+
sections?: EditorSection[];
|
|
312
|
+
previewUrl?: string;
|
|
313
|
+
icon?: string;
|
|
314
|
+
commitMessage?: string;
|
|
315
|
+
}
|
|
316
|
+
export interface ComponentConfig {
|
|
317
|
+
/** Label shown in the insert menu. Defaults to the component name. */
|
|
318
|
+
label?: string;
|
|
319
|
+
description?: string;
|
|
320
|
+
/** Lucide icon name. */
|
|
321
|
+
icon?: string;
|
|
322
|
+
/**
|
|
323
|
+
* Import specifier written at the top of the MDX file when the component
|
|
324
|
+
* is used, e.g. `@/components/blocks/Highlights.astro`. Omit for components
|
|
325
|
+
* provided globally (MDX `components` prop) or plain HTML tags.
|
|
326
|
+
*/
|
|
327
|
+
import?: string;
|
|
328
|
+
/** Named import instead of default. */
|
|
329
|
+
namedImport?: boolean;
|
|
330
|
+
/** Props editable in the control panel. */
|
|
331
|
+
props?: Schema;
|
|
332
|
+
/**
|
|
333
|
+
* Whether the component wraps rich text children. `true` gives a nested
|
|
334
|
+
* editor; `"text"` restricts children to inline content; `false` (default)
|
|
335
|
+
* is self-closing.
|
|
336
|
+
*/
|
|
337
|
+
children?: boolean | "text";
|
|
338
|
+
/** Render inline (within a paragraph) rather than as a block. */
|
|
339
|
+
inline?: boolean;
|
|
340
|
+
}
|
|
341
|
+
export interface AssetContainerConfig {
|
|
342
|
+
label: string;
|
|
343
|
+
/** Repository directory, e.g. `src/assets/images` or `public/bulletins`. */
|
|
344
|
+
directory: string;
|
|
345
|
+
/** Accepted extensions (without the dot). Defaults to common image types. */
|
|
346
|
+
accept?: string[];
|
|
347
|
+
icon?: string;
|
|
348
|
+
}
|
|
349
|
+
export interface NavigationGroup {
|
|
350
|
+
label: string;
|
|
351
|
+
/** Collection, singleton or asset container keys, prefixed: `collections.sermons`, `singletons.site`, `assets.images`. */
|
|
352
|
+
items: string[];
|
|
353
|
+
}
|
|
354
|
+
export interface RepoConfig {
|
|
355
|
+
/** GitHub owner (user or organisation). */
|
|
356
|
+
owner: string;
|
|
357
|
+
/** Repository name. */
|
|
358
|
+
name: string;
|
|
359
|
+
/** Branch that commits go to. Defaults to the repository default branch. */
|
|
360
|
+
branch?: string;
|
|
361
|
+
}
|
|
362
|
+
export interface AuthConfig {
|
|
363
|
+
/**
|
|
364
|
+
* Email addresses that are always admins. They can sign in before anyone
|
|
365
|
+
* has invited them (the first admin bootstraps the user list) and cannot
|
|
366
|
+
* be removed or demoted from the control panel.
|
|
367
|
+
*/
|
|
368
|
+
admins?: string[];
|
|
369
|
+
/**
|
|
370
|
+
* Prefix for the sign-in tables (`user`, `session`, `account`,
|
|
371
|
+
* `verification`, `rateLimit`), e.g. `mysite_` for `mysite_user`. Lets
|
|
372
|
+
* several sites share one D1 database, each with its own users and
|
|
373
|
+
* sessions. Lowercase letters, digits and underscores, starting with a
|
|
374
|
+
* letter (table names ignore case, so `Site_` would clash with `site_`).
|
|
375
|
+
* Changing it on a live site starts it with an empty user list.
|
|
376
|
+
*/
|
|
377
|
+
tablePrefix?: string;
|
|
378
|
+
}
|
|
379
|
+
export interface MailConfig {
|
|
380
|
+
/**
|
|
381
|
+
* `resend` sends through Resend (API key in `VESTRY_RESEND_API_KEY`);
|
|
382
|
+
* `console` prints emails to the server log (development only).
|
|
383
|
+
*/
|
|
384
|
+
provider: "resend" | "console";
|
|
385
|
+
/** The From address, e.g. `Vestry <vestry@example.org>`. */
|
|
386
|
+
from: string;
|
|
387
|
+
}
|
|
388
|
+
export interface VestryConfig {
|
|
389
|
+
/** Display name for the control panel. */
|
|
390
|
+
name?: string;
|
|
391
|
+
/**
|
|
392
|
+
* Logo shown in the control panel's top bar instead of the name: a
|
|
393
|
+
* repository path (e.g. `src/assets/logo.svg`, served through Vestry) or an
|
|
394
|
+
* absolute URL. The bar is dark, so use a light/reverse variant.
|
|
395
|
+
*/
|
|
396
|
+
logo?: string;
|
|
397
|
+
/** Public site URL, used for preview links. */
|
|
398
|
+
siteUrl?: string;
|
|
399
|
+
repo: RepoConfig;
|
|
400
|
+
collections?: Record<string, CollectionConfig>;
|
|
401
|
+
singletons?: Record<string, SingletonConfig>;
|
|
402
|
+
components?: Record<string, ComponentConfig>;
|
|
403
|
+
assets?: Record<string, AssetContainerConfig>;
|
|
404
|
+
/** Optional navigation grouping; defaults to Collections / Singletons / Assets. */
|
|
405
|
+
navigation?: NavigationGroup[];
|
|
406
|
+
/** Default commit message template. */
|
|
407
|
+
commitMessage?: string;
|
|
408
|
+
/** Sign-in: who may edit. Users sign in with a code emailed to them. */
|
|
409
|
+
auth?: AuthConfig;
|
|
410
|
+
/** Outbound email for sign-in codes and invitations. Required in production. */
|
|
411
|
+
mail?: MailConfig;
|
|
412
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vestry configuration types.
|
|
3
|
+
*
|
|
4
|
+
* Everything here is plain, JSON-serializable data. The integration embeds the
|
|
5
|
+
* config into the server bundle and ships it to the control panel over the
|
|
6
|
+
* API, so field definitions cannot contain functions. Behaviour that would
|
|
7
|
+
* normally be a callback (preview URLs, slug generation, default values) is
|
|
8
|
+
* expressed as small templates or declarative options instead.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Vestry HTTP API. Runtime-agnostic: takes a `Request`, returns a
|
|
3
|
+
* `Response`. The Astro route and the dev-server middleware both delegate here.
|
|
4
|
+
*/
|
|
5
|
+
import type { VestryConfig } from "../config/types.js";
|
|
6
|
+
import { type AuthDatabase } from "./auth.js";
|
|
7
|
+
import type { Cache } from "./cache.js";
|
|
8
|
+
import type { BuildIndex } from "./index-types.js";
|
|
9
|
+
import { type Mailer } from "./mail.js";
|
|
10
|
+
import { type PublicUser } from "./roles.js";
|
|
11
|
+
import { type ContentSource } from "./source.js";
|
|
12
|
+
export type EnvReader = (key: string) => string | undefined;
|
|
13
|
+
export interface ApiOptions {
|
|
14
|
+
config: VestryConfig;
|
|
15
|
+
index: BuildIndex;
|
|
16
|
+
/** URL path the control panel is mounted at, e.g. `/admin`. */
|
|
17
|
+
basePath: string;
|
|
18
|
+
env: EnvReader;
|
|
19
|
+
/** Edit the project directory instead of the repository (dev). */
|
|
20
|
+
localSource?: ContentSource;
|
|
21
|
+
/**
|
|
22
|
+
* Sign-in settings. Production resolves the database from the D1 binding,
|
|
23
|
+
* the mailer from `config.mail` and the secret from `VESTRY_SECRET`; dev
|
|
24
|
+
* and tests inject their own. With a local source sign-in is skipped
|
|
25
|
+
* unless `required` is set.
|
|
26
|
+
*/
|
|
27
|
+
auth?: {
|
|
28
|
+
database?: AuthDatabase;
|
|
29
|
+
mailer?: Mailer;
|
|
30
|
+
secret?: string;
|
|
31
|
+
required?: boolean;
|
|
32
|
+
/** Development: no rate limiting, a fixed fallback secret. */
|
|
33
|
+
dev?: boolean;
|
|
34
|
+
/** Create the tables on first use (default true). */
|
|
35
|
+
migrate?: boolean;
|
|
36
|
+
};
|
|
37
|
+
/** Name of the binding holding the D1 database for users and sessions. */
|
|
38
|
+
databaseBinding?: string;
|
|
39
|
+
cache?: Cache;
|
|
40
|
+
/** Hook that lets hosts supply the remote source (defaults to GitHub via a GitHub App). */
|
|
41
|
+
createSource?: () => ContentSource;
|
|
42
|
+
}
|
|
43
|
+
/** Per-request context the host passes along (Cloudflare bindings, etc.). */
|
|
44
|
+
export interface RequestContext {
|
|
45
|
+
bindings?: Record<string, unknown>;
|
|
46
|
+
}
|
|
47
|
+
export interface ClientConfig {
|
|
48
|
+
config: VestryConfig;
|
|
49
|
+
basePath: string;
|
|
50
|
+
mode: "local" | "github";
|
|
51
|
+
/** Whether sign-in is required (false in plain local mode). */
|
|
52
|
+
auth: boolean;
|
|
53
|
+
source: {
|
|
54
|
+
label: string;
|
|
55
|
+
branch?: string;
|
|
56
|
+
url?: string;
|
|
57
|
+
};
|
|
58
|
+
user: PublicUser | null;
|
|
59
|
+
/** Set when the host is missing bindings or secrets. */
|
|
60
|
+
setupError?: string;
|
|
61
|
+
}
|
|
62
|
+
export declare const DEFAULT_DATABASE_BINDING = "VESTRY_DB";
|
|
63
|
+
export declare function json(data: unknown, init?: ResponseInit): Response;
|
|
64
|
+
export declare function createApi(options: ApiOptions): {
|
|
65
|
+
handle: (request: Request, ctx?: RequestContext) => Promise<Response>;
|
|
66
|
+
apiPrefix: string;
|
|
67
|
+
};
|