@postedin/cms-client 0.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 +66 -0
- package/bin/dissect/cli.mjs +138 -0
- package/bin/dissect/dissect.mjs +290 -0
- package/bin/profile/build.mjs +106 -0
- package/bin/profile/fetch-log.mjs +298 -0
- package/bin/profile/format.mjs +90 -0
- package/bin/profile/interference-summary.mjs +558 -0
- package/bin/profile/interference.mjs +604 -0
- package/bin/profile/measure.mjs +137 -0
- package/bin/profile/report.mjs +90 -0
- package/bin/profile/site-env.mjs +16 -0
- package/bin/profile/summarize.mjs +429 -0
- package/dist/browser.d.ts +145 -0
- package/dist/browser.js +11 -0
- package/dist/browser.js.map +1 -0
- package/dist/chunk-6V54ITTK.js +197 -0
- package/dist/chunk-6V54ITTK.js.map +1 -0
- package/dist/chunk-MNZ7DIGC.js +51 -0
- package/dist/chunk-MNZ7DIGC.js.map +1 -0
- package/dist/form-proxy/upload-policy.d.ts +40 -0
- package/dist/form-proxy/upload-policy.js +17 -0
- package/dist/form-proxy/upload-policy.js.map +1 -0
- package/dist/index.d.ts +570 -0
- package/dist/index.js +1636 -0
- package/dist/index.js.map +1 -0
- package/dist/payload-types.d.ts +8985 -0
- package/dist/payload-types.js +1 -0
- package/dist/payload-types.js.map +1 -0
- package/package.json +74 -0
- package/src/api.ts +387 -0
- package/src/blog-listing.ts +75 -0
- package/src/browser.ts +24 -0
- package/src/client.ts +144 -0
- package/src/cms-to-href.ts +70 -0
- package/src/cms.ts +86 -0
- package/src/collections/appearance.ts +94 -0
- package/src/collections/areas.ts +29 -0
- package/src/collections/authors.ts +27 -0
- package/src/collections/banners.ts +14 -0
- package/src/collections/categories.ts +111 -0
- package/src/collections/forms.ts +29 -0
- package/src/collections/header-footer.ts +19 -0
- package/src/collections/image-links.ts +14 -0
- package/src/collections/media.ts +18 -0
- package/src/collections/options.ts +10 -0
- package/src/collections/pages.ts +83 -0
- package/src/collections/posts.ts +249 -0
- package/src/collections/project.ts +16 -0
- package/src/collections/questions.ts +35 -0
- package/src/collections/seo.ts +10 -0
- package/src/collections/tags.ts +25 -0
- package/src/collections/team-members.ts +79 -0
- package/src/config-time.ts +98 -0
- package/src/context.ts +12 -0
- package/src/decode-html.ts +8 -0
- package/src/form-proxy/cms-client.ts +95 -0
- package/src/form-proxy/cms-errors.ts +73 -0
- package/src/form-proxy/cms-write.ts +44 -0
- package/src/form-proxy/http.ts +96 -0
- package/src/form-proxy/index.ts +73 -0
- package/src/form-proxy/rate-limit.ts +46 -0
- package/src/form-proxy/submissions.ts +88 -0
- package/src/form-proxy/types.ts +23 -0
- package/src/form-proxy/upload-policy.ts +92 -0
- package/src/form-proxy/uploads.ts +81 -0
- package/src/home-page.ts +83 -0
- package/src/index.ts +68 -0
- package/src/loader.ts +83 -0
- package/src/locales.ts +80 -0
- package/src/payload-types.ts +10854 -0
- package/src/placeholder.ts +9 -0
- package/src/resolve-menu-items.ts +184 -0
- package/src/routes.ts +184 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,570 @@
|
|
|
1
|
+
import { Locale, LocaleOptions, HomePageRef, CmsLink, Locales, CmsMainMenu, Routes } from './browser.js';
|
|
2
|
+
export { CmsCallToActionLinks, CmsFooter, CmsHeader, CmsMenuItem, CmsSocialLinks, CmsToHref, CreateRoutes, defineCmsToHref, defineLocales, defineRoutes } from './browser.js';
|
|
3
|
+
import { Media, Project, Area, Page, TeamMember, Tag, Question, QuestionTag, Category, Post, Appearance, Author, Banner, ImageLink, Form, HeaderFooter, Options as Options$1, Seo, MemberType } from './payload-types.js';
|
|
4
|
+
|
|
5
|
+
/** Which of the two URL helpers is asking: a download link or an `<img>`. */
|
|
6
|
+
type UploadUse = 'file' | 'image';
|
|
7
|
+
/**
|
|
8
|
+
* A site's own rule for where an upload is served from. Return a URL to use
|
|
9
|
+
* it, or `undefined` to let the default rule decide. Consulted for every
|
|
10
|
+
* production build, bucket or not, since a site's rewrites do not depend on
|
|
11
|
+
* one; in dev the URL the CMS returned is always used.
|
|
12
|
+
*/
|
|
13
|
+
type ResolveUploadUrl = (media: Media, use: UploadUse) => string | null | undefined;
|
|
14
|
+
interface ApiOptions {
|
|
15
|
+
apiUrl: string;
|
|
16
|
+
apiKey: string;
|
|
17
|
+
projectSlug: string;
|
|
18
|
+
uploadsBaseUrl?: string;
|
|
19
|
+
protectionBypassSecret?: string;
|
|
20
|
+
isDev: boolean;
|
|
21
|
+
pageConcurrency?: number;
|
|
22
|
+
resolveUploadUrl?: ResolveUploadUrl;
|
|
23
|
+
}
|
|
24
|
+
type Collection<T> = {
|
|
25
|
+
docs: T[];
|
|
26
|
+
totalDocs: number;
|
|
27
|
+
limit: number;
|
|
28
|
+
totalPages: number;
|
|
29
|
+
page: number;
|
|
30
|
+
pagingCounter: number;
|
|
31
|
+
hasPrevPage: boolean;
|
|
32
|
+
hasNextPage: boolean;
|
|
33
|
+
prevPage: number | null;
|
|
34
|
+
nextPage: number | null;
|
|
35
|
+
};
|
|
36
|
+
declare function mapWithConcurrency<TItem, TResult>(items: TItem[], limit: number, worker: (item: TItem, index: number) => Promise<TResult>): Promise<TResult[]>;
|
|
37
|
+
type FallbackMode = 'null' | 'default';
|
|
38
|
+
type FetchCmsGlobalOptions = {
|
|
39
|
+
query?: any;
|
|
40
|
+
depth?: number;
|
|
41
|
+
locale?: Locale;
|
|
42
|
+
fallback?: FallbackMode;
|
|
43
|
+
};
|
|
44
|
+
type FetchCmsCollectionOptions = FetchCmsGlobalOptions & {
|
|
45
|
+
status?: string;
|
|
46
|
+
limit?: number;
|
|
47
|
+
sort?: string;
|
|
48
|
+
};
|
|
49
|
+
type Api = ReturnType<typeof createApi>;
|
|
50
|
+
declare function createApi(options: ApiOptions): {
|
|
51
|
+
apiUrl: (url: string, query?: any, scoped?: boolean) => string;
|
|
52
|
+
buildHeaders: () => Record<string, string>;
|
|
53
|
+
getUploadsPublicUrl: (endpoint: string) => string;
|
|
54
|
+
fileUrl: (media?: Media | null) => string | null;
|
|
55
|
+
imageUrl: (media?: Media | null) => string;
|
|
56
|
+
fetchCmsFile: (url: string) => Promise<Response>;
|
|
57
|
+
fetchCmsGlobal: <T>(global: string, fetchOptions?: FetchCmsGlobalOptions) => Promise<T>;
|
|
58
|
+
fetchCmsGlobalCollection: <T>(collection: string, fetchOptions?: FetchCmsGlobalOptions) => Promise<T>;
|
|
59
|
+
fetchCmsCollection: <T>(collection: string, fetchOptions?: FetchCmsCollectionOptions) => Promise<T[]>;
|
|
60
|
+
fetchCmsProject: () => Promise<Project>;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
declare function createGlobalLoader<TInput, TOutput = TInput>(fetchFn: () => Promise<TInput>, options?: {
|
|
64
|
+
transform?: (data: TInput) => Promise<TOutput> | TOutput;
|
|
65
|
+
}): () => Promise<TOutput | NonNullable<TOutput>>;
|
|
66
|
+
interface Doc {
|
|
67
|
+
id: string;
|
|
68
|
+
slug?: string;
|
|
69
|
+
path?: string;
|
|
70
|
+
title?: string;
|
|
71
|
+
name?: string | null;
|
|
72
|
+
}
|
|
73
|
+
declare function createCollectionLoader<TInput extends Array<any>, TOutput extends Array<any> = TInput>(fetchFn: () => Promise<TInput>, options?: {
|
|
74
|
+
transform?: (data: TInput) => Promise<TOutput> | TOutput;
|
|
75
|
+
}): (() => Promise<TOutput>) & {
|
|
76
|
+
page: (page: number, limit: number, options?: {
|
|
77
|
+
excluded: Doc[];
|
|
78
|
+
}) => Promise<TOutput>;
|
|
79
|
+
find: (predicate: Parameters<any[]["find"]>[0]) => Promise<any>;
|
|
80
|
+
filter: (predicate: Parameters<any[]["filter"]>[0]) => Promise<any[]>;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
interface WiredArea extends Omit<Area, 'page'> {
|
|
84
|
+
page?: Page | null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
interface WiredTeamMember extends Omit<TeamMember, 'slug' | 'areas'> {
|
|
88
|
+
slug: string;
|
|
89
|
+
areas?: {
|
|
90
|
+
docs?: (string | WiredArea)[];
|
|
91
|
+
hasNextPage?: boolean;
|
|
92
|
+
totalDocs?: number;
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
interface WiredTag extends Tag {
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
interface WiredQuestion extends Omit<Question, 'tags'> {
|
|
100
|
+
tags: QuestionTag[];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
type CategoryBreadcrumb = {
|
|
104
|
+
label: string;
|
|
105
|
+
url: string;
|
|
106
|
+
};
|
|
107
|
+
interface WiredCategory extends Omit<Category, 'parent' | 'slug'> {
|
|
108
|
+
slug: string;
|
|
109
|
+
parent?: WiredCategory;
|
|
110
|
+
children: WiredCategory[];
|
|
111
|
+
path: string;
|
|
112
|
+
breadcrumbs: CategoryBreadcrumb[];
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* A category plus how many posts are filed under it. The count follows the same
|
|
116
|
+
* rule as `cms.posts.findByCategory`, counting a post under its primary and its
|
|
117
|
+
* secondary categories alike, so the number a listing prints is the number of
|
|
118
|
+
* entries the category page then shows.
|
|
119
|
+
*/
|
|
120
|
+
interface CountedCategory extends WiredCategory {
|
|
121
|
+
postCount: number;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
interface WiredPost extends Post {
|
|
125
|
+
coverImage?: Media | null;
|
|
126
|
+
category?: WiredCategory | null;
|
|
127
|
+
secondaryCategories?: WiredCategory[];
|
|
128
|
+
tags?: WiredTag[];
|
|
129
|
+
searchTokens: string;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
interface WiredPage extends Omit<Page, 'parent'> {
|
|
133
|
+
parent?: WiredPage;
|
|
134
|
+
children: WiredPage[];
|
|
135
|
+
path: string;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
type WiredAppearance = Appearance & {
|
|
139
|
+
branding: NonNullable<Appearance['branding']> & {
|
|
140
|
+
brandColor: NonNullable<NonNullable<Appearance['branding']>['brandColor']>;
|
|
141
|
+
logo: NonNullable<NonNullable<Appearance['branding']>['logo']>;
|
|
142
|
+
};
|
|
143
|
+
backgroundColor: {
|
|
144
|
+
lightTheme: string;
|
|
145
|
+
darkTheme: string;
|
|
146
|
+
};
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* What a blank Appearance field falls back to. Both are CSS values, and both
|
|
150
|
+
* are a site's own: the template states them in its theme file, so its
|
|
151
|
+
* defaults are variables that file defines.
|
|
152
|
+
*/
|
|
153
|
+
interface AppearanceFallbacks {
|
|
154
|
+
brandColor: string;
|
|
155
|
+
backgroundColor: {
|
|
156
|
+
lightTheme: string;
|
|
157
|
+
darkTheme: string;
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
declare const DEFAULT_APPEARANCE_FALLBACKS: AppearanceFallbacks;
|
|
161
|
+
|
|
162
|
+
interface WiredAuthor extends Omit<Author, 'slug'> {
|
|
163
|
+
slug: string;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
type Cms = ReturnType<typeof buildCms>;
|
|
167
|
+
declare function buildCms(ctx: Context, locale: Locale): {
|
|
168
|
+
locale: "es" | "en";
|
|
169
|
+
areas: {
|
|
170
|
+
all: (() => Promise<WiredArea[]>) & {
|
|
171
|
+
page: (page: number, limit: number, options?: {
|
|
172
|
+
excluded: Doc[];
|
|
173
|
+
}) => Promise<WiredArea[]>;
|
|
174
|
+
find: (predicate: Parameters<any[]["find"]>[0]) => Promise<any>;
|
|
175
|
+
filter: (predicate: Parameters<any[]["filter"]>[0]) => Promise<any[]>;
|
|
176
|
+
};
|
|
177
|
+
};
|
|
178
|
+
authors: {
|
|
179
|
+
all: (() => Promise<WiredAuthor[]>) & {
|
|
180
|
+
page: (page: number, limit: number, options?: {
|
|
181
|
+
excluded: Doc[];
|
|
182
|
+
}) => Promise<WiredAuthor[]>;
|
|
183
|
+
find: (predicate: Parameters<any[]["find"]>[0]) => Promise<any>;
|
|
184
|
+
filter: (predicate: Parameters<any[]["filter"]>[0]) => Promise<any[]>;
|
|
185
|
+
};
|
|
186
|
+
findBySlug: (slug: string) => Promise<any>;
|
|
187
|
+
};
|
|
188
|
+
banners: {
|
|
189
|
+
all: (() => Promise<Banner[]>) & {
|
|
190
|
+
page: (page: number, limit: number, options?: {
|
|
191
|
+
excluded: Doc[];
|
|
192
|
+
}) => Promise<Banner[]>;
|
|
193
|
+
find: (predicate: Parameters<any[]["find"]>[0]) => Promise<any>;
|
|
194
|
+
filter: (predicate: Parameters<any[]["filter"]>[0]) => Promise<any[]>;
|
|
195
|
+
};
|
|
196
|
+
};
|
|
197
|
+
appearance: () => Promise<WiredAppearance | NonNullable<WiredAppearance>>;
|
|
198
|
+
imageLinks: {
|
|
199
|
+
all: (() => Promise<ImageLink[]>) & {
|
|
200
|
+
page: (page: number, limit: number, options?: {
|
|
201
|
+
excluded: Doc[];
|
|
202
|
+
}) => Promise<ImageLink[]>;
|
|
203
|
+
find: (predicate: Parameters<any[]["find"]>[0]) => Promise<any>;
|
|
204
|
+
filter: (predicate: Parameters<any[]["filter"]>[0]) => Promise<any[]>;
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
categories: {
|
|
208
|
+
populated: () => Promise<WiredCategory[]>;
|
|
209
|
+
withCounts: () => Promise<CountedCategory[]>;
|
|
210
|
+
all: (() => Promise<WiredCategory[]>) & {
|
|
211
|
+
page: (page: number, limit: number, options?: {
|
|
212
|
+
excluded: Doc[];
|
|
213
|
+
}) => Promise<WiredCategory[]>;
|
|
214
|
+
find: (predicate: Parameters<any[]["find"]>[0]) => Promise<any>;
|
|
215
|
+
filter: (predicate: Parameters<any[]["filter"]>[0]) => Promise<any[]>;
|
|
216
|
+
};
|
|
217
|
+
wire: (category: Category | string | null | undefined) => Promise<WiredCategory | null | undefined>;
|
|
218
|
+
};
|
|
219
|
+
forms: {
|
|
220
|
+
all: (() => Promise<Form[]>) & {
|
|
221
|
+
page: (page: number, limit: number, options?: {
|
|
222
|
+
excluded: Doc[];
|
|
223
|
+
}) => Promise<Form[]>;
|
|
224
|
+
find: (predicate: Parameters<any[]["find"]>[0]) => Promise<any>;
|
|
225
|
+
filter: (predicate: Parameters<any[]["filter"]>[0]) => Promise<any[]>;
|
|
226
|
+
};
|
|
227
|
+
findById: (id: string) => Promise<Form | null>;
|
|
228
|
+
resolve: (form: Form | string) => Promise<Form | null>;
|
|
229
|
+
};
|
|
230
|
+
headerFooter: () => Promise<HeaderFooter>;
|
|
231
|
+
media: {
|
|
232
|
+
all: (() => Promise<Media[]>) & {
|
|
233
|
+
page: (page: number, limit: number, options?: {
|
|
234
|
+
excluded: Doc[];
|
|
235
|
+
}) => Promise<Media[]>;
|
|
236
|
+
find: (predicate: Parameters<any[]["find"]>[0]) => Promise<any>;
|
|
237
|
+
filter: (predicate: Parameters<any[]["filter"]>[0]) => Promise<any[]>;
|
|
238
|
+
};
|
|
239
|
+
};
|
|
240
|
+
options: () => Promise<Options$1>;
|
|
241
|
+
pages: {
|
|
242
|
+
all: (() => Promise<WiredPage[]>) & {
|
|
243
|
+
page: (page: number, limit: number, options?: {
|
|
244
|
+
excluded: Doc[];
|
|
245
|
+
}) => Promise<WiredPage[]>;
|
|
246
|
+
find: (predicate: Parameters<any[]["find"]>[0]) => Promise<any>;
|
|
247
|
+
filter: (predicate: Parameters<any[]["filter"]>[0]) => Promise<any[]>;
|
|
248
|
+
};
|
|
249
|
+
findByPath: (path: string) => Promise<WiredPage | undefined>;
|
|
250
|
+
findById: (id: string) => Promise<WiredPage | null>;
|
|
251
|
+
};
|
|
252
|
+
posts: {
|
|
253
|
+
all: (() => Promise<WiredPost[]>) & {
|
|
254
|
+
page: (page: number, limit: number, options?: {
|
|
255
|
+
excluded: Doc[];
|
|
256
|
+
}) => Promise<WiredPost[]>;
|
|
257
|
+
find: (predicate: Parameters<any[]["find"]>[0]) => Promise<any>;
|
|
258
|
+
filter: (predicate: Parameters<any[]["filter"]>[0]) => Promise<any[]>;
|
|
259
|
+
};
|
|
260
|
+
exists: () => Promise<boolean>;
|
|
261
|
+
page: (page: number, limit: number, options?: {
|
|
262
|
+
excluded: Doc[];
|
|
263
|
+
} | undefined) => Promise<WiredPost[]>;
|
|
264
|
+
latest: () => Promise<WiredPost[]>;
|
|
265
|
+
featured: () => Promise<WiredPost[]>;
|
|
266
|
+
related: (post: WiredPost, limit?: number) => Promise<any[]>;
|
|
267
|
+
findBySlug: (slug: string) => Promise<any>;
|
|
268
|
+
findByAuthor: (author: Author) => Promise<any[]>;
|
|
269
|
+
findByTeamMember: (memberId: string) => Promise<WiredPost[]>;
|
|
270
|
+
findByCategory: (category: Category) => Promise<any[]>;
|
|
271
|
+
findByTag: (tag: Tag) => Promise<any[]>;
|
|
272
|
+
nextInCategory: (post: WiredPost) => Promise<WiredPost | undefined>;
|
|
273
|
+
};
|
|
274
|
+
project: () => Promise<Project>;
|
|
275
|
+
questions: {
|
|
276
|
+
all: (() => Promise<WiredQuestion[]>) & {
|
|
277
|
+
page: (page: number, limit: number, options?: {
|
|
278
|
+
excluded: Doc[];
|
|
279
|
+
}) => Promise<WiredQuestion[]>;
|
|
280
|
+
find: (predicate: Parameters<any[]["find"]>[0]) => Promise<any>;
|
|
281
|
+
filter: (predicate: Parameters<any[]["filter"]>[0]) => Promise<any[]>;
|
|
282
|
+
};
|
|
283
|
+
filterByTag: (searchTag: QuestionTag) => Promise<any[]>;
|
|
284
|
+
};
|
|
285
|
+
seo: () => Promise<Seo>;
|
|
286
|
+
tags: {
|
|
287
|
+
all: (() => Promise<WiredTag[]>) & {
|
|
288
|
+
page: (page: number, limit: number, options?: {
|
|
289
|
+
excluded: Doc[];
|
|
290
|
+
}) => Promise<WiredTag[]>;
|
|
291
|
+
find: (predicate: Parameters<any[]["find"]>[0]) => Promise<any>;
|
|
292
|
+
filter: (predicate: Parameters<any[]["filter"]>[0]) => Promise<any[]>;
|
|
293
|
+
};
|
|
294
|
+
findBySlug: (slug: string) => Promise<any>;
|
|
295
|
+
};
|
|
296
|
+
teamMembers: {
|
|
297
|
+
all: (() => Promise<WiredTeamMember[]>) & {
|
|
298
|
+
page: (page: number, limit: number, options?: {
|
|
299
|
+
excluded: Doc[];
|
|
300
|
+
}) => Promise<WiredTeamMember[]>;
|
|
301
|
+
find: (predicate: Parameters<any[]["find"]>[0]) => Promise<any>;
|
|
302
|
+
filter: (predicate: Parameters<any[]["filter"]>[0]) => Promise<any[]>;
|
|
303
|
+
};
|
|
304
|
+
types: (() => Promise<MemberType[]>) & {
|
|
305
|
+
page: (page: number, limit: number, options?: {
|
|
306
|
+
excluded: Doc[];
|
|
307
|
+
}) => Promise<MemberType[]>;
|
|
308
|
+
find: (predicate: Parameters<any[]["find"]>[0]) => Promise<any>;
|
|
309
|
+
filter: (predicate: Parameters<any[]["filter"]>[0]) => Promise<any[]>;
|
|
310
|
+
};
|
|
311
|
+
findBySlug: (slug: string) => Promise<any>;
|
|
312
|
+
};
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
interface RateLimiter {
|
|
316
|
+
allow(key: string): boolean;
|
|
317
|
+
}
|
|
318
|
+
interface Options {
|
|
319
|
+
limit: number;
|
|
320
|
+
windowMs: number;
|
|
321
|
+
now?: () => number;
|
|
322
|
+
}
|
|
323
|
+
declare function createRateLimiter({ limit, windowMs, now, }: Options): RateLimiter;
|
|
324
|
+
|
|
325
|
+
type CmsResult = {
|
|
326
|
+
status: number;
|
|
327
|
+
id?: string;
|
|
328
|
+
fields?: string[];
|
|
329
|
+
};
|
|
330
|
+
interface FormOwnershipCheck {
|
|
331
|
+
formBelongsToProject(formId: string): Promise<boolean>;
|
|
332
|
+
}
|
|
333
|
+
interface ProxyDeps<TClient extends FormOwnershipCheck> {
|
|
334
|
+
projectId: string;
|
|
335
|
+
cms: TClient;
|
|
336
|
+
clientAddress: string;
|
|
337
|
+
rateLimiter?: RateLimiter;
|
|
338
|
+
/**
|
|
339
|
+
* The locales a submission may name. Defaults to every locale the CMS
|
|
340
|
+
* schema knows.
|
|
341
|
+
*/
|
|
342
|
+
locales?: readonly string[];
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
interface SubmissionsCmsClient extends FormOwnershipCheck {
|
|
346
|
+
createSubmission(payload: {
|
|
347
|
+
form: string;
|
|
348
|
+
project: string;
|
|
349
|
+
data: Record<string, unknown>;
|
|
350
|
+
honeypot: string;
|
|
351
|
+
}, locale?: Locale): Promise<CmsResult>;
|
|
352
|
+
}
|
|
353
|
+
declare const MAX_SUBMISSION_BYTES: number;
|
|
354
|
+
declare function handleFormSubmission(request: Request, deps: ProxyDeps<SubmissionsCmsClient>): Promise<Response>;
|
|
355
|
+
|
|
356
|
+
interface UploadsCmsClient extends FormOwnershipCheck {
|
|
357
|
+
createUpload(file: File, payload: {
|
|
358
|
+
form: string;
|
|
359
|
+
project: string;
|
|
360
|
+
}): Promise<CmsResult>;
|
|
361
|
+
}
|
|
362
|
+
declare function handleFormUpload(request: Request, deps: ProxyDeps<UploadsCmsClient>): Promise<Response>;
|
|
363
|
+
|
|
364
|
+
type FormProxyCmsClient = SubmissionsCmsClient & UploadsCmsClient;
|
|
365
|
+
declare function createFormProxyCmsClient(api: Pick<Api, 'buildHeaders' | 'fetchCmsCollection'>, apiUrl: string): FormProxyCmsClient;
|
|
366
|
+
|
|
367
|
+
declare function refusedFieldNames(body: unknown): string[];
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* The part of an Astro `APIContext` the proxy reads. `clientAddress` is a
|
|
371
|
+
* getter that throws on a prerendered route, which is why it is read guarded.
|
|
372
|
+
*/
|
|
373
|
+
interface RequestContext {
|
|
374
|
+
readonly clientAddress: string;
|
|
375
|
+
}
|
|
376
|
+
type FormProxy = ReturnType<typeof createFormProxy>;
|
|
377
|
+
declare function createFormProxy(cms: FormProxyCmsClient, project: () => Promise<Project>, locales: readonly string[]): {
|
|
378
|
+
cms: FormProxyCmsClient;
|
|
379
|
+
submissionLimiter: RateLimiter;
|
|
380
|
+
uploadLimiter: RateLimiter;
|
|
381
|
+
buildProxyDeps: (context: RequestContext, rateLimiter: RateLimiter) => Promise<ProxyDeps<FormProxyCmsClient>>;
|
|
382
|
+
handleFormSubmission: typeof handleFormSubmission;
|
|
383
|
+
handleFormUpload: typeof handleFormUpload;
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
interface BlogListing {
|
|
387
|
+
/**
|
|
388
|
+
* What the project calls its blog. `null` when no blog page is configured or
|
|
389
|
+
* the editor left the field blank, in which case the caller falls back to the
|
|
390
|
+
* `blog.title` translation.
|
|
391
|
+
*/
|
|
392
|
+
name: string | null;
|
|
393
|
+
/** Intro copy for the listing, in the dual Lexical/HTML shape. */
|
|
394
|
+
description: Page['listingDescription'] | null;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/** What an extension collection is built from. */
|
|
398
|
+
interface ExtensionContext {
|
|
399
|
+
api: Context['api'];
|
|
400
|
+
locale: Locale;
|
|
401
|
+
/** The client's other services, for a collection that wires against them. */
|
|
402
|
+
cms: (locale: Locale) => Cms;
|
|
403
|
+
createCollectionLoader: typeof createCollectionLoader;
|
|
404
|
+
createGlobalLoader: typeof createGlobalLoader;
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* A collection only one site reads. It is built per locale and appears on
|
|
408
|
+
* `client.cms(locale)` under the key it was registered with.
|
|
409
|
+
*/
|
|
410
|
+
type Extension<T = unknown> = (context: ExtensionContext) => T;
|
|
411
|
+
/** What each extension builds, by the key it appears under. */
|
|
412
|
+
type Extensions = Record<string, unknown>;
|
|
413
|
+
type CmsWith<E extends Extensions> = Cms & E;
|
|
414
|
+
interface ClientOptions<E extends Extensions = Record<never, never>> extends LocaleOptions {
|
|
415
|
+
/** The CMS origin, e.g. `https://cms.example.com`. */
|
|
416
|
+
apiUrl: string;
|
|
417
|
+
/** A project-scoped `api-keys` document's key. */
|
|
418
|
+
apiKey: string;
|
|
419
|
+
/** Every query is scoped to this project. */
|
|
420
|
+
projectSlug: string;
|
|
421
|
+
/** Public origin of the uploads bucket. Without it the CMS serves files. */
|
|
422
|
+
uploadsBaseUrl?: string;
|
|
423
|
+
/** Sent as `x-vercel-protection-bypass` when the CMS sits behind it. */
|
|
424
|
+
protectionBypassSecret?: string;
|
|
425
|
+
/** Dev serves every upload from the CMS's own URL. */
|
|
426
|
+
isDev: boolean;
|
|
427
|
+
/**
|
|
428
|
+
* The Appearance document, fetched at config time. Required for
|
|
429
|
+
* `cms.appearance()`; a config-time client leaves it out.
|
|
430
|
+
*/
|
|
431
|
+
appearance?: Appearance;
|
|
432
|
+
/** What a blank Appearance field falls back to. */
|
|
433
|
+
appearanceFallbacks?: AppearanceFallbacks;
|
|
434
|
+
/**
|
|
435
|
+
* The Project document, fetched at config time. Required for
|
|
436
|
+
* `cms.project()` and the form proxy; a config-time client leaves it out.
|
|
437
|
+
*/
|
|
438
|
+
project?: Project;
|
|
439
|
+
/** Collection pages fetched at a time. Default 4. */
|
|
440
|
+
pageConcurrency?: number;
|
|
441
|
+
/** A site's own rule for where an upload is served from. */
|
|
442
|
+
resolveUploadUrl?: ResolveUploadUrl;
|
|
443
|
+
/** Collections only this site reads, by the key they appear under. */
|
|
444
|
+
extensions?: {
|
|
445
|
+
[K in keyof E]: Extension<E[K]>;
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
type Client<E extends Extensions = Record<never, never>> = ReturnType<typeof createClient<E>>;
|
|
449
|
+
/**
|
|
450
|
+
* The CMS client a site builds once from its environment. Nothing in here
|
|
451
|
+
* reads the environment itself: an npm-installed package is externalised by
|
|
452
|
+
* Astro, so `import.meta.env` would be empty by the time it ran.
|
|
453
|
+
*/
|
|
454
|
+
declare function createClient<E extends Extensions = Record<never, never>>(options: ClientOptions<E>): {
|
|
455
|
+
options: ClientOptions<E>;
|
|
456
|
+
locales: {
|
|
457
|
+
locales: readonly ("es" | "en")[];
|
|
458
|
+
defaultLocale: "es" | "en";
|
|
459
|
+
localePrefix: Readonly<Record<"es" | "en", string>>;
|
|
460
|
+
isLocale: (value: unknown) => value is Locale;
|
|
461
|
+
resolveLocale: (value: unknown) => Locale;
|
|
462
|
+
prefixPath: (path: string, locale: Locale) => string;
|
|
463
|
+
stripLocalePrefix: (path: string) => {
|
|
464
|
+
locale: Locale;
|
|
465
|
+
path: string;
|
|
466
|
+
};
|
|
467
|
+
};
|
|
468
|
+
api: {
|
|
469
|
+
apiUrl: (url: string, query?: any, scoped?: boolean) => string;
|
|
470
|
+
buildHeaders: () => Record<string, string>;
|
|
471
|
+
getUploadsPublicUrl: (endpoint: string) => string;
|
|
472
|
+
fileUrl: (media?: Media | null) => string | null;
|
|
473
|
+
imageUrl: (media?: Media | null) => string;
|
|
474
|
+
fetchCmsFile: (url: string) => Promise<Response>;
|
|
475
|
+
fetchCmsGlobal: <T>(global: string, fetchOptions?: FetchCmsGlobalOptions) => Promise<T>;
|
|
476
|
+
fetchCmsGlobalCollection: <T>(collection: string, fetchOptions?: FetchCmsGlobalOptions) => Promise<T>;
|
|
477
|
+
fetchCmsCollection: <T>(collection: string, fetchOptions?: FetchCmsCollectionOptions) => Promise<T[]>;
|
|
478
|
+
fetchCmsProject: () => Promise<Project>;
|
|
479
|
+
};
|
|
480
|
+
cms: (locale?: Locale) => CmsWith<E>;
|
|
481
|
+
routes: (locale: Locale, homePage?: HomePageRef) => {
|
|
482
|
+
readonly locale: "es" | "en";
|
|
483
|
+
readonly root: <T extends "index" | "search" = "index">(name?: T, ...params: Parameters<{
|
|
484
|
+
readonly index: () => string;
|
|
485
|
+
readonly search: () => string;
|
|
486
|
+
}[T]>) => ReturnType<{
|
|
487
|
+
readonly index: () => string;
|
|
488
|
+
readonly search: () => string;
|
|
489
|
+
}[T]>;
|
|
490
|
+
readonly blog: <T extends "page" | "author" | "category" | "post" | "tag" | "index" | "more" = "index">(name?: T, ...params: Parameters<{
|
|
491
|
+
readonly index: () => string;
|
|
492
|
+
readonly more: () => string;
|
|
493
|
+
readonly page: (n: number) => string;
|
|
494
|
+
readonly category: (path: string) => string;
|
|
495
|
+
readonly author: (slug: string) => string;
|
|
496
|
+
readonly post: (slug: string) => string;
|
|
497
|
+
readonly tag: (slug: string) => string;
|
|
498
|
+
}[T]>) => ReturnType<{
|
|
499
|
+
readonly index: () => string;
|
|
500
|
+
readonly more: () => string;
|
|
501
|
+
readonly page: (n: number) => string;
|
|
502
|
+
readonly category: (path: string) => string;
|
|
503
|
+
readonly author: (slug: string) => string;
|
|
504
|
+
readonly post: (slug: string) => string;
|
|
505
|
+
readonly tag: (slug: string) => string;
|
|
506
|
+
}[T]>;
|
|
507
|
+
readonly team: <T extends "index" | "member" | "vcard" = "index">(name?: T, ...params: Parameters<{
|
|
508
|
+
readonly index: () => string;
|
|
509
|
+
readonly member: (slug: string) => string;
|
|
510
|
+
readonly vcard: (slug: string) => string;
|
|
511
|
+
}[T]>) => ReturnType<{
|
|
512
|
+
readonly index: () => string;
|
|
513
|
+
readonly member: (slug: string) => string;
|
|
514
|
+
readonly vcard: (slug: string) => string;
|
|
515
|
+
}[T]>;
|
|
516
|
+
readonly page: (slugOrPage: string | Page) => string;
|
|
517
|
+
readonly search: () => string;
|
|
518
|
+
readonly find: (routeType: ("team-member" | "page" | "author" | "category" | "blog" | "post" | "tag") | string, slugOrPath: string | undefined) => string | undefined;
|
|
519
|
+
readonly fromCMSCollection: (collectionSlug: string, doc: {
|
|
520
|
+
slug: string;
|
|
521
|
+
} & Partial<Page>) => string | undefined;
|
|
522
|
+
};
|
|
523
|
+
cmsToHref: (link: Partial<CmsLink>, locale: Locale, homePage: HomePageRef) => string | undefined;
|
|
524
|
+
getHomePage: (locale: Locale) => Promise<WiredPage | null>;
|
|
525
|
+
getHomePageRef: (locale: Locale) => Promise<HomePageRef>;
|
|
526
|
+
getBlogListing: (locale: Locale) => Promise<BlogListing>;
|
|
527
|
+
/** Wires a single post document, e.g. a draft for live preview. */
|
|
528
|
+
wirePost: (post: Post | undefined, locale: Locale) => Promise<WiredPost | undefined>;
|
|
529
|
+
formProxy: {
|
|
530
|
+
cms: FormProxyCmsClient;
|
|
531
|
+
submissionLimiter: RateLimiter;
|
|
532
|
+
uploadLimiter: RateLimiter;
|
|
533
|
+
buildProxyDeps: (context: RequestContext, rateLimiter: RateLimiter) => Promise<ProxyDeps<FormProxyCmsClient>>;
|
|
534
|
+
handleFormSubmission: typeof handleFormSubmission;
|
|
535
|
+
handleFormUpload: typeof handleFormUpload;
|
|
536
|
+
};
|
|
537
|
+
/** The fetches `astro.config.mjs` makes before the build starts. */
|
|
538
|
+
config: {
|
|
539
|
+
fetchProjectSettings(): Promise<{
|
|
540
|
+
project: Project;
|
|
541
|
+
appearance: Appearance;
|
|
542
|
+
options: Options$1;
|
|
543
|
+
}>;
|
|
544
|
+
redirects(): Promise<Record<string, string>>;
|
|
545
|
+
fetchIconBuffer(icon: Media): Promise<false | Buffer<ArrayBuffer>>;
|
|
546
|
+
};
|
|
547
|
+
};
|
|
548
|
+
|
|
549
|
+
/** What every collection service is built from. Internal to the package. */
|
|
550
|
+
interface Context {
|
|
551
|
+
api: Api;
|
|
552
|
+
locales: Locales;
|
|
553
|
+
options: ClientOptions<any>;
|
|
554
|
+
cms: (locale: Locale) => Cms;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
type MenuCollectionData = {
|
|
558
|
+
pages: WiredPage[];
|
|
559
|
+
categories: WiredCategory[];
|
|
560
|
+
tags: WiredTag[];
|
|
561
|
+
teamMembers: WiredTeamMember[];
|
|
562
|
+
};
|
|
563
|
+
/** The words the menu adds of its own. Site copy, so the site supplies it. */
|
|
564
|
+
type MenuLabels = {
|
|
565
|
+
/** Heads the team-members submenu: the site's `team.title`. */
|
|
566
|
+
team: string;
|
|
567
|
+
};
|
|
568
|
+
declare function resolveMenuItems(mainMenu: CmsMainMenu, data: MenuCollectionData, routes: Routes, labels: MenuLabels): CmsMainMenu;
|
|
569
|
+
|
|
570
|
+
export { type Api, type AppearanceFallbacks, type BlogListing, type CategoryBreadcrumb, type Client, type ClientOptions, type Cms, CmsLink, CmsMainMenu, type CmsResult, type CmsWith, type Collection, type CountedCategory, DEFAULT_APPEARANCE_FALLBACKS, type Doc, type Extension, type ExtensionContext, type Extensions, type FallbackMode, type FetchCmsCollectionOptions, type FetchCmsGlobalOptions, type FormOwnershipCheck, type FormProxy, type FormProxyCmsClient, HomePageRef, Locale, LocaleOptions, Locales, MAX_SUBMISSION_BYTES, type MenuCollectionData, type MenuLabels, type ProxyDeps, type RateLimiter, type RequestContext, type ResolveUploadUrl, Routes, type SubmissionsCmsClient, type UploadUse, type UploadsCmsClient, type WiredAppearance, type WiredArea, type WiredAuthor, type WiredCategory, type WiredPage, type WiredPost, type WiredQuestion, type WiredTag, type WiredTeamMember, createClient, createCollectionLoader, createFormProxy, createFormProxyCmsClient, createGlobalLoader, createRateLimiter, handleFormSubmission, handleFormUpload, mapWithConcurrency, refusedFieldNames, resolveMenuItems };
|