@byline/core 3.14.0 → 3.15.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/dist/@types/admin-types.d.ts +45 -7
- package/dist/@types/collection-types.d.ts +32 -4
- package/dist/@types/field-types.d.ts +22 -0
- package/dist/@types/index.d.ts +1 -0
- package/dist/@types/index.js +1 -0
- package/dist/@types/search-types.d.ts +275 -0
- package/dist/@types/search-types.js +8 -0
- package/dist/@types/site-config.d.ts +31 -1
- package/dist/auth/assert-actor-can-perform.test.node.js +9 -1
- package/dist/auth/register-collection-abilities.d.ts +8 -5
- package/dist/auth/register-collection-abilities.js +14 -4
- package/dist/auth/register-collection-abilities.test.node.js +11 -7
- package/dist/config/config.d.ts +12 -1
- package/dist/config/config.js +11 -0
- package/dist/config/resolve-item-view-columns.test.node.d.ts +8 -0
- package/dist/config/resolve-item-view-columns.test.node.js +30 -0
- package/dist/core.js +7 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/services/build-search-document.d.ts +46 -0
- package/dist/services/build-search-document.js +220 -0
- package/dist/services/build-search-document.test.node.d.ts +8 -0
- package/dist/services/build-search-document.test.node.js +164 -0
- package/dist/services/index.d.ts +3 -1
- package/dist/services/index.js +3 -1
- package/dist/services/populate.d.ts +6 -0
- package/dist/services/populate.js +1 -1
- package/dist/services/relation-projection.d.ts +4 -15
- package/dist/services/relation-projection.js +19 -6
- package/dist/services/validate-search-config.d.ts +28 -0
- package/dist/services/validate-search-config.js +32 -0
- package/dist/storage/collection-fingerprint.test.node.js +1 -1
- package/package.json +2 -2
package/dist/services/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
export { ERR_CONFLICT, ERR_INVALID_TRANSITION, ERR_NOT_FOUND, ERR_PATCH_FAILED, ERR_READ_BUDGET_EXCEEDED, ERR_VALIDATION, } from '../lib/errors.js';
|
|
3
3
|
export { normaliseDateFields } from '../utils/normalise-dates.js';
|
|
4
4
|
export { assignCounterValues } from './assign-counter-values.js';
|
|
5
|
+
export { buildSearchDocument, } from './build-search-document.js';
|
|
5
6
|
export { ensureCollections, } from './collection-bootstrap.js';
|
|
6
7
|
export { discoverCounterGroups, } from './discover-counter-groups.js';
|
|
7
8
|
export * from './document-lifecycle/index.js';
|
|
@@ -9,8 +10,9 @@ export * from './document-read.js';
|
|
|
9
10
|
export * from './document-to-markdown.js';
|
|
10
11
|
export * from './field-upload.js';
|
|
11
12
|
export { validateTranslations, } from './i18n-validator.js';
|
|
12
|
-
export { createReadContext, populateDocuments, } from './populate.js';
|
|
13
|
+
export { createReadContext, populateDocuments, resolveIdentityField, } from './populate.js';
|
|
13
14
|
export { buildRelationSummaryPopulateMap, resolveRelationProjection, } from './relation-projection.js';
|
|
14
15
|
export { embedRichTextFields, resolveEmbedOnSave, } from './richtext-embed.js';
|
|
15
16
|
export { collectRichTextLeaves, populateRichTextFields, resolvePopulateOnRead, validateRichTextFieldFlags, } from './richtext-populate.js';
|
|
17
|
+
export { validateSearchConfig, } from './validate-search-config.js';
|
|
16
18
|
export { walkFieldTree } from './walk-field-tree.js';
|
|
@@ -276,6 +276,12 @@ declare function matchesPopulate(fieldName: string, populate: PopulateSpec): Pop
|
|
|
276
276
|
* not need to appear in the `fields` list.
|
|
277
277
|
*/
|
|
278
278
|
declare function buildBatchSelect(leaves: RelationLeafRef[], targetDef: CollectionDefinition | undefined): string[] | undefined;
|
|
279
|
+
/**
|
|
280
|
+
* The field that represents a target document's identity for populate's
|
|
281
|
+
* default projection. Prefers `useAsTitle` (server-safe schema-level
|
|
282
|
+
* config), falling back to the first declared text field.
|
|
283
|
+
*/
|
|
284
|
+
export declare function resolveIdentityField(def: CollectionDefinition): string | undefined;
|
|
279
285
|
/**
|
|
280
286
|
* Merge the per-leaf sub-populate specs for all leaves pointing at a
|
|
281
287
|
* single (now-populated) target document into a single PopulateSpec for
|
|
@@ -405,7 +405,7 @@ function buildBatchSelect(leaves, targetDef) {
|
|
|
405
405
|
* default projection. Prefers `useAsTitle` (server-safe schema-level
|
|
406
406
|
* config), falling back to the first declared text field.
|
|
407
407
|
*/
|
|
408
|
-
function resolveIdentityField(def) {
|
|
408
|
+
export function resolveIdentityField(def) {
|
|
409
409
|
if (def.useAsTitle)
|
|
410
410
|
return def.useAsTitle;
|
|
411
411
|
const firstText = def.fields.find((f) => f.type === 'text');
|
|
@@ -5,17 +5,6 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Copyright (c) Infonomic Company Limited
|
|
7
7
|
*/
|
|
8
|
-
/**
|
|
9
|
-
* Relation projection helpers.
|
|
10
|
-
*
|
|
11
|
-
* Translate a source collection's relation fields into a `PopulateMap`
|
|
12
|
-
* projection that fetches just enough data from each target to render
|
|
13
|
-
* a relation-summary tile on the admin edit view (picker columns,
|
|
14
|
-
* `useAsTitle`, plus an optional source-side `displayField` override).
|
|
15
|
-
*
|
|
16
|
-
* Consumed by the admin webapp's edit-route server fn so relation tiles
|
|
17
|
-
* arrive pre-hydrated on first paint — no client-side fetch per relation.
|
|
18
|
-
*/
|
|
19
8
|
import type { CollectionAdminConfig, CollectionDefinition, FieldSet, RelationField } from '../@types/index.js';
|
|
20
9
|
import type { PopulateMap } from './populate.js';
|
|
21
10
|
/**
|
|
@@ -25,10 +14,10 @@ import type { PopulateMap } from './populate.js';
|
|
|
25
14
|
* - `sourceField.displayField` (explicit per-relation override)
|
|
26
15
|
* - target's `useAsTitle`
|
|
27
16
|
* - target's first declared text field (safety fallback)
|
|
28
|
-
* - every `
|
|
29
|
-
* to a real schema field (
|
|
30
|
-
* like `status` or `updated_at` which ride on the document row
|
|
31
|
-
*
|
|
17
|
+
* - every item-view column `fieldName` on the target admin config that
|
|
18
|
+
* maps to a real schema field (item-view columns may reference metadata
|
|
19
|
+
* like `status` or `updated_at` which ride on the document row and don't
|
|
20
|
+
* need a projection entry)
|
|
32
21
|
*/
|
|
33
22
|
export declare function resolveRelationProjection(sourceField: RelationField, targetDef: CollectionDefinition | null, targetAdmin: CollectionAdminConfig | null): string[];
|
|
34
23
|
export type RelationTargetResolver = (targetPath: string) => {
|
|
@@ -5,6 +5,18 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Copyright (c) Infonomic Company Limited
|
|
7
7
|
*/
|
|
8
|
+
/**
|
|
9
|
+
* Relation projection helpers.
|
|
10
|
+
*
|
|
11
|
+
* Translate a source collection's relation fields into a `PopulateMap`
|
|
12
|
+
* projection that fetches just enough data from each target to render
|
|
13
|
+
* a relation-summary tile on the admin edit view (picker columns,
|
|
14
|
+
* `useAsTitle`, plus an optional source-side `displayField` override).
|
|
15
|
+
*
|
|
16
|
+
* Consumed by the admin webapp's edit-route server fn so relation tiles
|
|
17
|
+
* arrive pre-hydrated on first paint — no client-side fetch per relation.
|
|
18
|
+
*/
|
|
19
|
+
import { resolveItemViewColumns } from '../config/config.js';
|
|
8
20
|
/**
|
|
9
21
|
* Union of the target-collection field names needed to render a
|
|
10
22
|
* relation-summary tile for the given source relation field.
|
|
@@ -12,10 +24,10 @@
|
|
|
12
24
|
* - `sourceField.displayField` (explicit per-relation override)
|
|
13
25
|
* - target's `useAsTitle`
|
|
14
26
|
* - target's first declared text field (safety fallback)
|
|
15
|
-
* - every `
|
|
16
|
-
* to a real schema field (
|
|
17
|
-
* like `status` or `updated_at` which ride on the document row
|
|
18
|
-
*
|
|
27
|
+
* - every item-view column `fieldName` on the target admin config that
|
|
28
|
+
* maps to a real schema field (item-view columns may reference metadata
|
|
29
|
+
* like `status` or `updated_at` which ride on the document row and don't
|
|
30
|
+
* need a projection entry)
|
|
19
31
|
*/
|
|
20
32
|
export function resolveRelationProjection(sourceField, targetDef, targetAdmin) {
|
|
21
33
|
const out = new Set();
|
|
@@ -26,8 +38,9 @@ export function resolveRelationProjection(sourceField, targetDef, targetAdmin) {
|
|
|
26
38
|
const firstText = targetDef?.fields.find((f) => f.type === 'text')?.name;
|
|
27
39
|
if (firstText)
|
|
28
40
|
out.add(firstText);
|
|
29
|
-
|
|
30
|
-
|
|
41
|
+
const itemViewColumns = resolveItemViewColumns(targetAdmin);
|
|
42
|
+
if (itemViewColumns) {
|
|
43
|
+
for (const col of itemViewColumns) {
|
|
31
44
|
const name = String(col.fieldName);
|
|
32
45
|
if (targetDef?.fields.some((f) => f.name === name))
|
|
33
46
|
out.add(name);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) Infonomic Company Limited
|
|
7
|
+
*/
|
|
8
|
+
import type { CollectionDefinition } from '../@types/collection-types.js';
|
|
9
|
+
/** Whether a `SearchProvider` is registered on `ServerConfig.search`. */
|
|
10
|
+
export interface SearchProviderPresence {
|
|
11
|
+
/** `ServerConfig.search != null` */
|
|
12
|
+
provider: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Validate search configuration across every collection. Throws when any
|
|
16
|
+
* collection opts into search (`CollectionDefinition.search`) but no
|
|
17
|
+
* `SearchProvider` is registered on `ServerConfig.search` — otherwise
|
|
18
|
+
* indexing and `client.search()` would silently no-op.
|
|
19
|
+
*
|
|
20
|
+
* Called once at `initBylineCore()` time, right after the richText field
|
|
21
|
+
* validation. Fail-fast at boot is the right posture; the alternative is a
|
|
22
|
+
* collection that declares it's searchable but never gets indexed.
|
|
23
|
+
*
|
|
24
|
+
* Note: a missing provider is only an error when at least one collection
|
|
25
|
+
* actually opts in. Installations that don't use search leave
|
|
26
|
+
* `ServerConfig.search` unset and pass cleanly.
|
|
27
|
+
*/
|
|
28
|
+
export declare function validateSearchConfig(collections: CollectionDefinition[], adapters: SearchProviderPresence): void;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) Infonomic Company Limited
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Validate search configuration across every collection. Throws when any
|
|
10
|
+
* collection opts into search (`CollectionDefinition.search`) but no
|
|
11
|
+
* `SearchProvider` is registered on `ServerConfig.search` — otherwise
|
|
12
|
+
* indexing and `client.search()` would silently no-op.
|
|
13
|
+
*
|
|
14
|
+
* Called once at `initBylineCore()` time, right after the richText field
|
|
15
|
+
* validation. Fail-fast at boot is the right posture; the alternative is a
|
|
16
|
+
* collection that declares it's searchable but never gets indexed.
|
|
17
|
+
*
|
|
18
|
+
* Note: a missing provider is only an error when at least one collection
|
|
19
|
+
* actually opts in. Installations that don't use search leave
|
|
20
|
+
* `ServerConfig.search` unset and pass cleanly.
|
|
21
|
+
*/
|
|
22
|
+
export function validateSearchConfig(collections, adapters) {
|
|
23
|
+
if (adapters.provider)
|
|
24
|
+
return;
|
|
25
|
+
const optedIn = collections.filter((def) => def.search != null).map((def) => def.path);
|
|
26
|
+
if (optedIn.length === 0)
|
|
27
|
+
return;
|
|
28
|
+
throw new Error(`initBylineCore: ${optedIn.length} collection(s) opt into search ` +
|
|
29
|
+
`(${optedIn.join(', ')}) but no search provider is registered. ` +
|
|
30
|
+
`Wire one via ServerConfig.search — see \`@byline/search-postgres\` → ` +
|
|
31
|
+
`\`postgresSearch()\` for the built-in Postgres full-text driver.`);
|
|
32
|
+
}
|
|
@@ -89,7 +89,7 @@ describe('fingerprintCollection', () => {
|
|
|
89
89
|
it('ignores search / showStats (admin UX only)', async () => {
|
|
90
90
|
const a = await fingerprintCollection(baseCollection());
|
|
91
91
|
const b = baseCollection();
|
|
92
|
-
b.search = {
|
|
92
|
+
b.search = { body: ['title', 'body.heading'] };
|
|
93
93
|
b.showStats = true;
|
|
94
94
|
expect(await fingerprintCollection(b)).toBe(a);
|
|
95
95
|
});
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@byline/core",
|
|
3
3
|
"private": false,
|
|
4
4
|
"license": "MPL-2.0",
|
|
5
|
-
"version": "3.
|
|
5
|
+
"version": "3.15.0",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": ">=20.9.0"
|
|
8
8
|
},
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
"sharp": "^0.34.5",
|
|
80
80
|
"uuid": "^14.0.0",
|
|
81
81
|
"zod": "^4.4.3",
|
|
82
|
-
"@byline/auth": "3.
|
|
82
|
+
"@byline/auth": "3.15.0"
|
|
83
83
|
},
|
|
84
84
|
"devDependencies": {
|
|
85
85
|
"@biomejs/biome": "2.4.15",
|