@dossierhq/core
Version:
The core Dossier library used by clients and server alike, used to interact with schema and entities directly, as well as remotely through a client.
148 lines • 5.42 kB
JavaScript
/// <reference types="./ContentUtils.d.ts" />
import { FieldType, } from '../schema/SchemaSpecification.js';
import { assertExhaustive } from '../utils/Asserts.js';
import { isRichTextRootNode } from './ContentTypeUtils.js';
export function getEntityNameBase(name) {
const hashIndex = name.lastIndexOf('#');
if (hashIndex < 0) {
return name;
}
return name.slice(0, hashIndex);
}
export function isEntityNameAsRequested(currentName, requestedName) {
if (requestedName === currentName) {
return true;
}
const currentNameBase = getEntityNameBase(currentName);
return requestedName === currentNameBase;
}
export function copyEntity(entity, changes) {
const copy = { ...entity };
if (typeof changes.id === 'string') {
copy.id = changes.id;
}
if (changes.info) {
copy.info = { ...entity.info };
for (const [key, value] of Object.entries(changes.info)) {
copy.info[key] = value;
}
}
if (changes.fields) {
const fieldsCopy = { ...entity.fields };
copy.fields = fieldsCopy;
for (const [key, value] of Object.entries(changes.fields)) {
fieldsCopy[key] = value;
}
}
return copy;
}
export function checkFieldTraversable(fieldSpec, value) {
if (fieldSpec.list) {
if (value !== null && value !== undefined && !Array.isArray(value)) {
return { path: [], message: `Expected a list of ${fieldSpec.type}, got ${typeof value}` };
}
}
return null;
}
export function checkFieldItemTraversable(fieldSpec, value) {
const { type } = fieldSpec;
if (value === null || value === undefined) {
return null;
}
if (Array.isArray(value)) {
return { path: [], message: `Expected single ${type}, got a list` };
}
switch (type) {
case FieldType.Boolean: {
if (typeof value !== 'boolean') {
return { path: [], message: `Expected a boolean, got ${typeof value}` };
}
break;
}
case FieldType.Component: {
if (typeof value !== 'object') {
return { path: [], message: `Expected a Component object, got ${typeof value}` };
}
if (!('type' in value)) {
return { path: ['type'], message: `Missing a Component type` };
}
if (typeof value.type !== 'string') {
return { path: ['type'], message: `Expected a Component type, got ${typeof value}` };
}
break;
}
case FieldType.Reference: {
if (typeof value !== 'object') {
return { path: [], message: `Expected an entity reference, got ${typeof value}` };
}
if (typeof value.id !== 'string') {
return {
path: ['id'],
message: `Expected an entity reference id, got ${typeof value.id}`,
};
}
break;
}
case FieldType.Location: {
if (typeof value !== 'object') {
return { path: [], message: `Expected a Location object, got ${typeof value}` };
}
const { lat, lng } = value;
if (typeof lat !== 'number' || typeof lng !== 'number') {
return {
path: [],
message: `Expected {lat: number, lng: number}, got {lat: ${typeof lat}, lng: ${typeof lng}}`,
};
}
break;
}
case FieldType.Number: {
if (typeof value !== 'number') {
return { path: [], message: `Expected a number, got ${typeof value}` };
}
break;
}
case FieldType.RichText: {
if (typeof value !== 'object') {
return { path: [], message: `Expected a RichText object, got ${typeof value}` };
}
const root = value.root;
if (!root) {
return { path: [], message: `RichText object is missing root` };
}
const rootTraversalError = checkRichTextNodeTraversable(root);
if (rootTraversalError) {
return { path: ['root', ...rootTraversalError.path], message: rootTraversalError.message };
}
if (!isRichTextRootNode(root)) {
return {
path: ['root'],
message: `RichText root is not a valid RichText node, (got ${root.type})`,
};
}
break;
}
case FieldType.String: {
if (typeof value !== 'string') {
return { path: [], message: `Expected a string, got ${typeof value}` };
}
break;
}
default:
assertExhaustive(type);
}
return null;
}
export function checkRichTextNodeTraversable(node) {
if (!node || typeof node !== 'object') {
return { path: [], message: `Expected a RichText node, got ${typeof node}` };
}
if (typeof node.type !== 'string') {
return { path: [], message: `RichText node is missing type` };
}
if ('children' in node && !Array.isArray(node.children)) {
return { path: [], message: `RichText node children is not an array` };
}
return null;
}
//# sourceMappingURL=ContentUtils.js.map