@byline/core 0.9.3
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 +373 -0
- package/README.md +17 -0
- package/dist/@types/admin-types.d.ts +275 -0
- package/dist/@types/admin-types.d.ts.map +1 -0
- package/dist/@types/admin-types.js +18 -0
- package/dist/@types/admin-types.js.map +1 -0
- package/dist/@types/collection-types.d.ts +816 -0
- package/dist/@types/collection-types.d.ts.map +1 -0
- package/dist/@types/collection-types.js +217 -0
- package/dist/@types/collection-types.js.map +1 -0
- package/dist/@types/db-types.d.ts +463 -0
- package/dist/@types/db-types.d.ts.map +1 -0
- package/dist/@types/db-types.js +2 -0
- package/dist/@types/db-types.js.map +1 -0
- package/dist/@types/field-data-types.d.ts +147 -0
- package/dist/@types/field-data-types.d.ts.map +1 -0
- package/dist/@types/field-data-types.js +38 -0
- package/dist/@types/field-data-types.js.map +1 -0
- package/dist/@types/field-types.d.ts +579 -0
- package/dist/@types/field-types.d.ts.map +1 -0
- package/dist/@types/field-types.js +32 -0
- package/dist/@types/field-types.js.map +1 -0
- package/dist/@types/index.d.ts +18 -0
- package/dist/@types/index.d.ts.map +1 -0
- package/dist/@types/index.js +18 -0
- package/dist/@types/index.js.map +1 -0
- package/dist/@types/populate-types.d.ts +54 -0
- package/dist/@types/populate-types.d.ts.map +1 -0
- package/dist/@types/populate-types.js +9 -0
- package/dist/@types/populate-types.js.map +1 -0
- package/dist/@types/query-predicate.d.ts +74 -0
- package/dist/@types/query-predicate.d.ts.map +1 -0
- package/dist/@types/query-predicate.js +9 -0
- package/dist/@types/query-predicate.js.map +1 -0
- package/dist/@types/site-config.d.ts +212 -0
- package/dist/@types/site-config.d.ts.map +1 -0
- package/dist/@types/site-config.js +9 -0
- package/dist/@types/site-config.js.map +1 -0
- package/dist/@types/storage-types.d.ts +86 -0
- package/dist/@types/storage-types.d.ts.map +1 -0
- package/dist/@types/storage-types.js +9 -0
- package/dist/@types/storage-types.js.map +1 -0
- package/dist/@types/store-types.d.ts +134 -0
- package/dist/@types/store-types.d.ts.map +1 -0
- package/dist/@types/store-types.js +24 -0
- package/dist/@types/store-types.js.map +1 -0
- package/dist/@types/type-utils.d.ts +17 -0
- package/dist/@types/type-utils.d.ts.map +1 -0
- package/dist/@types/type-utils.js +9 -0
- package/dist/@types/type-utils.js.map +1 -0
- package/dist/auth/apply-before-read.d.ts +36 -0
- package/dist/auth/apply-before-read.d.ts.map +1 -0
- package/dist/auth/apply-before-read.js +68 -0
- package/dist/auth/apply-before-read.js.map +1 -0
- package/dist/auth/apply-before-read.test.node.d.ts +9 -0
- package/dist/auth/apply-before-read.test.node.d.ts.map +1 -0
- package/dist/auth/apply-before-read.test.node.js +144 -0
- package/dist/auth/apply-before-read.test.node.js.map +1 -0
- package/dist/auth/assert-actor-can-perform.d.ts +39 -0
- package/dist/auth/assert-actor-can-perform.d.ts.map +1 -0
- package/dist/auth/assert-actor-can-perform.js +64 -0
- package/dist/auth/assert-actor-can-perform.js.map +1 -0
- package/dist/auth/assert-actor-can-perform.test.node.d.ts +9 -0
- package/dist/auth/assert-actor-can-perform.test.node.d.ts.map +1 -0
- package/dist/auth/assert-actor-can-perform.test.node.js +119 -0
- package/dist/auth/assert-actor-can-perform.test.node.js.map +1 -0
- package/dist/auth/index.d.ts +11 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +11 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/register-collection-abilities.d.ts +40 -0
- package/dist/auth/register-collection-abilities.d.ts.map +1 -0
- package/dist/auth/register-collection-abilities.js +87 -0
- package/dist/auth/register-collection-abilities.js.map +1 -0
- package/dist/auth/register-collection-abilities.test.node.d.ts +9 -0
- package/dist/auth/register-collection-abilities.test.node.d.ts.map +1 -0
- package/dist/auth/register-collection-abilities.test.node.js +124 -0
- package/dist/auth/register-collection-abilities.test.node.js.map +1 -0
- package/dist/config/config.d.ts +10 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +108 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/routes.d.ts +16 -0
- package/dist/config/routes.d.ts.map +1 -0
- package/dist/config/routes.js +26 -0
- package/dist/config/routes.js.map +1 -0
- package/dist/config/validate-admin-configs.d.ts +33 -0
- package/dist/config/validate-admin-configs.d.ts.map +1 -0
- package/dist/config/validate-admin-configs.js +250 -0
- package/dist/config/validate-admin-configs.js.map +1 -0
- package/dist/config/validate-admin-configs.test.node.d.ts +9 -0
- package/dist/config/validate-admin-configs.test.node.d.ts.map +1 -0
- package/dist/config/validate-admin-configs.test.node.js +224 -0
- package/dist/config/validate-admin-configs.test.node.js.map +1 -0
- package/dist/config/validate-collections.d.ts +33 -0
- package/dist/config/validate-collections.d.ts.map +1 -0
- package/dist/config/validate-collections.js +70 -0
- package/dist/config/validate-collections.js.map +1 -0
- package/dist/config/validate-collections.test.node.d.ts +9 -0
- package/dist/config/validate-collections.test.node.d.ts.map +1 -0
- package/dist/config/validate-collections.test.node.js +149 -0
- package/dist/config/validate-collections.test.node.js.map +1 -0
- package/dist/core.d.ts +89 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +99 -0
- package/dist/core.js.map +1 -0
- package/dist/defaults/default-values.d.ts +13 -0
- package/dist/defaults/default-values.d.ts.map +1 -0
- package/dist/defaults/default-values.js +60 -0
- package/dist/defaults/default-values.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/errors.d.ts +98 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +134 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/logger.d.ts +62 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +120 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/registry.d.ts +65 -0
- package/dist/lib/registry.d.ts.map +1 -0
- package/dist/lib/registry.js +133 -0
- package/dist/lib/registry.js.map +1 -0
- package/dist/logger/index.d.ts +3 -0
- package/dist/logger/index.d.ts.map +1 -0
- package/dist/logger/index.js +3 -0
- package/dist/logger/index.js.map +1 -0
- package/dist/patches/apply-patches.d.ts +21 -0
- package/dist/patches/apply-patches.d.ts.map +1 -0
- package/dist/patches/apply-patches.js +357 -0
- package/dist/patches/apply-patches.js.map +1 -0
- package/dist/patches/index.d.ts +3 -0
- package/dist/patches/index.d.ts.map +1 -0
- package/dist/patches/index.js +4 -0
- package/dist/patches/index.js.map +1 -0
- package/dist/patches/patch-types.d.ts +82 -0
- package/dist/patches/patch-types.d.ts.map +1 -0
- package/dist/patches/patch-types.js +3 -0
- package/dist/patches/patch-types.js.map +1 -0
- package/dist/patches/patch.test.node.d.ts +2 -0
- package/dist/patches/patch.test.node.d.ts.map +1 -0
- package/dist/patches/patch.test.node.js +193 -0
- package/dist/patches/patch.test.node.js.map +1 -0
- package/dist/query/parse-where.d.ts +100 -0
- package/dist/query/parse-where.d.ts.map +1 -0
- package/dist/query/parse-where.js +352 -0
- package/dist/query/parse-where.js.map +1 -0
- package/dist/query/parse-where.test.node.d.ts +9 -0
- package/dist/query/parse-where.test.node.d.ts.map +1 -0
- package/dist/query/parse-where.test.node.js +581 -0
- package/dist/query/parse-where.test.node.js.map +1 -0
- package/dist/schemas/zod/builder.d.ts +466 -0
- package/dist/schemas/zod/builder.d.ts.map +1 -0
- package/dist/schemas/zod/builder.js +276 -0
- package/dist/schemas/zod/builder.js.map +1 -0
- package/dist/schemas/zod/cache.d.ts +14 -0
- package/dist/schemas/zod/cache.d.ts.map +1 -0
- package/dist/schemas/zod/cache.js +40 -0
- package/dist/schemas/zod/cache.js.map +1 -0
- package/dist/schemas/zod/index.d.ts +4 -0
- package/dist/schemas/zod/index.d.ts.map +1 -0
- package/dist/schemas/zod/index.js +4 -0
- package/dist/schemas/zod/index.js.map +1 -0
- package/dist/schemas/zod/types.d.ts +13 -0
- package/dist/schemas/zod/types.d.ts.map +1 -0
- package/dist/schemas/zod/types.js +2 -0
- package/dist/schemas/zod/types.js.map +1 -0
- package/dist/services/collection-bootstrap.d.ts +46 -0
- package/dist/services/collection-bootstrap.d.ts.map +1 -0
- package/dist/services/collection-bootstrap.js +108 -0
- package/dist/services/collection-bootstrap.js.map +1 -0
- package/dist/services/collection-bootstrap.test.node.d.ts +9 -0
- package/dist/services/collection-bootstrap.test.node.d.ts.map +1 -0
- package/dist/services/collection-bootstrap.test.node.js +208 -0
- package/dist/services/collection-bootstrap.test.node.js.map +1 -0
- package/dist/services/document-lifecycle.d.ts +245 -0
- package/dist/services/document-lifecycle.d.ts.map +1 -0
- package/dist/services/document-lifecycle.js +481 -0
- package/dist/services/document-lifecycle.js.map +1 -0
- package/dist/services/document-lifecycle.test.node.d.ts +9 -0
- package/dist/services/document-lifecycle.test.node.d.ts.map +1 -0
- package/dist/services/document-lifecycle.test.node.js +781 -0
- package/dist/services/document-lifecycle.test.node.js.map +1 -0
- package/dist/services/document-read.d.ts +26 -0
- package/dist/services/document-read.d.ts.map +1 -0
- package/dist/services/document-read.js +60 -0
- package/dist/services/document-read.js.map +1 -0
- package/dist/services/field-upload.d.ts +100 -0
- package/dist/services/field-upload.d.ts.map +1 -0
- package/dist/services/field-upload.js +328 -0
- package/dist/services/field-upload.js.map +1 -0
- package/dist/services/field-upload.test.node.d.ts +9 -0
- package/dist/services/field-upload.test.node.d.ts.map +1 -0
- package/dist/services/field-upload.test.node.js +337 -0
- package/dist/services/field-upload.test.node.js.map +1 -0
- package/dist/services/index.d.ts +10 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +11 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/populate.d.ts +299 -0
- package/dist/services/populate.d.ts.map +1 -0
- package/dist/services/populate.js +484 -0
- package/dist/services/populate.js.map +1 -0
- package/dist/services/populate.test.node.d.ts +9 -0
- package/dist/services/populate.test.node.d.ts.map +1 -0
- package/dist/services/populate.test.node.js +910 -0
- package/dist/services/populate.test.node.js.map +1 -0
- package/dist/services/relation-projection.d.ts +52 -0
- package/dist/services/relation-projection.d.ts.map +1 -0
- package/dist/services/relation-projection.js +81 -0
- package/dist/services/relation-projection.js.map +1 -0
- package/dist/services/richtext-populate.d.ts +87 -0
- package/dist/services/richtext-populate.d.ts.map +1 -0
- package/dist/services/richtext-populate.js +189 -0
- package/dist/services/richtext-populate.js.map +1 -0
- package/dist/services/richtext-populate.test.node.d.ts +9 -0
- package/dist/services/richtext-populate.test.node.d.ts.map +1 -0
- package/dist/services/richtext-populate.test.node.js +197 -0
- package/dist/services/richtext-populate.test.node.js.map +1 -0
- package/dist/storage/collection-fingerprint.d.ts +21 -0
- package/dist/storage/collection-fingerprint.d.ts.map +1 -0
- package/dist/storage/collection-fingerprint.js +172 -0
- package/dist/storage/collection-fingerprint.js.map +1 -0
- package/dist/storage/collection-fingerprint.test.node.d.ts +9 -0
- package/dist/storage/collection-fingerprint.test.node.d.ts.map +1 -0
- package/dist/storage/collection-fingerprint.test.node.js +256 -0
- package/dist/storage/collection-fingerprint.test.node.js.map +1 -0
- package/dist/storage/field-store-map.d.ts +59 -0
- package/dist/storage/field-store-map.d.ts.map +1 -0
- package/dist/storage/field-store-map.js +75 -0
- package/dist/storage/field-store-map.js.map +1 -0
- package/dist/storage/field-store-map.test.node.d.ts +9 -0
- package/dist/storage/field-store-map.test.node.d.ts.map +1 -0
- package/dist/storage/field-store-map.test.node.js +117 -0
- package/dist/storage/field-store-map.test.node.js.map +1 -0
- package/dist/storage/index.d.ts +10 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +10 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/utils/normalise-dates.d.ts +15 -0
- package/dist/utils/normalise-dates.d.ts.map +1 -0
- package/dist/utils/normalise-dates.js +22 -0
- package/dist/utils/normalise-dates.js.map +1 -0
- package/dist/utils/slugify.d.ts +56 -0
- package/dist/utils/slugify.d.ts.map +1 -0
- package/dist/utils/slugify.js +91 -0
- package/dist/utils/slugify.js.map +1 -0
- package/dist/utils/slugify.test.node.d.ts +9 -0
- package/dist/utils/slugify.test.node.d.ts.map +1 -0
- package/dist/utils/slugify.test.node.js +86 -0
- package/dist/utils/slugify.test.node.js.map +1 -0
- package/dist/utils/storage-utils.d.ts +36 -0
- package/dist/utils/storage-utils.d.ts.map +1 -0
- package/dist/utils/storage-utils.js +38 -0
- package/dist/utils/storage-utils.js.map +1 -0
- package/dist/utils/utils.general.d.ts +64 -0
- package/dist/utils/utils.general.d.ts.map +1 -0
- package/dist/utils/utils.general.js +219 -0
- package/dist/utils/utils.general.js.map +1 -0
- package/dist/validation/index.d.ts +9 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/index.js +9 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/shared.d.ts +36 -0
- package/dist/validation/shared.d.ts.map +1 -0
- package/dist/validation/shared.js +42 -0
- package/dist/validation/shared.js.map +1 -0
- package/dist/workflow/index.d.ts +2 -0
- package/dist/workflow/index.d.ts.map +1 -0
- package/dist/workflow/index.js +3 -0
- package/dist/workflow/index.js.map +1 -0
- package/dist/workflow/workflow.d.ts +40 -0
- package/dist/workflow/workflow.d.ts.map +1 -0
- package/dist/workflow/workflow.js +96 -0
- package/dist/workflow/workflow.js.map +1 -0
- package/dist/workflow/workflow.test.node.d.ts +2 -0
- package/dist/workflow/workflow.test.node.d.ts.map +1 -0
- package/dist/workflow/workflow.test.node.js +198 -0
- package/dist/workflow/workflow.test.node.js.map +1 -0
- package/package.json +88 -0
|
@@ -0,0 +1,33 @@
|
|
|
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 { CollectionAdminConfig, CollectionDefinition } from '../@types/index.js';
|
|
9
|
+
/**
|
|
10
|
+
* Validate every admin config in a configuration.
|
|
11
|
+
*
|
|
12
|
+
* Enforced rules (per admin config):
|
|
13
|
+
* 1. Slug pairing — `admin.slug` matches exactly one `collection.path`.
|
|
14
|
+
* 2. Placement — when `layout` is present, every top-level schema field
|
|
15
|
+
* name appears exactly once across the union of all `tabSet.tabs[].fields`,
|
|
16
|
+
* all `row.fields`, all `group.fields`, `layout.main`, and `layout.sidebar`.
|
|
17
|
+
* 3. Name resolution — every string referenced in any `fields[]` array or
|
|
18
|
+
* layout region resolves to either a top-level schema field name or a
|
|
19
|
+
* declared primitive name. The literal `'path'` is explicitly rejected
|
|
20
|
+
* with a message pointing the user at `useAsPath`.
|
|
21
|
+
* 4. No collisions — primitive names (across `tabSets` / `rows` / `groups`)
|
|
22
|
+
* are unique within an admin config and don't shadow schema field names.
|
|
23
|
+
* 5. Nesting — `tabSets` only appear in `layout.main`; rows contain only
|
|
24
|
+
* schema field names; groups exclude tabSets and nested groups.
|
|
25
|
+
* 6. `fields` map sanity — every key in `admin.fields` matches a top-level
|
|
26
|
+
* schema field name.
|
|
27
|
+
*
|
|
28
|
+
* Throws a plain `Error` (not a `BylineError`) because configuration
|
|
29
|
+
* validation runs at startup, before the logger and error registry are
|
|
30
|
+
* necessarily wired up.
|
|
31
|
+
*/
|
|
32
|
+
export declare function validateAdminConfigs(admins: readonly CollectionAdminConfig[] | undefined, collections: readonly CollectionDefinition[]): void;
|
|
33
|
+
//# sourceMappingURL=validate-admin-configs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-admin-configs.d.ts","sourceRoot":"","sources":["../../src/config/validate-admin-configs.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAErF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,SAAS,qBAAqB,EAAE,GAAG,SAAS,EACpD,WAAW,EAAE,SAAS,oBAAoB,EAAE,GAC3C,IAAI,CAWN"}
|
|
@@ -0,0 +1,250 @@
|
|
|
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 every admin config in a configuration.
|
|
10
|
+
*
|
|
11
|
+
* Enforced rules (per admin config):
|
|
12
|
+
* 1. Slug pairing — `admin.slug` matches exactly one `collection.path`.
|
|
13
|
+
* 2. Placement — when `layout` is present, every top-level schema field
|
|
14
|
+
* name appears exactly once across the union of all `tabSet.tabs[].fields`,
|
|
15
|
+
* all `row.fields`, all `group.fields`, `layout.main`, and `layout.sidebar`.
|
|
16
|
+
* 3. Name resolution — every string referenced in any `fields[]` array or
|
|
17
|
+
* layout region resolves to either a top-level schema field name or a
|
|
18
|
+
* declared primitive name. The literal `'path'` is explicitly rejected
|
|
19
|
+
* with a message pointing the user at `useAsPath`.
|
|
20
|
+
* 4. No collisions — primitive names (across `tabSets` / `rows` / `groups`)
|
|
21
|
+
* are unique within an admin config and don't shadow schema field names.
|
|
22
|
+
* 5. Nesting — `tabSets` only appear in `layout.main`; rows contain only
|
|
23
|
+
* schema field names; groups exclude tabSets and nested groups.
|
|
24
|
+
* 6. `fields` map sanity — every key in `admin.fields` matches a top-level
|
|
25
|
+
* schema field name.
|
|
26
|
+
*
|
|
27
|
+
* Throws a plain `Error` (not a `BylineError`) because configuration
|
|
28
|
+
* validation runs at startup, before the logger and error registry are
|
|
29
|
+
* necessarily wired up.
|
|
30
|
+
*/
|
|
31
|
+
export function validateAdminConfigs(admins, collections) {
|
|
32
|
+
if (admins == null || admins.length === 0)
|
|
33
|
+
return;
|
|
34
|
+
const collectionsByPath = new Map();
|
|
35
|
+
for (const collection of collections) {
|
|
36
|
+
collectionsByPath.set(collection.path, collection);
|
|
37
|
+
}
|
|
38
|
+
for (const admin of admins) {
|
|
39
|
+
validateOne(admin, collectionsByPath);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function validateOne(admin, collectionsByPath) {
|
|
43
|
+
// Rule 1 — slug pairing.
|
|
44
|
+
const collection = collectionsByPath.get(admin.slug);
|
|
45
|
+
if (collection == null) {
|
|
46
|
+
throw new Error(`Admin config "${admin.slug}" has no matching collection (no collection with \`path: '${admin.slug}'\` was registered).`);
|
|
47
|
+
}
|
|
48
|
+
const slug = admin.slug;
|
|
49
|
+
const fail = (msg) => {
|
|
50
|
+
throw new Error(`Collection "${slug}": ${msg}`);
|
|
51
|
+
};
|
|
52
|
+
// Top-level schema field names — the population subject to placement
|
|
53
|
+
// bookkeeping. Fields nested inside group/array/blocks are rendered by
|
|
54
|
+
// their parent widget and are not addressable from layout.
|
|
55
|
+
const topLevelFieldNames = new Set();
|
|
56
|
+
for (const field of collection.fields) {
|
|
57
|
+
if ('name' in field)
|
|
58
|
+
topLevelFieldNames.add(field.name);
|
|
59
|
+
}
|
|
60
|
+
// Build primitive lookup tables.
|
|
61
|
+
const tabSets = admin.tabSets ?? [];
|
|
62
|
+
const rows = admin.rows ?? [];
|
|
63
|
+
const groups = admin.groups ?? [];
|
|
64
|
+
const tabSetNames = new Set();
|
|
65
|
+
const rowNames = new Set();
|
|
66
|
+
const groupNames = new Set();
|
|
67
|
+
// Rule 4 (collisions) — primitive names unique among themselves and
|
|
68
|
+
// distinct from schema field names. Collected as we go so we can also
|
|
69
|
+
// resolve names later.
|
|
70
|
+
for (const set of tabSets) {
|
|
71
|
+
if (tabSetNames.has(set.name)) {
|
|
72
|
+
fail(`tab set name "${set.name}" is declared more than once.`);
|
|
73
|
+
}
|
|
74
|
+
if (topLevelFieldNames.has(set.name)) {
|
|
75
|
+
fail(`tab set name "${set.name}" collides with a schema field of the same name. Rename the tab set.`);
|
|
76
|
+
}
|
|
77
|
+
tabSetNames.add(set.name);
|
|
78
|
+
}
|
|
79
|
+
for (const row of rows) {
|
|
80
|
+
if (rowNames.has(row.name)) {
|
|
81
|
+
fail(`row name "${row.name}" is declared more than once.`);
|
|
82
|
+
}
|
|
83
|
+
if (tabSetNames.has(row.name) || groupNames.has(row.name)) {
|
|
84
|
+
fail(`row name "${row.name}" collides with another primitive of the same name.`);
|
|
85
|
+
}
|
|
86
|
+
if (topLevelFieldNames.has(row.name)) {
|
|
87
|
+
fail(`row name "${row.name}" collides with a schema field of the same name. Rename the row.`);
|
|
88
|
+
}
|
|
89
|
+
rowNames.add(row.name);
|
|
90
|
+
}
|
|
91
|
+
for (const group of groups) {
|
|
92
|
+
if (groupNames.has(group.name)) {
|
|
93
|
+
fail(`group name "${group.name}" is declared more than once.`);
|
|
94
|
+
}
|
|
95
|
+
if (tabSetNames.has(group.name) || rowNames.has(group.name)) {
|
|
96
|
+
fail(`group name "${group.name}" collides with another primitive of the same name.`);
|
|
97
|
+
}
|
|
98
|
+
if (topLevelFieldNames.has(group.name)) {
|
|
99
|
+
fail(`group name "${group.name}" collides with a schema field of the same name. Rename the group.`);
|
|
100
|
+
}
|
|
101
|
+
groupNames.add(group.name);
|
|
102
|
+
}
|
|
103
|
+
// Helper: reject `'path'` references with a clear message regardless of
|
|
104
|
+
// where they appear.
|
|
105
|
+
const checkNotPath = (name, where) => {
|
|
106
|
+
if (name === 'path') {
|
|
107
|
+
fail(`'path' is a system widget rendered automatically based on \`useAsPath\` and cannot be referenced from admin configs (found in ${where}). Remove the entry — the path widget already renders at the top of the sidebar when \`useAsPath\` is set.`);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
const resolve = (name) => {
|
|
111
|
+
if (topLevelFieldNames.has(name))
|
|
112
|
+
return 'field';
|
|
113
|
+
if (tabSetNames.has(name))
|
|
114
|
+
return 'tabSet';
|
|
115
|
+
if (rowNames.has(name))
|
|
116
|
+
return 'row';
|
|
117
|
+
if (groupNames.has(name))
|
|
118
|
+
return 'group';
|
|
119
|
+
return undefined;
|
|
120
|
+
};
|
|
121
|
+
// Rule 5 — nesting. Validate each primitive's contents.
|
|
122
|
+
for (const set of tabSets) {
|
|
123
|
+
if (set.tabs.length === 0) {
|
|
124
|
+
fail(`tab set "${set.name}" declares no tabs.`);
|
|
125
|
+
}
|
|
126
|
+
const tabNames = new Set();
|
|
127
|
+
for (const tab of set.tabs) {
|
|
128
|
+
if (tabNames.has(tab.name)) {
|
|
129
|
+
fail(`tab set "${set.name}" declares tab "${tab.name}" more than once.`);
|
|
130
|
+
}
|
|
131
|
+
tabNames.add(tab.name);
|
|
132
|
+
for (const name of tab.fields) {
|
|
133
|
+
checkNotPath(name, `tab set "${set.name}" → tab "${tab.name}" fields`);
|
|
134
|
+
const kind = resolve(name);
|
|
135
|
+
if (kind == null) {
|
|
136
|
+
fail(`tab set "${set.name}" → tab "${tab.name}" references "${name}", which is neither a top-level schema field nor a declared primitive (tabSet/row/group).`);
|
|
137
|
+
}
|
|
138
|
+
if (kind === 'tabSet') {
|
|
139
|
+
fail(`tab set "${set.name}" → tab "${tab.name}" cannot contain tab set "${name}". Tab sets are top-level only.`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
for (const row of rows) {
|
|
145
|
+
if (row.fields.length === 0) {
|
|
146
|
+
fail(`row "${row.name}" declares no fields.`);
|
|
147
|
+
}
|
|
148
|
+
for (const name of row.fields) {
|
|
149
|
+
checkNotPath(name, `row "${row.name}" fields`);
|
|
150
|
+
const kind = resolve(name);
|
|
151
|
+
if (kind == null) {
|
|
152
|
+
fail(`row "${row.name}" references "${name}", which is neither a top-level schema field nor a declared primitive.`);
|
|
153
|
+
}
|
|
154
|
+
if (kind !== 'field') {
|
|
155
|
+
fail(`row "${row.name}" can only contain schema field names; "${name}" is a ${kind}.`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
for (const group of groups) {
|
|
160
|
+
if (group.fields.length === 0) {
|
|
161
|
+
fail(`group "${group.name}" declares no fields.`);
|
|
162
|
+
}
|
|
163
|
+
for (const name of group.fields) {
|
|
164
|
+
checkNotPath(name, `group "${group.name}" fields`);
|
|
165
|
+
const kind = resolve(name);
|
|
166
|
+
if (kind == null) {
|
|
167
|
+
fail(`group "${group.name}" references "${name}", which is neither a top-level schema field nor a declared primitive.`);
|
|
168
|
+
}
|
|
169
|
+
if (kind === 'tabSet') {
|
|
170
|
+
fail(`group "${group.name}" cannot contain tab set "${name}". Tab sets are top-level only.`);
|
|
171
|
+
}
|
|
172
|
+
if (kind === 'group') {
|
|
173
|
+
fail(`group "${group.name}" cannot contain another group ("${name}"). Groups do not nest.`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// Rule 6 — `fields` map keys must match top-level schema field names.
|
|
178
|
+
if (admin.fields != null) {
|
|
179
|
+
for (const key of Object.keys(admin.fields)) {
|
|
180
|
+
if (!topLevelFieldNames.has(key)) {
|
|
181
|
+
fail(`\`fields["${key}"]\` references a name that is not a top-level schema field. Per-field overrides apply only to top-level schema fields.`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Rule 2 + 3 — layout: name resolution + bookkeeping (every schema field
|
|
186
|
+
// placed exactly once). Skipped when no `layout` is declared (the
|
|
187
|
+
// renderer's default-layout synthesis covers the trivial case).
|
|
188
|
+
if (admin.layout == null)
|
|
189
|
+
return;
|
|
190
|
+
// Validate that layout regions reference resolvable names with valid
|
|
191
|
+
// kinds. Then walk into tab sets via their declared tabs to enumerate
|
|
192
|
+
// every schema field actually placed somewhere.
|
|
193
|
+
const placedFields = new Set();
|
|
194
|
+
const recordFieldPlacement = (name, where) => {
|
|
195
|
+
if (placedFields.has(name)) {
|
|
196
|
+
fail(`schema field "${name}" is placed more than once (most recently in ${where}).`);
|
|
197
|
+
}
|
|
198
|
+
placedFields.add(name);
|
|
199
|
+
};
|
|
200
|
+
// Walk a `fields[]` list (from a tab, group, or layout region) and record
|
|
201
|
+
// every schema field encountered. Recurses through groups and rows.
|
|
202
|
+
const walkContents = (names, where, allow) => {
|
|
203
|
+
for (const name of names) {
|
|
204
|
+
checkNotPath(name, where);
|
|
205
|
+
const kind = resolve(name);
|
|
206
|
+
if (kind == null) {
|
|
207
|
+
fail(`${where} references "${name}", which is neither a top-level schema field nor a declared primitive.`);
|
|
208
|
+
}
|
|
209
|
+
if (kind === 'tabSet' && !allow.tabSet) {
|
|
210
|
+
fail(`${where} cannot contain tab set "${name}". Tab sets are only allowed in \`layout.main\`.`);
|
|
211
|
+
}
|
|
212
|
+
if (kind === 'field') {
|
|
213
|
+
recordFieldPlacement(name, where);
|
|
214
|
+
}
|
|
215
|
+
else if (kind === 'tabSet') {
|
|
216
|
+
const set = tabSets.find((s) => s.name === name);
|
|
217
|
+
if (set == null)
|
|
218
|
+
return;
|
|
219
|
+
for (const tab of set.tabs) {
|
|
220
|
+
walkContents(tab.fields, `tab set "${set.name}" → tab "${tab.name}"`, {
|
|
221
|
+
tabSet: false,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
else if (kind === 'row') {
|
|
226
|
+
const row = rows.find((r) => r.name === name);
|
|
227
|
+
if (row == null)
|
|
228
|
+
return;
|
|
229
|
+
walkContents(row.fields, `row "${row.name}"`, { tabSet: false });
|
|
230
|
+
}
|
|
231
|
+
else if (kind === 'group') {
|
|
232
|
+
const group = groups.find((g) => g.name === name);
|
|
233
|
+
if (group == null)
|
|
234
|
+
return;
|
|
235
|
+
walkContents(group.fields, `group "${group.name}"`, { tabSet: false });
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
walkContents(admin.layout.main, '`layout.main`', { tabSet: true });
|
|
240
|
+
if (admin.layout.sidebar != null) {
|
|
241
|
+
walkContents(admin.layout.sidebar, '`layout.sidebar`', { tabSet: false });
|
|
242
|
+
}
|
|
243
|
+
// Bookkeeping — every top-level schema field must be placed somewhere.
|
|
244
|
+
for (const fieldName of topLevelFieldNames) {
|
|
245
|
+
if (!placedFields.has(fieldName)) {
|
|
246
|
+
fail(`schema field "${fieldName}" is not placed in any tab, row, group, or layout region. Add it to one of them, or remove the field from the schema.`);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
//# sourceMappingURL=validate-admin-configs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-admin-configs.js","sourceRoot":"","sources":["../../src/config/validate-admin-configs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
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
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=validate-admin-configs.test.node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-admin-configs.test.node.d.ts","sourceRoot":"","sources":["../../src/config/validate-admin-configs.test.node.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
|
@@ -0,0 +1,224 @@
|
|
|
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 { describe, expect, it } from 'vitest';
|
|
9
|
+
import { validateAdminConfigs } from './validate-admin-configs.js';
|
|
10
|
+
const collection = {
|
|
11
|
+
path: 'news',
|
|
12
|
+
labels: { singular: 'News', plural: 'News' },
|
|
13
|
+
useAsPath: 'title',
|
|
14
|
+
fields: [
|
|
15
|
+
{ name: 'title', label: 'Title', type: 'text' },
|
|
16
|
+
{ name: 'summary', label: 'Summary', type: 'textArea' },
|
|
17
|
+
{ name: 'content', label: 'Content', type: 'richText' },
|
|
18
|
+
{ name: 'text1', label: 'Text 1', type: 'text' },
|
|
19
|
+
{ name: 'text2', label: 'Text 2', type: 'text' },
|
|
20
|
+
],
|
|
21
|
+
};
|
|
22
|
+
const baseAdmin = {
|
|
23
|
+
slug: 'news',
|
|
24
|
+
tabSets: [
|
|
25
|
+
{
|
|
26
|
+
name: 'main',
|
|
27
|
+
tabs: [
|
|
28
|
+
{ name: 'details', label: 'Details', fields: ['title', 'summary', 'titles'] },
|
|
29
|
+
{ name: 'content', label: 'Content', fields: ['content'] },
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
rows: [{ name: 'titles', fields: ['text1', 'text2'] }],
|
|
34
|
+
layout: { main: ['main'] },
|
|
35
|
+
};
|
|
36
|
+
describe('validateAdminConfigs', () => {
|
|
37
|
+
it('accepts a valid admin config (baseline)', () => {
|
|
38
|
+
expect(() => validateAdminConfigs([baseAdmin], [collection])).not.toThrow();
|
|
39
|
+
});
|
|
40
|
+
it('is a no-op when admins is undefined', () => {
|
|
41
|
+
expect(() => validateAdminConfigs(undefined, [collection])).not.toThrow();
|
|
42
|
+
});
|
|
43
|
+
// Rule 1 — slug pairing.
|
|
44
|
+
it('rejects an admin config whose slug has no matching collection', () => {
|
|
45
|
+
const orphan = { slug: 'nonexistent', layout: { main: [] } };
|
|
46
|
+
expect(() => validateAdminConfigs([orphan], [collection])).toThrow(/no matching collection/);
|
|
47
|
+
});
|
|
48
|
+
// Rule 2 — placement bookkeeping.
|
|
49
|
+
it('rejects an admin config that leaves a schema field unplaced', () => {
|
|
50
|
+
const admin = {
|
|
51
|
+
...baseAdmin,
|
|
52
|
+
tabSets: [
|
|
53
|
+
{
|
|
54
|
+
name: 'main',
|
|
55
|
+
tabs: [
|
|
56
|
+
// omit 'summary' from the details tab
|
|
57
|
+
{ name: 'details', label: 'Details', fields: ['title', 'titles'] },
|
|
58
|
+
{ name: 'content', label: 'Content', fields: ['content'] },
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
};
|
|
63
|
+
expect(() => validateAdminConfigs([admin], [collection])).toThrow(/"summary" is not placed/);
|
|
64
|
+
});
|
|
65
|
+
it('rejects placing the same schema field twice', () => {
|
|
66
|
+
const admin = {
|
|
67
|
+
...baseAdmin,
|
|
68
|
+
layout: { main: ['main'], sidebar: ['title'] },
|
|
69
|
+
};
|
|
70
|
+
expect(() => validateAdminConfigs([admin], [collection])).toThrow(/placed more than once/);
|
|
71
|
+
});
|
|
72
|
+
// Rule 3 — name resolution + path rejection.
|
|
73
|
+
it('rejects unknown names in a layout region', () => {
|
|
74
|
+
const admin = {
|
|
75
|
+
...baseAdmin,
|
|
76
|
+
layout: { main: ['main', 'doesNotExist'] },
|
|
77
|
+
};
|
|
78
|
+
expect(() => validateAdminConfigs([admin], [collection])).toThrow(/"doesNotExist", which is neither a top-level schema field nor a declared primitive/);
|
|
79
|
+
});
|
|
80
|
+
it("rejects 'path' in layout.sidebar with a useAsPath hint", () => {
|
|
81
|
+
const admin = {
|
|
82
|
+
...baseAdmin,
|
|
83
|
+
layout: { main: ['main'], sidebar: ['path'] },
|
|
84
|
+
};
|
|
85
|
+
expect(() => validateAdminConfigs([admin], [collection])).toThrow(/useAsPath/);
|
|
86
|
+
});
|
|
87
|
+
it("rejects 'path' inside a tab", () => {
|
|
88
|
+
const admin = {
|
|
89
|
+
...baseAdmin,
|
|
90
|
+
tabSets: [
|
|
91
|
+
{
|
|
92
|
+
name: 'main',
|
|
93
|
+
tabs: [
|
|
94
|
+
{
|
|
95
|
+
name: 'details',
|
|
96
|
+
label: 'Details',
|
|
97
|
+
fields: ['title', 'summary', 'titles', 'path'],
|
|
98
|
+
},
|
|
99
|
+
{ name: 'content', label: 'Content', fields: ['content'] },
|
|
100
|
+
],
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
};
|
|
104
|
+
expect(() => validateAdminConfigs([admin], [collection])).toThrow(/useAsPath/);
|
|
105
|
+
});
|
|
106
|
+
// Rule 4 — collisions.
|
|
107
|
+
it('rejects a primitive name that collides with a schema field', () => {
|
|
108
|
+
const admin = {
|
|
109
|
+
...baseAdmin,
|
|
110
|
+
rows: [
|
|
111
|
+
{ name: 'titles', fields: ['text1', 'text2'] },
|
|
112
|
+
// 'title' is also a schema field — collision
|
|
113
|
+
{ name: 'title', fields: ['summary'] },
|
|
114
|
+
],
|
|
115
|
+
};
|
|
116
|
+
expect(() => validateAdminConfigs([admin], [collection])).toThrow(/collides with a schema field/);
|
|
117
|
+
});
|
|
118
|
+
it('rejects two primitives sharing the same name', () => {
|
|
119
|
+
const admin = {
|
|
120
|
+
...baseAdmin,
|
|
121
|
+
rows: [{ name: 'titles', fields: ['text1', 'text2'] }],
|
|
122
|
+
groups: [{ name: 'titles', label: 'X', fields: ['summary'] }],
|
|
123
|
+
};
|
|
124
|
+
expect(() => validateAdminConfigs([admin], [collection])).toThrow(/collides with another primitive/);
|
|
125
|
+
});
|
|
126
|
+
// Rule 5 — nesting.
|
|
127
|
+
it('rejects a row whose fields include a non-field primitive', () => {
|
|
128
|
+
const admin = {
|
|
129
|
+
slug: 'news',
|
|
130
|
+
tabSets: [
|
|
131
|
+
{
|
|
132
|
+
name: 'main',
|
|
133
|
+
tabs: [
|
|
134
|
+
{ name: 'details', label: 'Details', fields: ['title', 'summary', 'badRow'] },
|
|
135
|
+
{ name: 'content', label: 'Content', fields: ['content'] },
|
|
136
|
+
],
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
groups: [{ name: 'someGroup', fields: ['text1'] }],
|
|
140
|
+
rows: [
|
|
141
|
+
// Row contains a group name — illegal.
|
|
142
|
+
{ name: 'badRow', fields: ['text2', 'someGroup'] },
|
|
143
|
+
],
|
|
144
|
+
layout: { main: ['main'] },
|
|
145
|
+
};
|
|
146
|
+
expect(() => validateAdminConfigs([admin], [collection])).toThrow(/can only contain schema field names/);
|
|
147
|
+
});
|
|
148
|
+
it('rejects a tab set referenced from inside a tab', () => {
|
|
149
|
+
const admin = {
|
|
150
|
+
slug: 'news',
|
|
151
|
+
tabSets: [
|
|
152
|
+
{
|
|
153
|
+
name: 'inner',
|
|
154
|
+
tabs: [{ name: 'a', label: 'A', fields: ['text1', 'text2'] }],
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: 'outer',
|
|
158
|
+
tabs: [
|
|
159
|
+
// Embedding the inner tab set inside a tab is illegal.
|
|
160
|
+
{ name: 'wrapper', label: 'Wrapper', fields: ['title', 'summary', 'inner'] },
|
|
161
|
+
{ name: 'content', label: 'Content', fields: ['content'] },
|
|
162
|
+
],
|
|
163
|
+
},
|
|
164
|
+
],
|
|
165
|
+
layout: { main: ['outer'] },
|
|
166
|
+
};
|
|
167
|
+
expect(() => validateAdminConfigs([admin], [collection])).toThrow(/Tab sets are top-level only/);
|
|
168
|
+
});
|
|
169
|
+
it('rejects a tab set referenced from layout.sidebar', () => {
|
|
170
|
+
const admin = {
|
|
171
|
+
...baseAdmin,
|
|
172
|
+
layout: { main: [], sidebar: ['main'] },
|
|
173
|
+
};
|
|
174
|
+
expect(() => validateAdminConfigs([admin], [collection])).toThrow(/Tab sets are only allowed in `layout.main`/);
|
|
175
|
+
});
|
|
176
|
+
it('rejects a group nested inside another group', () => {
|
|
177
|
+
const admin = {
|
|
178
|
+
slug: 'news',
|
|
179
|
+
tabSets: [
|
|
180
|
+
{
|
|
181
|
+
name: 'main',
|
|
182
|
+
tabs: [
|
|
183
|
+
{ name: 'details', label: 'Details', fields: ['title', 'summary', 'outer'] },
|
|
184
|
+
{ name: 'content', label: 'Content', fields: ['content'] },
|
|
185
|
+
],
|
|
186
|
+
},
|
|
187
|
+
],
|
|
188
|
+
groups: [
|
|
189
|
+
{ name: 'outer', label: 'Outer', fields: ['text1', 'inner'] },
|
|
190
|
+
{ name: 'inner', label: 'Inner', fields: ['text2'] },
|
|
191
|
+
],
|
|
192
|
+
layout: { main: ['main'] },
|
|
193
|
+
};
|
|
194
|
+
expect(() => validateAdminConfigs([admin], [collection])).toThrow(/Groups do not nest/);
|
|
195
|
+
});
|
|
196
|
+
// Rule 6 — `fields` map sanity.
|
|
197
|
+
it('rejects a `fields` map key that is not a schema field name', () => {
|
|
198
|
+
const admin = {
|
|
199
|
+
...baseAdmin,
|
|
200
|
+
fields: { nonexistent: {} },
|
|
201
|
+
};
|
|
202
|
+
expect(() => validateAdminConfigs([admin], [collection])).toThrow(/not a top-level schema field/);
|
|
203
|
+
});
|
|
204
|
+
// Layout omitted — bookkeeping skipped, primitive declarations still checked.
|
|
205
|
+
it('skips placement bookkeeping when layout is omitted', () => {
|
|
206
|
+
const admin = {
|
|
207
|
+
slug: 'news',
|
|
208
|
+
// No layout — renderer will synthesise a default.
|
|
209
|
+
};
|
|
210
|
+
expect(() => validateAdminConfigs([admin], [collection])).not.toThrow();
|
|
211
|
+
});
|
|
212
|
+
it('still rejects a primitive collision when layout is omitted', () => {
|
|
213
|
+
const admin = {
|
|
214
|
+
slug: 'news',
|
|
215
|
+
rows: [
|
|
216
|
+
{ name: 'titles', fields: ['text1', 'text2'] },
|
|
217
|
+
// 'title' is also a schema field — collision still caught.
|
|
218
|
+
{ name: 'title', fields: ['summary'] },
|
|
219
|
+
],
|
|
220
|
+
};
|
|
221
|
+
expect(() => validateAdminConfigs([admin], [collection])).toThrow(/collides with a schema field/);
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
//# sourceMappingURL=validate-admin-configs.test.node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-admin-configs.test.node.js","sourceRoot":"","sources":["../../src/config/validate-admin-configs.test.node.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
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/index.js';
|
|
9
|
+
/**
|
|
10
|
+
* Field names that cannot be declared in a collection schema because they
|
|
11
|
+
* collide with system-managed attributes on `documentVersions`. Exported
|
|
12
|
+
* so storage-layer reconstruction can skip orphan rows that may exist in
|
|
13
|
+
* store tables from installations whose schemas declared these names as
|
|
14
|
+
* user fields before they were promoted to system attributes.
|
|
15
|
+
*/
|
|
16
|
+
export declare const RESERVED_FIELD_NAMES: ReadonlySet<string>;
|
|
17
|
+
/**
|
|
18
|
+
* Validate every collection in a configuration.
|
|
19
|
+
*
|
|
20
|
+
* Enforced rules:
|
|
21
|
+
* - No field (at any nesting depth) may be named `path`. The `path`
|
|
22
|
+
* column on `documentVersions` is system-managed; collections opt
|
|
23
|
+
* into derived paths via `useAsPath`.
|
|
24
|
+
* - When `useAsPath` is set, the referenced field must exist at the
|
|
25
|
+
* top level of the collection and be of a type the slugifier can
|
|
26
|
+
* sensibly consume (text-like or date-like).
|
|
27
|
+
*
|
|
28
|
+
* Throws a plain `Error` (not a `BylineError`) because configuration
|
|
29
|
+
* validation runs at startup, before the logger and error registry are
|
|
30
|
+
* necessarily wired up.
|
|
31
|
+
*/
|
|
32
|
+
export declare function validateCollections(collections: readonly CollectionDefinition[]): void;
|
|
33
|
+
//# sourceMappingURL=validate-collections.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-collections.d.ts","sourceRoot":"","sources":["../../src/config/validate-collections.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAoB,MAAM,oBAAoB,CAAA;AAEhF;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,EAAE,WAAW,CAAC,MAAM,CAAqB,CAAA;AAwB1E;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,SAAS,oBAAoB,EAAE,GAAG,IAAI,CA0BtF"}
|