Schema validation on index

pull/1081/head
Zef Hemel 2024-08-24 16:14:29 +02:00
parent c416e8aeb5
commit fed9965a99
4 changed files with 37 additions and 32 deletions

View File

@ -245,8 +245,6 @@ config:
tag:
type: string
readOnly: true
enum:
- page
tags:
anyOf:
- type: array
@ -320,8 +318,6 @@ config:
tag:
type: string
readOnly: true
enum:
- aspiring-page
name:
type: string
readOnly: true
@ -341,8 +337,6 @@ config:
tag:
type: string
readOnly: true
enum:
- attachment
tags:
type: array
readOnly: true
@ -386,8 +380,6 @@ config:
tag:
type: string
readOnly: true
enum:
- item
tags:
type: array
items:
@ -423,8 +415,6 @@ config:
tag:
type: string
readOnly: true
enum:
- tag
tags:
type: array
readOnly: true
@ -457,8 +447,6 @@ config:
readOnly: true
tag:
type: string
enum:
- anchor
tags:
type: array
items:
@ -483,8 +471,6 @@ config:
readOnly: true
tag:
type: string
enum:
- link
tags:
type: array
items:
@ -521,8 +507,6 @@ config:
readOnly: true
tag:
type: string
enum:
- header
tags:
type: array
items:
@ -549,8 +533,6 @@ config:
readOnly: true
tag:
type: string
enum:
- paragraph
tags:
type: array
items:
@ -575,8 +557,6 @@ config:
readOnly: true
tag:
type: string
enum:
- template
tags:
anyOf:
- type: array
@ -610,8 +590,6 @@ config:
readOnly: true
tag:
type: string
enum:
- table
tags:
type: array
items:

View File

@ -1,8 +1,10 @@
import type { IndexTreeEvent } from "@silverbulletmd/silverbullet/types";
import {
editor,
jsonschema,
markdown,
space,
system,
YAML,
} from "@silverbulletmd/silverbullet/syscalls";
@ -17,6 +19,7 @@ import {
} from "@silverbulletmd/silverbullet/lib/tree";
import { updateITags } from "@silverbulletmd/silverbullet/lib/tags";
import type { AspiringPageObject } from "./page_links.ts";
import { deepObjectMerge } from "@silverbulletmd/silverbullet/lib/json";
export async function indexPage({ name, tree }: IndexTreeEvent) {
if (name.startsWith("_")) {
@ -61,13 +64,38 @@ export async function indexPage({ name, tree }: IndexTreeEvent) {
updateITags(combinedPageMeta, frontmatter);
// console.log("Page object", combinedPageMeta);
await indexObjects<PageMeta>(name, [combinedPageMeta]);
// Make sure this page is no (longer) in the aspiring pages list
await queryDeleteObjects<AspiringPageObject>("aspiring-page", {
filter: ["=", ["attr", "name"], ["string", name]],
});
const tagSchema = (await system.getSpaceConfig("schema")).tag;
// Validate the page meta against schemas, and only index the tags that validate
for (const tag of combinedPageMeta.tags) {
let schema = tagSchema[tag];
if (schema) {
schema = deepObjectMerge({ type: "object" }, schema);
const validationError = await jsonschema.validateObject(
schema,
combinedPageMeta,
);
if (validationError) {
console.warn(
"Validation failed for",
combinedPageMeta,
"for tag",
tag,
". Error:",
validationError,
". Removing tag until this is resolved.",
);
combinedPageMeta.tags.splice(combinedPageMeta.tags.indexOf(tag), 1);
}
}
}
// console.log("Page object", combinedPageMeta);
await indexObjects<PageMeta>(name, [combinedPageMeta]);
}
export async function lintFrontmatter(): Promise<LintDiagnostic[]> {

View File

@ -53,8 +53,6 @@ config:
readOnly: true
tag:
type: string
enum:
- task
tags:
type: array
items:
@ -90,8 +88,6 @@ config:
readOnly: true
tag:
type: string
enum:
- taskstate
tags:
type: array
items:

View File

@ -82,11 +82,14 @@ schema.config.properties.myFullName.type: string
Now, if you would accidentally change `myFullName` into a number or boolean value, you would get a validation error.
# Validation
At the moment, validation only occurs in the editor in [[Space Config]] and [[Frontmatter]] blocks and shows any violations as highlighted errors.
Validation happens during linting in the editor (visually, with squiggly lines for errors) and indexing (at the database level). Therefore, changes to your schema will only go into effect when either of those two things kick in.
Even if data does not pass validation, it is still stored in the data store so it does not (currently) _enforce_ the format.
For pages, during indexing, specified [[Frontmatter]] is validated against schema specified for its tags. If validation fails for one of these tags, that _tag will be removed_ from its `tags` attribute and therefore **not** be indexed as such. This guarantees that the schema is enforced and any object follows the schema.
This may change in the future.
For instance, in the example mentioned in [[#Example]], if the `lastName` of either of the two `#contact` tagged pages is removed (which would mean it no longer matches the schema constraints), this object will no longer be indexed as a `contact` and thus not appear in query results for it. However, since the page still follows the regular `page` tag schema, it will still appear in `page` query results.
> **note** Note
> If you would like to enforce a newly introduced or updated schema on your entire space, you will have to run a full {[Space: Reindex]}.
# Supported types
All standard JSON Schema types are supported. Likely you are interested in: