@next-buildr/payload 0.0.0-stage → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/adapter/adapter.test.d.ts +2 -0
- package/dist/adapter/adapter.test.d.ts.map +1 -0
- package/dist/adapter/adapter.test.js +282 -0
- package/dist/adapter/canvas-data-source.d.ts +9 -0
- package/dist/adapter/canvas-data-source.d.ts.map +1 -0
- package/dist/adapter/canvas-data-source.js +24 -0
- package/dist/adapter/document-adapter.d.ts +20 -0
- package/dist/adapter/document-adapter.d.ts.map +1 -0
- package/dist/adapter/document-adapter.js +183 -0
- package/dist/adapter/http.d.ts +34 -0
- package/dist/adapter/http.d.ts.map +1 -0
- package/dist/adapter/http.js +72 -0
- package/dist/adapter/index.d.ts +4 -0
- package/dist/adapter/index.d.ts.map +1 -0
- package/dist/adapter/index.js +5 -0
- package/dist/admin/index.d.ts +4 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +2 -0
- package/dist/admin/layout-field-connected.d.ts +6 -0
- package/dist/admin/layout-field-connected.d.ts.map +1 -0
- package/dist/admin/layout-field-connected.js +16 -0
- package/dist/admin/layout-field-view.d.ts +16 -0
- package/dist/admin/layout-field-view.d.ts.map +1 -0
- package/dist/admin/layout-field-view.js +14 -0
- package/dist/admin/layout-field.d.ts +6 -0
- package/dist/admin/layout-field.d.ts.map +1 -0
- package/dist/admin/layout-field.js +13 -0
- package/dist/admin/layout-field.test.d.ts +2 -0
- package/dist/admin/layout-field.test.d.ts.map +1 -0
- package/dist/admin/layout-field.test.js +41 -0
- package/dist/contract.d.ts +289 -0
- package/dist/contract.d.ts.map +1 -0
- package/dist/contract.js +176 -0
- package/dist/data/build-context.d.ts +20 -0
- package/dist/data/build-context.d.ts.map +1 -0
- package/dist/data/build-context.js +25 -0
- package/dist/data/data.test.d.ts +2 -0
- package/dist/data/data.test.d.ts.map +1 -0
- package/dist/data/data.test.js +261 -0
- package/dist/data/index.d.ts +10 -0
- package/dist/data/index.d.ts.map +1 -0
- package/dist/data/index.js +5 -0
- package/dist/data/normalize.d.ts +14 -0
- package/dist/data/normalize.d.ts.map +1 -0
- package/dist/data/normalize.js +128 -0
- package/dist/data/payload-data-source.d.ts +42 -0
- package/dist/data/payload-data-source.d.ts.map +1 -0
- package/dist/data/payload-data-source.js +179 -0
- package/dist/data/payload-data-source.test.d.ts +2 -0
- package/dist/data/payload-data-source.test.d.ts.map +1 -0
- package/dist/data/payload-data-source.test.js +160 -0
- package/dist/data/resolve-layout.d.ts +45 -0
- package/dist/data/resolve-layout.d.ts.map +1 -0
- package/dist/data/resolve-layout.js +111 -0
- package/dist/data/schema-from-fields.d.ts +63 -0
- package/dist/data/schema-from-fields.d.ts.map +1 -0
- package/dist/data/schema-from-fields.js +178 -0
- package/dist/data/where.d.ts +53 -0
- package/dist/data/where.d.ts.map +1 -0
- package/dist/data/where.js +210 -0
- package/dist/mcp/http-backend.d.ts +35 -0
- package/dist/mcp/http-backend.d.ts.map +1 -0
- package/dist/mcp/http-backend.js +337 -0
- package/dist/mcp/http-backend.test.d.ts +2 -0
- package/dist/mcp/http-backend.test.d.ts.map +1 -0
- package/dist/mcp/http-backend.test.js +178 -0
- package/dist/mcp/index.d.ts +2 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +2 -0
- package/dist/mcp/route.d.ts +63 -0
- package/dist/mcp/route.d.ts.map +1 -0
- package/dist/mcp/route.js +230 -0
- package/dist/next/get-document.d.ts +64 -0
- package/dist/next/get-document.d.ts.map +1 -0
- package/dist/next/get-document.js +208 -0
- package/dist/next/get-document.test.d.ts +2 -0
- package/dist/next/get-document.test.d.ts.map +1 -0
- package/dist/next/get-document.test.js +155 -0
- package/dist/next/index.d.ts +9 -0
- package/dist/next/index.d.ts.map +1 -0
- package/dist/next/index.js +4 -0
- package/dist/next/next-helpers.test.d.ts +2 -0
- package/dist/next/next-helpers.test.d.ts.map +1 -0
- package/dist/next/next-helpers.test.js +122 -0
- package/dist/next/revalidate.d.ts +44 -0
- package/dist/next/revalidate.d.ts.map +1 -0
- package/dist/next/revalidate.js +45 -0
- package/dist/next/seo.d.ts +43 -0
- package/dist/next/seo.d.ts.map +1 -0
- package/dist/next/seo.js +53 -0
- package/dist/next/tags.d.ts +23 -0
- package/dist/next/tags.d.ts.map +1 -0
- package/dist/next/tags.js +31 -0
- package/dist/plugin/access.d.ts +19 -0
- package/dist/plugin/access.d.ts.map +1 -0
- package/dist/plugin/access.js +32 -0
- package/dist/plugin/collections/form-submissions.d.ts +10 -0
- package/dist/plugin/collections/form-submissions.d.ts.map +1 -0
- package/dist/plugin/collections/form-submissions.js +37 -0
- package/dist/plugin/collections/templates.d.ts +13 -0
- package/dist/plugin/collections/templates.d.ts.map +1 -0
- package/dist/plugin/collections/templates.js +118 -0
- package/dist/plugin/endpoints/access.test.d.ts +2 -0
- package/dist/plugin/endpoints/access.test.d.ts.map +1 -0
- package/dist/plugin/endpoints/access.test.js +91 -0
- package/dist/plugin/endpoints/adapter-contract.test.d.ts +2 -0
- package/dist/plugin/endpoints/adapter-contract.test.d.ts.map +1 -0
- package/dist/plugin/endpoints/adapter-contract.test.js +45 -0
- package/dist/plugin/endpoints/context.d.ts +65 -0
- package/dist/plugin/endpoints/context.d.ts.map +1 -0
- package/dist/plugin/endpoints/context.js +113 -0
- package/dist/plugin/endpoints/data-context.d.ts +8 -0
- package/dist/plugin/endpoints/data-context.d.ts.map +1 -0
- package/dist/plugin/endpoints/data-context.js +63 -0
- package/dist/plugin/endpoints/data-endpoints.test.d.ts +2 -0
- package/dist/plugin/endpoints/data-endpoints.test.d.ts.map +1 -0
- package/dist/plugin/endpoints/data-endpoints.test.js +125 -0
- package/dist/plugin/endpoints/data-query.test.d.ts +2 -0
- package/dist/plugin/endpoints/data-query.test.d.ts.map +1 -0
- package/dist/plugin/endpoints/data-query.test.js +96 -0
- package/dist/plugin/endpoints/data-schema.d.ts +5 -0
- package/dist/plugin/endpoints/data-schema.d.ts.map +1 -0
- package/dist/plugin/endpoints/data-schema.js +21 -0
- package/dist/plugin/endpoints/data.d.ts +10 -0
- package/dist/plugin/endpoints/data.d.ts.map +1 -0
- package/dist/plugin/endpoints/data.js +96 -0
- package/dist/plugin/endpoints/document.d.ts +11 -0
- package/dist/plugin/endpoints/document.d.ts.map +1 -0
- package/dist/plugin/endpoints/document.js +119 -0
- package/dist/plugin/endpoints/documents.d.ts +10 -0
- package/dist/plugin/endpoints/documents.d.ts.map +1 -0
- package/dist/plugin/endpoints/documents.js +145 -0
- package/dist/plugin/endpoints/endpoints.test-kit.d.ts +42 -0
- package/dist/plugin/endpoints/endpoints.test-kit.d.ts.map +1 -0
- package/dist/plugin/endpoints/endpoints.test-kit.js +141 -0
- package/dist/plugin/endpoints/endpoints.test.d.ts +2 -0
- package/dist/plugin/endpoints/endpoints.test.d.ts.map +1 -0
- package/dist/plugin/endpoints/endpoints.test.js +209 -0
- package/dist/plugin/endpoints/forms.d.ts +16 -0
- package/dist/plugin/endpoints/forms.d.ts.map +1 -0
- package/dist/plugin/endpoints/forms.js +199 -0
- package/dist/plugin/endpoints/forms.test.d.ts +2 -0
- package/dist/plugin/endpoints/forms.test.d.ts.map +1 -0
- package/dist/plugin/endpoints/forms.test.js +346 -0
- package/dist/plugin/endpoints/guards.d.ts +9 -0
- package/dist/plugin/endpoints/guards.d.ts.map +1 -0
- package/dist/plugin/endpoints/guards.js +35 -0
- package/dist/plugin/endpoints/index.d.ts +6 -0
- package/dist/plugin/endpoints/index.d.ts.map +1 -0
- package/dist/plugin/endpoints/index.js +32 -0
- package/dist/plugin/endpoints/locales-no-fallback.test.d.ts +2 -0
- package/dist/plugin/endpoints/locales-no-fallback.test.d.ts.map +1 -0
- package/dist/plugin/endpoints/locales-no-fallback.test.js +30 -0
- package/dist/plugin/endpoints/locales.test.d.ts +2 -0
- package/dist/plugin/endpoints/locales.test.d.ts.map +1 -0
- package/dist/plugin/endpoints/locales.test.js +128 -0
- package/dist/plugin/endpoints/manifest.d.ts +5 -0
- package/dist/plugin/endpoints/manifest.d.ts.map +1 -0
- package/dist/plugin/endpoints/manifest.js +18 -0
- package/dist/plugin/endpoints/mcp-http-backend.test.d.ts +2 -0
- package/dist/plugin/endpoints/mcp-http-backend.test.d.ts.map +1 -0
- package/dist/plugin/endpoints/mcp-http-backend.test.js +84 -0
- package/dist/plugin/endpoints/mcp-off.test.d.ts +2 -0
- package/dist/plugin/endpoints/mcp-off.test.d.ts.map +1 -0
- package/dist/plugin/endpoints/mcp-off.test.js +33 -0
- package/dist/plugin/endpoints/mcp-publish.test.d.ts +2 -0
- package/dist/plugin/endpoints/mcp-publish.test.d.ts.map +1 -0
- package/dist/plugin/endpoints/mcp-publish.test.js +42 -0
- package/dist/plugin/endpoints/mcp-route.test.d.ts +2 -0
- package/dist/plugin/endpoints/mcp-route.test.d.ts.map +1 -0
- package/dist/plugin/endpoints/mcp-route.test.js +132 -0
- package/dist/plugin/endpoints/mcp.test.d.ts +2 -0
- package/dist/plugin/endpoints/mcp.test.d.ts.map +1 -0
- package/dist/plugin/endpoints/mcp.test.js +231 -0
- package/dist/plugin/endpoints/media.d.ts +7 -0
- package/dist/plugin/endpoints/media.d.ts.map +1 -0
- package/dist/plugin/endpoints/media.js +115 -0
- package/dist/plugin/endpoints/media.test.d.ts +2 -0
- package/dist/plugin/endpoints/media.test.d.ts.map +1 -0
- package/dist/plugin/endpoints/media.test.js +95 -0
- package/dist/plugin/endpoints/publish-a11y.test.d.ts +2 -0
- package/dist/plugin/endpoints/publish-a11y.test.d.ts.map +1 -0
- package/dist/plugin/endpoints/publish-a11y.test.js +27 -0
- package/dist/plugin/endpoints/publish.d.ts +9 -0
- package/dist/plugin/endpoints/publish.d.ts.map +1 -0
- package/dist/plugin/endpoints/publish.js +81 -0
- package/dist/plugin/endpoints/rename.d.ts +9 -0
- package/dist/plugin/endpoints/rename.d.ts.map +1 -0
- package/dist/plugin/endpoints/rename.js +47 -0
- package/dist/plugin/endpoints/respond.d.ts +9 -0
- package/dist/plugin/endpoints/respond.d.ts.map +1 -0
- package/dist/plugin/endpoints/respond.js +10 -0
- package/dist/plugin/endpoints/samples.d.ts +5 -0
- package/dist/plugin/endpoints/samples.d.ts.map +1 -0
- package/dist/plugin/endpoints/samples.js +42 -0
- package/dist/plugin/endpoints/save.d.ts +9 -0
- package/dist/plugin/endpoints/save.d.ts.map +1 -0
- package/dist/plugin/endpoints/save.js +58 -0
- package/dist/plugin/endpoints/session.d.ts +5 -0
- package/dist/plugin/endpoints/session.d.ts.map +1 -0
- package/dist/plugin/endpoints/session.js +30 -0
- package/dist/plugin/endpoints/templates.test.d.ts +2 -0
- package/dist/plugin/endpoints/templates.test.d.ts.map +1 -0
- package/dist/plugin/endpoints/templates.test.js +191 -0
- package/dist/plugin/fields.d.ts +28 -0
- package/dist/plugin/fields.d.ts.map +1 -0
- package/dist/plugin/fields.js +62 -0
- package/dist/plugin/forms/forms.test.d.ts +2 -0
- package/dist/plugin/forms/forms.test.d.ts.map +1 -0
- package/dist/plugin/forms/forms.test.js +88 -0
- package/dist/plugin/forms/notify.d.ts +6 -0
- package/dist/plugin/forms/notify.d.ts.map +1 -0
- package/dist/plugin/forms/notify.js +13 -0
- package/dist/plugin/forms/rate-limit.d.ts +24 -0
- package/dist/plugin/forms/rate-limit.d.ts.map +1 -0
- package/dist/plugin/forms/rate-limit.js +36 -0
- package/dist/plugin/forms/validate.d.ts +22 -0
- package/dist/plugin/forms/validate.d.ts.map +1 -0
- package/dist/plugin/forms/validate.js +79 -0
- package/dist/plugin/hooks/layout-hook.d.ts +9 -0
- package/dist/plugin/hooks/layout-hook.d.ts.map +1 -0
- package/dist/plugin/hooks/layout-hook.js +33 -0
- package/dist/plugin/hooks/layout-hook.test.d.ts +2 -0
- package/dist/plugin/hooks/layout-hook.test.d.ts.map +1 -0
- package/dist/plugin/hooks/layout-hook.test.js +191 -0
- package/dist/plugin/hooks/process-layout.d.ts +32 -0
- package/dist/plugin/hooks/process-layout.d.ts.map +1 -0
- package/dist/plugin/hooks/process-layout.js +68 -0
- package/dist/plugin/hooks/read-layout.d.ts +17 -0
- package/dist/plugin/hooks/read-layout.d.ts.map +1 -0
- package/dist/plugin/hooks/read-layout.js +39 -0
- package/dist/plugin/index.d.ts +18 -0
- package/dist/plugin/index.d.ts.map +1 -0
- package/dist/plugin/index.js +105 -0
- package/dist/plugin/locales.d.ts +32 -0
- package/dist/plugin/locales.d.ts.map +1 -0
- package/dist/plugin/locales.js +56 -0
- package/dist/plugin/options.d.ts +77 -0
- package/dist/plugin/options.d.ts.map +1 -0
- package/dist/plugin/options.js +123 -0
- package/dist/plugin/plugin.test.d.ts +2 -0
- package/dist/plugin/plugin.test.d.ts.map +1 -0
- package/dist/plugin/plugin.test.js +186 -0
- package/dist/plugin/write-guard.d.ts +14 -0
- package/dist/plugin/write-guard.d.ts.map +1 -0
- package/dist/plugin/write-guard.js +18 -0
- package/package.json +107 -3
- package/README.md +0 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-context.d.ts","sourceRoot":"","sources":["../../src/data/build-context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE3E,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,8EAA8E;IAC9E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACpD,QAAQ,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5F;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAmB9E"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { normalizeDoc } from './normalize.js';
|
|
2
|
+
/**
|
|
3
|
+
* The data scopes of a document: `{ site, [context]: doc, route }`, shaped exactly like the schema
|
|
4
|
+
* `schemaFromCollection` derives (same allow-list), ready to be served to the canvas as `scopes`.
|
|
5
|
+
*/
|
|
6
|
+
export function buildContext(input) {
|
|
7
|
+
const { source, options, collection } = input;
|
|
8
|
+
const own = source.collections.find((candidate) => candidate.slug === collection);
|
|
9
|
+
const scopes = {};
|
|
10
|
+
const siteGlobal = source.globals?.find((global) => global.slug === options.siteGlobal);
|
|
11
|
+
if (siteGlobal !== undefined) {
|
|
12
|
+
scopes['site'] =
|
|
13
|
+
input.site === undefined
|
|
14
|
+
? null
|
|
15
|
+
: normalizeDoc(source, siteGlobal.fields, input.site, options.contextNames);
|
|
16
|
+
}
|
|
17
|
+
scopes[options.contextNames[collection] ?? collection] =
|
|
18
|
+
own === undefined ? null : normalizeDoc(source, own.fields, input.doc, options.contextNames);
|
|
19
|
+
scopes['route'] = {
|
|
20
|
+
path: input.route.path,
|
|
21
|
+
locale: input.route.locale,
|
|
22
|
+
params: { page: input.route.page ?? null },
|
|
23
|
+
};
|
|
24
|
+
return scopes;
|
|
25
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data.test.d.ts","sourceRoot":"","sources":["../../src/data/data.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { schemaAtPath } from '@next-buildr/core';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import { buildContext } from './build-context.js';
|
|
4
|
+
import { normalizeDoc, normalizeMedia } from './normalize.js';
|
|
5
|
+
import { schemaFromCollection, } from './schema-from-fields.js';
|
|
6
|
+
const text = (name, extra = {}) => ({
|
|
7
|
+
type: 'text',
|
|
8
|
+
name,
|
|
9
|
+
...extra,
|
|
10
|
+
});
|
|
11
|
+
const posts = {
|
|
12
|
+
slug: 'posts',
|
|
13
|
+
fields: [
|
|
14
|
+
text('title', { label: 'Title' }),
|
|
15
|
+
{ type: 'textarea', name: 'excerpt' },
|
|
16
|
+
{ type: 'number', name: 'readingTime' },
|
|
17
|
+
{ type: 'checkbox', name: 'featured' },
|
|
18
|
+
{ type: 'date', name: 'publishedAt' },
|
|
19
|
+
{ type: 'select', name: 'kind', options: ['news', { label: 'Guide', value: 'guide' }] },
|
|
20
|
+
{ type: 'select', name: 'flags', hasMany: true, options: ['a', 'b'] },
|
|
21
|
+
{ type: 'richText', name: 'content' },
|
|
22
|
+
{ type: 'upload', name: 'cover', relationTo: 'media' },
|
|
23
|
+
{ type: 'upload', name: 'gallery', relationTo: 'media', hasMany: true },
|
|
24
|
+
{ type: 'relationship', name: 'author', relationTo: 'authors' },
|
|
25
|
+
{ type: 'relationship', name: 'tags', relationTo: 'tags', hasMany: true },
|
|
26
|
+
{ type: 'relationship', name: 'owner', relationTo: 'users' },
|
|
27
|
+
{ type: 'relationship', name: 'either', relationTo: ['authors', 'tags'] },
|
|
28
|
+
{
|
|
29
|
+
type: 'group',
|
|
30
|
+
name: 'seo',
|
|
31
|
+
fields: [text('title'), text('internalNote', { hidden: true })],
|
|
32
|
+
},
|
|
33
|
+
{ type: 'array', name: 'facts', fields: [text('label'), { type: 'number', name: 'value' }] },
|
|
34
|
+
{ type: 'row', fields: [text('subtitle')] },
|
|
35
|
+
{ type: 'tabs', tabs: [{ fields: [text('lead')] }, { name: 'extra', fields: [text('note')] }] },
|
|
36
|
+
// Never data for a binding:
|
|
37
|
+
{ type: 'blocks', name: 'sections' },
|
|
38
|
+
{ type: 'json', name: 'layout' },
|
|
39
|
+
{ type: 'json', name: 'raw' },
|
|
40
|
+
{ type: 'point', name: 'where' },
|
|
41
|
+
text('password'),
|
|
42
|
+
text('resetPasswordToken'),
|
|
43
|
+
text('apiKey'),
|
|
44
|
+
text('secretNotes'),
|
|
45
|
+
text('draftOnly', { hidden: true }),
|
|
46
|
+
text('restricted', { access: { read: () => false } }),
|
|
47
|
+
{ type: 'number', name: 'buildrRevision' },
|
|
48
|
+
{ type: 'text', name: '_status' },
|
|
49
|
+
{ type: 'ui', name: 'preview' },
|
|
50
|
+
],
|
|
51
|
+
};
|
|
52
|
+
const authors = {
|
|
53
|
+
slug: 'authors',
|
|
54
|
+
fields: [
|
|
55
|
+
text('name'),
|
|
56
|
+
{ type: 'upload', name: 'avatar', relationTo: 'media' },
|
|
57
|
+
{ type: 'relationship', name: 'user', relationTo: 'users' },
|
|
58
|
+
{ type: 'relationship', name: 'posts', relationTo: 'posts', hasMany: true },
|
|
59
|
+
text('salt'),
|
|
60
|
+
],
|
|
61
|
+
};
|
|
62
|
+
const users = {
|
|
63
|
+
slug: 'users',
|
|
64
|
+
auth: true,
|
|
65
|
+
fields: [text('email'), text('name'), text('role'), text('password')],
|
|
66
|
+
};
|
|
67
|
+
const tags = { slug: 'tags', fields: [text('title')] };
|
|
68
|
+
const media = { slug: 'media', fields: [text('alt')] };
|
|
69
|
+
const internal = { slug: 'payload-preferences', fields: [text('key')] };
|
|
70
|
+
const settings = {
|
|
71
|
+
slug: 'site-settings',
|
|
72
|
+
fields: [text('siteName'), { type: 'upload', name: 'logo', relationTo: 'media' }, text('token')],
|
|
73
|
+
};
|
|
74
|
+
const source = {
|
|
75
|
+
collections: [posts, authors, users, tags, media, internal],
|
|
76
|
+
globals: [settings],
|
|
77
|
+
};
|
|
78
|
+
const options = { contextNames: { posts: 'post' }, siteGlobal: 'site-settings' };
|
|
79
|
+
const schema = () => {
|
|
80
|
+
const built = schemaFromCollection(source, 'posts', options);
|
|
81
|
+
if (built === undefined)
|
|
82
|
+
throw new Error('expected a schema');
|
|
83
|
+
return built;
|
|
84
|
+
};
|
|
85
|
+
describe('schemaFromCollection', () => {
|
|
86
|
+
it('maps the field types of a post', () => {
|
|
87
|
+
expect(schema()).toMatchSnapshot();
|
|
88
|
+
});
|
|
89
|
+
it('resolves paths through relations with the core schema helpers', () => {
|
|
90
|
+
const built = schema();
|
|
91
|
+
expect(schemaAtPath(built, 'post.title')?.type).toEqual({ t: 'string' });
|
|
92
|
+
expect(schemaAtPath(built, 'post.author.name')?.type).toEqual({ t: 'string' });
|
|
93
|
+
expect(schemaAtPath(built, 'post.author.avatar')?.type).toEqual({ t: 'media' });
|
|
94
|
+
expect(schemaAtPath(built, 'post.seo.title')?.type).toEqual({ t: 'string' });
|
|
95
|
+
expect(schemaAtPath(built, 'post.extra.note')?.type).toEqual({ t: 'string' });
|
|
96
|
+
expect(schemaAtPath(built, 'site.logo')?.type).toEqual({ t: 'media' });
|
|
97
|
+
expect(schemaAtPath(built, 'route.path')?.type).toEqual({ t: 'string' });
|
|
98
|
+
});
|
|
99
|
+
it('never exposes users, credentials, hidden or builder-owned fields', () => {
|
|
100
|
+
const built = schema();
|
|
101
|
+
const json = JSON.stringify(built);
|
|
102
|
+
for (const forbidden of [
|
|
103
|
+
'users',
|
|
104
|
+
'email',
|
|
105
|
+
'role',
|
|
106
|
+
'password',
|
|
107
|
+
'resetPasswordToken',
|
|
108
|
+
'apiKey',
|
|
109
|
+
'secretNotes',
|
|
110
|
+
'salt',
|
|
111
|
+
'token',
|
|
112
|
+
'internalNote',
|
|
113
|
+
'draftOnly',
|
|
114
|
+
'restricted',
|
|
115
|
+
'buildrRevision',
|
|
116
|
+
'_status',
|
|
117
|
+
'layout',
|
|
118
|
+
'sections',
|
|
119
|
+
'raw',
|
|
120
|
+
'where',
|
|
121
|
+
'either',
|
|
122
|
+
'owner',
|
|
123
|
+
'payload-preferences',
|
|
124
|
+
]) {
|
|
125
|
+
expect(json, forbidden).not.toContain(`"${forbidden}"`);
|
|
126
|
+
}
|
|
127
|
+
expect(built.entities['users']).toBeUndefined();
|
|
128
|
+
expect(Object.keys(built.entities).sort()).toEqual(['authors', 'post', 'tags']);
|
|
129
|
+
});
|
|
130
|
+
it('refuses a collection that is an auth collection or internal', () => {
|
|
131
|
+
expect(schemaFromCollection(source, 'users', options)).toBeUndefined();
|
|
132
|
+
expect(schemaFromCollection(source, 'payload-preferences', options)).toBeUndefined();
|
|
133
|
+
expect(schemaFromCollection(source, 'nope', options)).toBeUndefined();
|
|
134
|
+
});
|
|
135
|
+
it('survives relations that point back (authors <-> posts)', () => {
|
|
136
|
+
const built = schema();
|
|
137
|
+
expect(schemaAtPath(built, 'post.author.posts')?.type.t).toBe('list');
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
const doc = {
|
|
141
|
+
id: 7,
|
|
142
|
+
createdAt: '2026-01-02T03:04:05.000Z',
|
|
143
|
+
updatedAt: new Date('2026-02-03T00:00:00Z'),
|
|
144
|
+
title: 'Hello',
|
|
145
|
+
publishedAt: '2026-03-04T05:06:07Z',
|
|
146
|
+
kind: 'news',
|
|
147
|
+
flags: ['a'],
|
|
148
|
+
cover: {
|
|
149
|
+
id: 3,
|
|
150
|
+
url: '/media/cover.jpg',
|
|
151
|
+
alt: 'A cover',
|
|
152
|
+
width: 800,
|
|
153
|
+
height: 600,
|
|
154
|
+
mimeType: 'image/jpeg',
|
|
155
|
+
focalX: 40,
|
|
156
|
+
focalY: 60,
|
|
157
|
+
filename: 'cover.jpg',
|
|
158
|
+
sizes: {
|
|
159
|
+
card: { url: '/media/cover-800.jpg', width: 800, height: 500 },
|
|
160
|
+
og: { url: null, width: null, height: null },
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
gallery: [5, { id: 6, url: '/media/g.jpg', mimeType: 'image/png' }],
|
|
164
|
+
author: {
|
|
165
|
+
id: 2,
|
|
166
|
+
name: 'Ada',
|
|
167
|
+
salt: 'NaCl',
|
|
168
|
+
user: { id: 1, email: 'ada@example.com', password: 'hash' },
|
|
169
|
+
posts: [{ id: 7, title: 'cycle' }],
|
|
170
|
+
},
|
|
171
|
+
tags: [{ id: 1, title: 'one' }, 9],
|
|
172
|
+
owner: { id: 1, email: 'ada@example.com', hash: 'x' },
|
|
173
|
+
seo: { title: 'SEO', internalNote: 'private' },
|
|
174
|
+
facts: [{ label: 'a', value: 1, id: 'row1' }],
|
|
175
|
+
lead: 'Lead',
|
|
176
|
+
extra: { note: 'Note', secret: 'no' },
|
|
177
|
+
sections: [{ blockType: 'x' }],
|
|
178
|
+
password: 'p',
|
|
179
|
+
resetPasswordToken: 't',
|
|
180
|
+
apiKey: 'k',
|
|
181
|
+
layout: { root: 'r' },
|
|
182
|
+
buildrRevision: 4,
|
|
183
|
+
_status: 'draft',
|
|
184
|
+
unknown: 'field',
|
|
185
|
+
};
|
|
186
|
+
describe('normalizeDoc', () => {
|
|
187
|
+
it('turns a populated document into plain, allow-listed data', () => {
|
|
188
|
+
expect(normalizeDoc(source, posts.fields, doc, options.contextNames)).toMatchSnapshot();
|
|
189
|
+
});
|
|
190
|
+
it('never lets a credential or an unlisted field through, at any depth', () => {
|
|
191
|
+
const json = JSON.stringify(normalizeDoc(source, posts.fields, doc, options.contextNames));
|
|
192
|
+
for (const leaked of [
|
|
193
|
+
'ada@example.com',
|
|
194
|
+
'NaCl',
|
|
195
|
+
'hash',
|
|
196
|
+
'private',
|
|
197
|
+
'"k"',
|
|
198
|
+
'blockType',
|
|
199
|
+
'root',
|
|
200
|
+
'field',
|
|
201
|
+
'no',
|
|
202
|
+
]) {
|
|
203
|
+
expect(json).not.toContain(`"${leaked}"`);
|
|
204
|
+
}
|
|
205
|
+
expect(json).not.toContain('ada@example.com');
|
|
206
|
+
expect(json).not.toContain('resetPasswordToken');
|
|
207
|
+
});
|
|
208
|
+
it('keeps an unpopulated relation as { id } and an unpopulated upload as null', () => {
|
|
209
|
+
const value = normalizeDoc(source, posts.fields, { id: 1, author: 4, cover: 3, gallery: [1, 2] }, options.contextNames);
|
|
210
|
+
expect(value['author']).toEqual({ id: '4' });
|
|
211
|
+
expect(value['cover']).toBeNull();
|
|
212
|
+
expect(value['gallery']).toEqual([null, null]);
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
describe('normalizeMedia', () => {
|
|
216
|
+
it('drops sizes without a URL and fills what Payload stores', () => {
|
|
217
|
+
expect(normalizeMedia(doc.cover)).toEqual({
|
|
218
|
+
id: '3',
|
|
219
|
+
url: '/media/cover.jpg',
|
|
220
|
+
alt: 'A cover',
|
|
221
|
+
width: 800,
|
|
222
|
+
height: 600,
|
|
223
|
+
mimeType: 'image/jpeg',
|
|
224
|
+
focalPoint: { x: 40, y: 60 },
|
|
225
|
+
sizes: { card: { url: '/media/cover-800.jpg', width: 800, height: 500 } },
|
|
226
|
+
});
|
|
227
|
+
expect(normalizeMedia(5)).toBeNull();
|
|
228
|
+
expect(normalizeMedia({ id: 1 })).toBeNull();
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
describe('buildContext', () => {
|
|
232
|
+
it('builds site, the document under its context name, and route', () => {
|
|
233
|
+
const scopes = buildContext({
|
|
234
|
+
source,
|
|
235
|
+
options,
|
|
236
|
+
collection: 'posts',
|
|
237
|
+
doc,
|
|
238
|
+
site: { siteName: 'Buildr', token: 'x', logo: doc.cover },
|
|
239
|
+
route: { path: '/posts/hello', locale: 'pl' },
|
|
240
|
+
});
|
|
241
|
+
expect(Object.keys(scopes).sort()).toEqual(['post', 'route', 'site']);
|
|
242
|
+
expect(scopes['site']).toMatchObject({ siteName: 'Buildr', logo: { id: '3' } });
|
|
243
|
+
expect(JSON.stringify(scopes['site'])).not.toContain('token');
|
|
244
|
+
expect(scopes['route']).toEqual({ path: '/posts/hello', locale: 'pl', params: { page: null } });
|
|
245
|
+
expect(scopes['post'].author.name).toBe('Ada');
|
|
246
|
+
});
|
|
247
|
+
it('has the shape of the schema', () => {
|
|
248
|
+
const scopes = buildContext({
|
|
249
|
+
source,
|
|
250
|
+
options,
|
|
251
|
+
collection: 'posts',
|
|
252
|
+
doc,
|
|
253
|
+
route: { path: '/', locale: 'pl' },
|
|
254
|
+
});
|
|
255
|
+
const built = schema();
|
|
256
|
+
const context = scopes['post'];
|
|
257
|
+
const declared = Object.keys(built.scopes['post'].type.fields);
|
|
258
|
+
expect(Object.keys(context).sort()).toEqual(declared.sort());
|
|
259
|
+
expect(scopes['site']).toBeNull(); // no readable site document was given
|
|
260
|
+
});
|
|
261
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type { BuildContextInput } from './build-context.ts';
|
|
2
|
+
export { buildContext } from './build-context.ts';
|
|
3
|
+
export { normalizeDoc, normalizeMedia } from './normalize.ts';
|
|
4
|
+
export type { PayloadDataSourceOptions, QueryableCollection } from './payload-data-source.ts';
|
|
5
|
+
export { createPayloadDataSource, DataQueryError } from './payload-data-source.ts';
|
|
6
|
+
export type { LayoutSource, ResolvedLayout, ResolveLayoutInput, } from './resolve-layout.ts';
|
|
7
|
+
export { builtinLayout, hasContent, resolveLayout } from './resolve-layout.ts';
|
|
8
|
+
export type { CollectionLike, FieldLike, SchemaOptions, SchemaSource, } from './schema-from-fields.ts';
|
|
9
|
+
export { exposedFields, isExposedCollection, schemaFromCollection } from './schema-from-fields.ts';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/data/index.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC9D,YAAY,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC9F,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AACnF,YAAY,EACV,YAAY,EACZ,cAAc,EACd,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC/E,YAAY,EACV,cAAc,EACd,SAAS,EACT,aAAa,EACb,YAAY,GACb,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { buildContext } from './build-context.js';
|
|
2
|
+
export { normalizeDoc, normalizeMedia } from './normalize.js';
|
|
3
|
+
export { createPayloadDataSource, DataQueryError } from './payload-data-source.js';
|
|
4
|
+
export { builtinLayout, hasContent, resolveLayout } from './resolve-layout.js';
|
|
5
|
+
export { exposedFields, isExposedCollection, schemaFromCollection } from './schema-from-fields.js';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { MediaAsset } from '@next-buildr/core';
|
|
2
|
+
import { type FieldLike, type SchemaSource } from './schema-from-fields.ts';
|
|
3
|
+
/**
|
|
4
|
+
* A populated Payload upload document as a `MediaAsset`; an id that was not populated (or a
|
|
5
|
+
* document without a URL) is `null`: the context never carries half a media asset.
|
|
6
|
+
*/
|
|
7
|
+
export declare function normalizeMedia(value: unknown): MediaAsset | null;
|
|
8
|
+
/**
|
|
9
|
+
* A document as plain, JSON-safe data for bindings: only the fields the schema exposes (an
|
|
10
|
+
* allow-list, so nothing else ever leaks), dates as ISO strings, uploads as `MediaAsset`s,
|
|
11
|
+
* relations as plain objects (`{ id }` when they were not populated).
|
|
12
|
+
*/
|
|
13
|
+
export declare function normalizeDoc(source: SchemaSource, fields: readonly FieldLike[], doc: Record<string, unknown>, contextNames?: Readonly<Record<string, string>>): Record<string, unknown>;
|
|
14
|
+
//# sourceMappingURL=normalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/data/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAEL,KAAK,SAAS,EAEd,KAAK,YAAY,EAClB,MAAM,yBAAyB,CAAC;AAcjC;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,GAAG,IAAI,CA+BhE;AAkFD;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,SAAS,SAAS,EAAE,EAC5B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,YAAY,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM,GAClD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAOzB"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { exposedFields, relationTarget, } from './schema-from-fields.js';
|
|
2
|
+
const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
3
|
+
const isoDate = (value) => {
|
|
4
|
+
if (value === null || value === undefined)
|
|
5
|
+
return null;
|
|
6
|
+
const date = value instanceof Date ? value : new Date(String(value));
|
|
7
|
+
return Number.isNaN(date.getTime()) ? null : date.toISOString();
|
|
8
|
+
};
|
|
9
|
+
const num = (value) => typeof value === 'number' && Number.isFinite(value) ? value : undefined;
|
|
10
|
+
/**
|
|
11
|
+
* A populated Payload upload document as a `MediaAsset`; an id that was not populated (or a
|
|
12
|
+
* document without a URL) is `null`: the context never carries half a media asset.
|
|
13
|
+
*/
|
|
14
|
+
export function normalizeMedia(value) {
|
|
15
|
+
if (!isRecord(value) || typeof value['url'] !== 'string' || value['id'] === undefined)
|
|
16
|
+
return null;
|
|
17
|
+
const sizes = {};
|
|
18
|
+
if (isRecord(value['sizes'])) {
|
|
19
|
+
for (const [name, size] of Object.entries(value['sizes'])) {
|
|
20
|
+
if (isRecord(size) && typeof size['url'] === 'string') {
|
|
21
|
+
const width = num(size['width']);
|
|
22
|
+
const height = num(size['height']);
|
|
23
|
+
if (width !== undefined && height !== undefined) {
|
|
24
|
+
sizes[name] = { url: size['url'], width, height };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const focalX = num(value['focalX']);
|
|
30
|
+
const focalY = num(value['focalY']);
|
|
31
|
+
const width = num(value['width']);
|
|
32
|
+
const height = num(value['height']);
|
|
33
|
+
return {
|
|
34
|
+
id: String(value['id']),
|
|
35
|
+
url: value['url'],
|
|
36
|
+
mimeType: typeof value['mimeType'] === 'string' ? value['mimeType'] : '',
|
|
37
|
+
...(typeof value['alt'] === 'string' ? { alt: value['alt'] } : {}),
|
|
38
|
+
...(width === undefined ? {} : { width }),
|
|
39
|
+
...(height === undefined ? {} : { height }),
|
|
40
|
+
...(focalX !== undefined && focalY !== undefined
|
|
41
|
+
? { focalPoint: { x: focalX, y: focalY } }
|
|
42
|
+
: {}),
|
|
43
|
+
...(Object.keys(sizes).length === 0 ? {} : { sizes }),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function normalizeValue(field, value, walk) {
|
|
47
|
+
if (value === null || value === undefined)
|
|
48
|
+
return null;
|
|
49
|
+
if (field.hasMany === true && Array.isArray(value) && field.type !== 'array') {
|
|
50
|
+
return value.map((item) => normalizeValue({ ...field, hasMany: false }, item, walk));
|
|
51
|
+
}
|
|
52
|
+
switch (field.type) {
|
|
53
|
+
case 'date':
|
|
54
|
+
return isoDate(value);
|
|
55
|
+
case 'upload':
|
|
56
|
+
return normalizeMedia(value);
|
|
57
|
+
case 'relationship': {
|
|
58
|
+
const slug = relationTarget(field, walk.source);
|
|
59
|
+
if (slug === undefined)
|
|
60
|
+
return null;
|
|
61
|
+
if (!isRecord(value))
|
|
62
|
+
return { id: String(value) };
|
|
63
|
+
const id = String(value['id']);
|
|
64
|
+
const target = walk.source.collections.find((candidate) => candidate.slug === slug);
|
|
65
|
+
// Not populated (or a cycle): the id is all there is; never the raw document.
|
|
66
|
+
if (target === undefined || walk.trail.includes(`${slug}:${id}`))
|
|
67
|
+
return { id };
|
|
68
|
+
return {
|
|
69
|
+
id,
|
|
70
|
+
...normalizeFields(target.fields, value, {
|
|
71
|
+
...walk,
|
|
72
|
+
trail: [...walk.trail, `${slug}:${id}`],
|
|
73
|
+
}),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
case 'group':
|
|
77
|
+
return isRecord(value) ? normalizeFields(field.fields ?? [], value, walk) : null;
|
|
78
|
+
case 'array':
|
|
79
|
+
return Array.isArray(value)
|
|
80
|
+
? value.map((row) => isRecord(row) ? normalizeFields(field.fields ?? [], row, walk) : null)
|
|
81
|
+
: null;
|
|
82
|
+
case 'richText':
|
|
83
|
+
return value;
|
|
84
|
+
default:
|
|
85
|
+
return value;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function normalizeFields(fields, doc, walk) {
|
|
89
|
+
const result = {};
|
|
90
|
+
for (const field of exposedFields(fields)) {
|
|
91
|
+
// Types the schema does not expose (blocks, json, ...) have no `case` above that keeps them.
|
|
92
|
+
if (!EXPOSED_TYPES.has(field.type))
|
|
93
|
+
continue;
|
|
94
|
+
// A relation the schema drops (to users, or polymorphic) is dropped here too.
|
|
95
|
+
if (field.type === 'relationship' && relationTarget(field, walk.source) === undefined)
|
|
96
|
+
continue;
|
|
97
|
+
result[field.name] = normalizeValue(field, doc[field.name], walk);
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
const EXPOSED_TYPES = new Set([
|
|
102
|
+
'text',
|
|
103
|
+
'textarea',
|
|
104
|
+
'email',
|
|
105
|
+
'number',
|
|
106
|
+
'checkbox',
|
|
107
|
+
'date',
|
|
108
|
+
'select',
|
|
109
|
+
'radio',
|
|
110
|
+
'richText',
|
|
111
|
+
'upload',
|
|
112
|
+
'relationship',
|
|
113
|
+
'group',
|
|
114
|
+
'array',
|
|
115
|
+
]);
|
|
116
|
+
/**
|
|
117
|
+
* A document as plain, JSON-safe data for bindings: only the fields the schema exposes (an
|
|
118
|
+
* allow-list, so nothing else ever leaks), dates as ISO strings, uploads as `MediaAsset`s,
|
|
119
|
+
* relations as plain objects (`{ id }` when they were not populated).
|
|
120
|
+
*/
|
|
121
|
+
export function normalizeDoc(source, fields, doc, contextNames = {}) {
|
|
122
|
+
return {
|
|
123
|
+
id: doc['id'] === undefined ? null : String(doc['id']),
|
|
124
|
+
createdAt: isoDate(doc['createdAt']),
|
|
125
|
+
updatedAt: isoDate(doc['updatedAt']),
|
|
126
|
+
...normalizeFields(fields, doc, { source, names: contextNames, trail: [] }),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type DataSource } from '@next-buildr/core';
|
|
2
|
+
import type { Payload, PayloadRequest } from 'payload';
|
|
3
|
+
/** What a collection may be queried by: the fields (as query paths) and the sort keys. */
|
|
4
|
+
export interface QueryableCollection {
|
|
5
|
+
readonly fields: readonly string[];
|
|
6
|
+
readonly sort: readonly string[];
|
|
7
|
+
}
|
|
8
|
+
export interface PayloadDataSourceOptions {
|
|
9
|
+
readonly payload: Payload;
|
|
10
|
+
/** The request whose user's access applies; without one the source reads as an anonymous visitor. */
|
|
11
|
+
readonly req?: PayloadRequest | undefined;
|
|
12
|
+
/** The allowlist: only these collections, with only these fields and sort keys. */
|
|
13
|
+
readonly queryable: Readonly<Record<string, QueryableCollection>>;
|
|
14
|
+
/** The collection `getMedia` reads. */
|
|
15
|
+
readonly mediaCollection?: string | undefined;
|
|
16
|
+
/** The name each collection is bound under (`post`, ...), as in the data schema. */
|
|
17
|
+
readonly contextNames?: Readonly<Record<string, string>> | undefined;
|
|
18
|
+
/** How deep relations are populated in the items (default 1: `author.name` works). */
|
|
19
|
+
readonly depth?: number | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* The address of a queried document, exposed to bindings as `item.path` (a card that links to its
|
|
22
|
+
* post). The application knows its routes and how a locale enters them; without it items have no `path`.
|
|
23
|
+
*/
|
|
24
|
+
readonly itemPath?: ((collection: string, doc: Record<string, unknown>, locale: string) => string | undefined) | undefined;
|
|
25
|
+
/** How many documents the in-memory pass may look at (default 1000). */
|
|
26
|
+
readonly scanLimit?: number | undefined;
|
|
27
|
+
}
|
|
28
|
+
/** A query that cannot be answered: not allowlisted, malformed, or too broad. */
|
|
29
|
+
export declare class DataQueryError extends Error {
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The server `DataSource` (ADR-018): queries and media served from Payload's Local API, held to
|
|
33
|
+
* the same contract suite as `MemoryDataSource`. Every call runs with the access of the request's
|
|
34
|
+
* user (`overrideAccess: false`); production reads published documents only.
|
|
35
|
+
*
|
|
36
|
+
* Conditions Payload evaluates like the contract (typed scalars, missing values) go to the
|
|
37
|
+
* database, so paging and totals are the database's. What it cannot (a case-sensitive `contains`,
|
|
38
|
+
* lists, an optional sort key: missing values must sort last in both directions) is decided by the
|
|
39
|
+
* memory source over at most `scanLimit` candidates the database already narrowed.
|
|
40
|
+
*/
|
|
41
|
+
export declare function createPayloadDataSource(options: PayloadDataSourceOptions): DataSource;
|
|
42
|
+
//# sourceMappingURL=payload-data-source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payload-data-source.d.ts","sourceRoot":"","sources":["../../src/data/payload-data-source.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,UAAU,EAOhB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAS,MAAM,SAAS,CAAC;AAY9D,0FAA0F;AAC1F,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,qGAAqG;IACrG,QAAQ,CAAC,GAAG,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IAC1C,mFAAmF;IACnF,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC;IAClE,uCAAuC;IACvC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9C,oFAAoF;IACpF,QAAQ,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC;IACrE,sFAAsF;IACtF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EACd,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC,GAC1F,SAAS,CAAC;IACd,wEAAwE;IACxE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACzC;AAID,iFAAiF;AACjF,qBAAa,cAAe,SAAQ,KAAK;CAAG;AAM5C;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,wBAAwB,GAAG,UAAU,CA6KrF"}
|