tsondb 0.5.10 → 0.5.12

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.
Files changed (30) hide show
  1. package/dist/src/web/components/typeInputs/ArrayTypeInput.d.ts +2 -1
  2. package/dist/src/web/components/typeInputs/ArrayTypeInput.js +7 -3
  3. package/dist/src/web/components/typeInputs/BooleanTypeInput.d.ts +1 -1
  4. package/dist/src/web/components/typeInputs/BooleanTypeInput.js +4 -0
  5. package/dist/src/web/components/typeInputs/DateTypeInput.d.ts +1 -1
  6. package/dist/src/web/components/typeInputs/DateTypeInput.js +4 -0
  7. package/dist/src/web/components/typeInputs/EnumTypeInput.d.ts +1 -0
  8. package/dist/src/web/components/typeInputs/EnumTypeInput.js +2 -2
  9. package/dist/src/web/components/typeInputs/FloatTypeInput.d.ts +1 -1
  10. package/dist/src/web/components/typeInputs/FloatTypeInput.js +5 -1
  11. package/dist/src/web/components/typeInputs/IncludeIdentifierTypeInput.d.ts +1 -0
  12. package/dist/src/web/components/typeInputs/IncludeIdentifierTypeInput.js +2 -2
  13. package/dist/src/web/components/typeInputs/IntegerTypeInput.d.ts +1 -1
  14. package/dist/src/web/components/typeInputs/IntegerTypeInput.js +5 -1
  15. package/dist/src/web/components/typeInputs/NestedEntityMapTypeInput.d.ts +2 -1
  16. package/dist/src/web/components/typeInputs/NestedEntityMapTypeInput.js +6 -2
  17. package/dist/src/web/components/typeInputs/ObjectTypeInput.d.ts +2 -1
  18. package/dist/src/web/components/typeInputs/ObjectTypeInput.js +8 -3
  19. package/dist/src/web/components/typeInputs/ReferenceIdentifierTypeInput.d.ts +1 -1
  20. package/dist/src/web/components/typeInputs/ReferenceIdentifierTypeInput.js +4 -0
  21. package/dist/src/web/components/typeInputs/StringTypeInput.d.ts +1 -1
  22. package/dist/src/web/components/typeInputs/StringTypeInput.js +4 -0
  23. package/dist/src/web/components/typeInputs/TypeInput.d.ts +1 -0
  24. package/dist/src/web/components/typeInputs/TypeInput.js +14 -60
  25. package/dist/src/web/routes/CreateInstance.js +1 -1
  26. package/dist/src/web/routes/Instance.js +4 -3
  27. package/dist/src/web/utils/debug.d.ts +1 -0
  28. package/dist/src/web/utils/debug.js +5 -0
  29. package/package.json +1 -1
  30. package/public/css/styles.css +4 -4
@@ -4,7 +4,8 @@ import type { InstanceNamesByEntity } from "../../hooks/useInstanceNamesByEntity
4
4
  import type { GetDeclFromDeclName } from "../../hooks/useSecondaryDeclarations.ts";
5
5
  type Props = {
6
6
  type: SerializedArrayType;
7
- value: unknown[];
7
+ path: string | undefined;
8
+ value: unknown;
8
9
  instanceNamesByEntity: InstanceNamesByEntity;
9
10
  getDeclFromDeclName: GetDeclFromDeclName;
10
11
  onChange: (value: unknown[]) => void;
@@ -1,15 +1,19 @@
1
- import { jsxs as _jsxs, jsx as _jsx } from "preact/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
2
2
  import { removeAt } from "../../../shared/utils/array.js";
3
3
  import { validateArrayConstraints } from "../../../shared/validation/array.js";
4
4
  import { createTypeSkeleton } from "../../utils/typeSkeleton.js";
5
5
  import { TypeInput } from "./TypeInput.js";
6
+ import { MismatchingTypeError } from "./utils/MismatchingTypeError.js";
6
7
  import { ValidationErrors } from "./utils/ValidationErrors.js";
7
- export const ArrayTypeInput = ({ type, value, instanceNamesByEntity, getDeclFromDeclName, onChange, }) => {
8
+ export const ArrayTypeInput = ({ type, path, value, instanceNamesByEntity, getDeclFromDeclName, onChange, }) => {
9
+ if (!Array.isArray(value)) {
10
+ return _jsx(MismatchingTypeError, { expected: "array", actual: value });
11
+ }
8
12
  const errors = validateArrayConstraints(type, value);
9
13
  const isTuple = typeof type.minItems === "number" && type.minItems === type.maxItems;
10
14
  return (_jsxs("div", { class: "field field--container field--array", children: [value.length > 0 && (_jsx("ol", { children: value.map((item, i) => (_jsxs("li", { class: "container-item array-item", children: [isTuple ? null : (_jsxs("div", { className: "container-item-header", children: [_jsxs("div", { className: "container-item-title", children: [i + 1, "."] }), _jsxs("button", { class: "destructive", onClick: () => {
11
15
  onChange(removeAt(value, i));
12
- }, disabled: type.minItems !== undefined && value.length <= type.minItems, children: ["Delete Item #", i + 1] })] })), _jsx(TypeInput, { type: type.items, value: item, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: newItem => {
16
+ }, disabled: type.minItems !== undefined && value.length <= type.minItems, children: ["Delete Item #", i + 1] })] })), _jsx(TypeInput, { type: type.items, path: path === undefined ? `[${i.toString()}]` : `${path}[${i.toString()}]`, value: item, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: newItem => {
13
17
  onChange(value.with(i, newItem));
14
18
  } })] }, i))) })), isTuple ? null : (_jsx("div", { class: "add-item-container", children: _jsxs("button", { onClick: () => {
15
19
  onChange([...value, createTypeSkeleton(getDeclFromDeclName, type.items)]);
@@ -2,7 +2,7 @@ import type { FunctionComponent } from "preact";
2
2
  import type { SerializedBooleanType } from "../../../node/schema/types/primitives/BooleanType.ts";
3
3
  type Props = {
4
4
  type: SerializedBooleanType;
5
- value: boolean;
5
+ value: unknown;
6
6
  onChange: (value: boolean) => void;
7
7
  };
8
8
  export declare const BooleanTypeInput: FunctionComponent<Props>;
@@ -1,5 +1,9 @@
1
1
  import { jsx as _jsx } from "preact/jsx-runtime";
2
+ import { MismatchingTypeError } from "./utils/MismatchingTypeError.js";
2
3
  export const BooleanTypeInput = ({ value, onChange }) => {
4
+ if (typeof value !== "boolean") {
5
+ return _jsx(MismatchingTypeError, { expected: "boolean", actual: value });
6
+ }
3
7
  return (_jsx("div", { class: "field", children: _jsx("input", { type: "checkbox", checked: value, onInput: event => {
4
8
  onChange(event.currentTarget.checked);
5
9
  } }) }));
@@ -2,7 +2,7 @@ import type { FunctionComponent } from "preact";
2
2
  import type { SerializedDateType } from "../../../node/schema/types/primitives/DateType.ts";
3
3
  type Props = {
4
4
  type: SerializedDateType;
5
- value: string;
5
+ value: unknown;
6
6
  onChange: (value: string) => void;
7
7
  };
8
8
  export declare const DateTypeInput: FunctionComponent<Props>;
@@ -1,7 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
2
2
  import { validateDateConstraints } from "../../../shared/validation/date.js";
3
+ import { MismatchingTypeError } from "./utils/MismatchingTypeError.js";
3
4
  import { ValidationErrors } from "./utils/ValidationErrors.js";
4
5
  export const DateTypeInput = ({ type, value, onChange }) => {
6
+ if (typeof value !== "string") {
7
+ return _jsx(MismatchingTypeError, { expected: "date string", actual: value });
8
+ }
5
9
  const errors = validateDateConstraints(type, value);
6
10
  return (_jsxs("div", { class: "field", children: [_jsx("input", { type: "date", value: value, onInput: event => {
7
11
  onChange(event.currentTarget.value);
@@ -4,6 +4,7 @@ import type { InstanceNamesByEntity } from "../../hooks/useInstanceNamesByEntity
4
4
  import type { GetDeclFromDeclName } from "../../hooks/useSecondaryDeclarations.ts";
5
5
  type Props = {
6
6
  type: SerializedEnumType;
7
+ path: string | undefined;
7
8
  value: unknown;
8
9
  instanceNamesByEntity: InstanceNamesByEntity;
9
10
  getDeclFromDeclName: GetDeclFromDeclName;
@@ -5,7 +5,7 @@ import { createTypeSkeleton } from "../../utils/typeSkeleton.js";
5
5
  import { Select } from "../Select.js";
6
6
  import { TypeInput } from "./TypeInput.js";
7
7
  import { MismatchingTypeError } from "./utils/MismatchingTypeError.js";
8
- export const EnumTypeInput = ({ type, value, instanceNamesByEntity, getDeclFromDeclName, onChange, }) => {
8
+ export const EnumTypeInput = ({ type, path, value, instanceNamesByEntity, getDeclFromDeclName, onChange, }) => {
9
9
  if (typeof value !== "object" ||
10
10
  value === null ||
11
11
  Array.isArray(value) ||
@@ -29,7 +29,7 @@ export const EnumTypeInput = ({ type, value, instanceNamesByEntity, getDeclFromD
29
29
  [event.currentTarget.value]: createTypeSkeleton(getDeclFromDeclName, caseMember.type),
30
30
  });
31
31
  }
32
- }, children: enumValues.map(enumValue => (_jsx("option", { value: enumValue, selected: enumValue === activeEnumCase, children: toTitleCase(enumValue) }, enumValue))) }), caseMember?.type == null ? null : (_jsx("div", { className: "associated-type", children: _jsx(TypeInput, { type: caseMember.type, value: value[activeEnumCase], instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: newValue => {
32
+ }, children: enumValues.map(enumValue => (_jsx("option", { value: enumValue, selected: enumValue === activeEnumCase, children: toTitleCase(enumValue) }, enumValue))) }), caseMember?.type == null ? null : (_jsx("div", { className: "associated-type", children: _jsx(TypeInput, { type: caseMember.type, path: path === undefined ? `{${activeEnumCase}}` : `${path}.{${activeEnumCase}}`, value: value[activeEnumCase], instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: newValue => {
33
33
  onChange({
34
34
  [discriminatorKey]: activeEnumCase,
35
35
  [activeEnumCase]: newValue,
@@ -2,7 +2,7 @@ import type { FunctionComponent } from "preact";
2
2
  import type { SerializedFloatType } from "../../../node/schema/types/primitives/FloatType.ts";
3
3
  type Props = {
4
4
  type: SerializedFloatType;
5
- value: number;
5
+ value: unknown;
6
6
  onChange: (value: number) => void;
7
7
  };
8
8
  export declare const FloatTypeInput: FunctionComponent<Props>;
@@ -1,9 +1,13 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
2
2
  import { useState } from "preact/hooks";
3
3
  import { validateNumberConstraints } from "../../../shared/validation/number.js";
4
+ import { MismatchingTypeError } from "./utils/MismatchingTypeError.js";
4
5
  import { ValidationErrors } from "./utils/ValidationErrors.js";
5
6
  export const FloatTypeInput = ({ type, value, onChange }) => {
6
- const [stringValue, setStringValue] = useState(value.toString());
7
+ const [stringValue, setStringValue] = useState(typeof value === "number" ? value.toString() : "");
8
+ if (typeof value !== "number") {
9
+ return _jsx(MismatchingTypeError, { expected: "float", actual: value });
10
+ }
7
11
  const errors = validateNumberConstraints(type, value);
8
12
  return (_jsxs("div", { class: "field", children: [_jsx("input", { type: "number", value: stringValue, onInput: event => {
9
13
  setStringValue(event.currentTarget.value);
@@ -4,6 +4,7 @@ import type { InstanceNamesByEntity } from "../../hooks/useInstanceNamesByEntity
4
4
  import type { GetDeclFromDeclName } from "../../hooks/useSecondaryDeclarations.ts";
5
5
  type Props = {
6
6
  type: SerializedIncludeIdentifierType;
7
+ path: string | undefined;
7
8
  value: unknown;
8
9
  instanceNamesByEntity: InstanceNamesByEntity;
9
10
  getDeclFromDeclName: GetDeclFromDeclName;
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
2
2
  import { TypeInput } from "./TypeInput.js";
3
- export const IncludeIdentifierTypeInput = ({ type, value, instanceNamesByEntity, getDeclFromDeclName, onChange, }) => {
3
+ export const IncludeIdentifierTypeInput = ({ type, path, value, instanceNamesByEntity, getDeclFromDeclName, onChange, }) => {
4
4
  const decl = getDeclFromDeclName(type.reference);
5
5
  if (decl === undefined) {
6
6
  return (_jsxs("div", { role: "alert", children: ["Unresolved declaration identifier ", _jsx("code", { children: type.reference })] }));
7
7
  }
8
- return (_jsx(TypeInput, { type: decl.type, value: value, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: onChange }));
8
+ return (_jsx(TypeInput, { type: decl.type, path: path, value: value, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: onChange }));
9
9
  };
@@ -2,7 +2,7 @@ import type { FunctionComponent } from "preact";
2
2
  import type { SerializedIntegerType } from "../../../node/schema/types/primitives/IntegerType.ts";
3
3
  type Props = {
4
4
  type: SerializedIntegerType;
5
- value: number;
5
+ value: unknown;
6
6
  onChange: (value: number) => void;
7
7
  };
8
8
  export declare const IntegerTypeInput: FunctionComponent<Props>;
@@ -1,9 +1,13 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
2
2
  import { useState } from "preact/hooks";
3
3
  import { validateNumberConstraints } from "../../../shared/validation/number.js";
4
+ import { MismatchingTypeError } from "./utils/MismatchingTypeError.js";
4
5
  import { ValidationErrors } from "./utils/ValidationErrors.js";
5
6
  export const IntegerTypeInput = ({ type, value, onChange }) => {
6
- const [stringValue, setStringValue] = useState(value.toString());
7
+ const [stringValue, setStringValue] = useState(typeof value === "number" ? value.toString() : "");
8
+ if (typeof value !== "number") {
9
+ return _jsx(MismatchingTypeError, { expected: "float", actual: value });
10
+ }
7
11
  const errors = validateNumberConstraints(type, value);
8
12
  return (_jsxs("div", { class: "field", children: [_jsx("input", { type: "number", value: stringValue, onInput: event => {
9
13
  setStringValue(event.currentTarget.value);
@@ -4,7 +4,8 @@ import type { InstanceNamesByEntity } from "../../hooks/useInstanceNamesByEntity
4
4
  import type { GetDeclFromDeclName } from "../../hooks/useSecondaryDeclarations.ts";
5
5
  type Props = {
6
6
  type: SerializedNestedEntityMapType;
7
- value: Record<string, unknown>;
7
+ path: string | undefined;
8
+ value: unknown;
8
9
  instanceNamesByEntity: InstanceNamesByEntity;
9
10
  getDeclFromDeclName: GetDeclFromDeclName;
10
11
  onChange: (value: Record<string, unknown>) => void;
@@ -5,8 +5,12 @@ import { toTitleCase } from "../../../shared/utils/string.js";
5
5
  import { createTypeSkeleton } from "../../utils/typeSkeleton.js";
6
6
  import { Select } from "../Select.js";
7
7
  import { TypeInput } from "./TypeInput.js";
8
- export const NestedEntityMapTypeInput = ({ type, value, instanceNamesByEntity, getDeclFromDeclName, onChange, }) => {
8
+ import { MismatchingTypeError } from "./utils/MismatchingTypeError.js";
9
+ export const NestedEntityMapTypeInput = ({ type, path, value, instanceNamesByEntity, getDeclFromDeclName, onChange, }) => {
9
10
  const [newKey, setNewKey] = useState("");
11
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
12
+ return _jsx(MismatchingTypeError, { expected: "object", actual: value });
13
+ }
10
14
  const existingKeys = Object.keys(value);
11
15
  const secondaryInstances = (instanceNamesByEntity[type.secondaryEntity] ?? [])
12
16
  .slice()
@@ -20,7 +24,7 @@ export const NestedEntityMapTypeInput = ({ type, value, instanceNamesByEntity, g
20
24
  // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
21
25
  delete newObj[key];
22
26
  onChange(newObj);
23
- }, children: ["Delete ", name] }) })] }), _jsx(TypeInput, { type: type.type, value: item, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: newItem => {
27
+ }, children: ["Delete ", name] }) })] }), _jsx(TypeInput, { type: type.type, path: path === undefined ? key : `${path}.${key}`, value: item, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: newItem => {
24
28
  onChange(sortObjectKeysAlphabetically({ ...value, [key]: newItem }));
25
29
  } })] }, key));
26
30
  }) })), _jsxs("div", { class: "add-item-container", children: [_jsxs(Select, { value: newKey, onInput: event => {
@@ -4,7 +4,8 @@ import type { InstanceNamesByEntity } from "../../hooks/useInstanceNamesByEntity
4
4
  import type { GetDeclFromDeclName } from "../../hooks/useSecondaryDeclarations.ts";
5
5
  type Props = {
6
6
  type: SerializedObjectType;
7
- value: Record<string, unknown>;
7
+ path: string | undefined;
8
+ value: unknown;
8
9
  instanceNamesByEntity: InstanceNamesByEntity;
9
10
  getDeclFromDeclName: GetDeclFromDeclName;
10
11
  onChange: (value: Record<string, unknown>) => void;
@@ -5,10 +5,15 @@ import { validateObjectConstraints } from "../../../shared/validation/object.js"
5
5
  import { Markdown } from "../../utils/Markdown.js";
6
6
  import { createTypeSkeleton } from "../../utils/typeSkeleton.js";
7
7
  import { TypeInput } from "./TypeInput.js";
8
+ import { MismatchingTypeError } from "./utils/MismatchingTypeError.js";
8
9
  import { ValidationErrors } from "./utils/ValidationErrors.js";
9
- export const ObjectTypeInput = ({ type, value, instanceNamesByEntity, getDeclFromDeclName, onChange, }) => {
10
+ export const ObjectTypeInput = ({ type, path, value, instanceNamesByEntity, getDeclFromDeclName, onChange, }) => {
11
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
12
+ return _jsx(MismatchingTypeError, { expected: "object", actual: value });
13
+ }
10
14
  const errors = validateObjectConstraints(type, Object.keys(type.properties), value);
11
- return (_jsxs("div", { class: "field field--container field--object", children: [_jsx("ul", { children: Object.entries(type.properties).map(([key, memberDecl]) => (_jsxs("li", { class: "container-item object-item", children: [_jsxs("div", { className: "container-item-header", children: [_jsxs("div", { className: "container-item-title", children: [_jsx("strong", { children: toTitleCase(key) }), memberDecl.comment === undefined ? null : (_jsx(Markdown, { class: "comment", string: memberDecl.comment }))] }), memberDecl.isRequired ? null : value[key] === undefined ? (_jsxs("button", { onClick: () => {
15
+ return (_jsxs("div", { class: "field field--container field--object", children: [_jsx("ul", { children: Object.entries(type.properties).map(([key, memberDecl]) => (_jsxs("li", { class: "container-item object-item", children: [_jsxs("div", { className: "container-item-header", children: [_jsxs("div", { className: "container-item-title", children: [_jsx("strong", { children: toTitleCase(key) }), memberDecl.comment === undefined ? null : (_jsx(Markdown, { class: "comment", string: memberDecl.comment }))] }), memberDecl.isRequired ? null : value[key] ===
16
+ undefined ? (_jsxs("button", { onClick: () => {
12
17
  onChange(sortObjectKeys({
13
18
  ...value,
14
19
  [key]: createTypeSkeleton(getDeclFromDeclName, memberDecl.type),
@@ -18,7 +23,7 @@ export const ObjectTypeInput = ({ type, value, instanceNamesByEntity, getDeclFro
18
23
  // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
19
24
  delete newObj[key];
20
25
  onChange(newObj);
21
- }, children: ["Remove ", toTitleCase(key)] }))] }), memberDecl.isRequired || value[key] !== undefined ? (_jsx(TypeInput, { type: memberDecl.type, value: value[key], instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: newItem => {
26
+ }, children: ["Remove ", toTitleCase(key)] }))] }), memberDecl.isRequired || value[key] !== undefined ? (_jsx(TypeInput, { type: memberDecl.type, path: path === undefined ? key : `${path}.${key}`, value: value[key], instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: newItem => {
22
27
  onChange(sortObjectKeys({ ...value, [key]: newItem }, Object.keys(type.properties)));
23
28
  } })) : null] }, key))) }), _jsx(ValidationErrors, { errors: errors })] }));
24
29
  };
@@ -3,7 +3,7 @@ import type { SerializedReferenceIdentifierType } from "../../../node/schema/typ
3
3
  import type { InstanceNamesByEntity } from "../../hooks/useInstanceNamesByEntity.ts";
4
4
  type Props = {
5
5
  type: SerializedReferenceIdentifierType;
6
- value: string;
6
+ value: unknown;
7
7
  instanceNamesByEntity: InstanceNamesByEntity;
8
8
  onChange: (value: string) => void;
9
9
  };
@@ -1,7 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
2
2
  import { Select } from "../Select.js";
3
+ import { MismatchingTypeError } from "./utils/MismatchingTypeError.js";
3
4
  import { ValidationErrors } from "./utils/ValidationErrors.js";
4
5
  export const ReferenceIdentifierTypeInput = ({ type, value, instanceNamesByEntity, onChange, }) => {
6
+ if (typeof value !== "string") {
7
+ return _jsx(MismatchingTypeError, { expected: "string identifier", actual: value });
8
+ }
5
9
  const instances = (instanceNamesByEntity[type.entity] ?? [])
6
10
  .slice()
7
11
  .sort((a, b) => a.name.localeCompare(b.name, undefined, { numeric: true }));
@@ -2,7 +2,7 @@ import type { FunctionComponent } from "preact";
2
2
  import type { SerializedStringType } from "../../../node/schema/types/primitives/StringType.ts";
3
3
  type Props = {
4
4
  type: SerializedStringType;
5
- value: string;
5
+ value: unknown;
6
6
  onChange: (value: string) => void;
7
7
  };
8
8
  export declare const StringTypeInput: FunctionComponent<Props>;
@@ -1,8 +1,12 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "preact/jsx-runtime";
2
2
  import { validateStringConstraints } from "../../../shared/validation/string.js";
3
3
  import { Markdown } from "../../utils/Markdown.js";
4
+ import { MismatchingTypeError } from "./utils/MismatchingTypeError.js";
4
5
  import { ValidationErrors } from "./utils/ValidationErrors.js";
5
6
  export const StringTypeInput = ({ type, value, onChange }) => {
7
+ if (typeof value !== "string") {
8
+ return _jsx(MismatchingTypeError, { expected: "string", actual: value });
9
+ }
6
10
  const { minLength, maxLength, pattern, isMarkdown } = type;
7
11
  const errors = validateStringConstraints(type, value);
8
12
  return (_jsx("div", { class: "field field--string", children: isMarkdown ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "editor", children: [_jsx("div", { class: "textarea-grow-wrap", "data-value": value, children: _jsx("textarea", { value: value, minLength: minLength, maxLength: maxLength, onInput: event => {
@@ -4,6 +4,7 @@ import type { InstanceNamesByEntity } from "../../hooks/useInstanceNamesByEntity
4
4
  import type { GetDeclFromDeclName } from "../../hooks/useSecondaryDeclarations.ts";
5
5
  type Props = {
6
6
  type: SerializedType;
7
+ path: string | undefined;
7
8
  value: unknown;
8
9
  instanceNamesByEntity: InstanceNamesByEntity;
9
10
  getDeclFromDeclName: GetDeclFromDeclName;
@@ -1,6 +1,5 @@
1
1
  import { jsx as _jsx } from "preact/jsx-runtime";
2
2
  import { memo } from "preact/compat";
3
- import { deepEqual } from "../../../shared/utils/compare.js";
4
3
  import { assertExhaustive } from "../../../shared/utils/typeSafety.js";
5
4
  import { ArrayTypeInput } from "./ArrayTypeInput.js";
6
5
  import { BooleanTypeInput } from "./BooleanTypeInput.js";
@@ -14,81 +13,36 @@ import { NestedEntityMapTypeInput } from "./NestedEntityMapTypeInput.js";
14
13
  import { ObjectTypeInput } from "./ObjectTypeInput.js";
15
14
  import { ReferenceIdentifierTypeInput } from "./ReferenceIdentifierTypeInput.js";
16
15
  import { StringTypeInput } from "./StringTypeInput.js";
17
- import { MismatchingTypeError } from "./utils/MismatchingTypeError.js";
18
- const TypeInput = ({ type, value, instanceNamesByEntity, getDeclFromDeclName, onChange, }) => {
16
+ const TypeInput = ({ type, path, value, instanceNamesByEntity, getDeclFromDeclName, onChange, }) => {
17
+ // console.log("rendering node at path ", path ?? "<root>")
19
18
  switch (type.kind) {
20
19
  case "BooleanType":
21
- if (typeof value === "boolean") {
22
- return _jsx(BooleanTypeInput, { type: type, value: value, onChange: onChange });
23
- }
24
- else {
25
- return _jsx(MismatchingTypeError, { expected: "boolean", actual: value });
26
- }
20
+ return _jsx(BooleanTypeInput, { type: type, value: value, onChange: onChange });
27
21
  case "DateType":
28
- if (typeof value === "string") {
29
- return _jsx(DateTypeInput, { type: type, value: value, onChange: onChange });
30
- }
31
- else {
32
- return _jsx(MismatchingTypeError, { expected: "date string", actual: value });
33
- }
22
+ return _jsx(DateTypeInput, { type: type, value: value, onChange: onChange });
34
23
  case "FloatType":
35
- if (typeof value === "number") {
36
- return _jsx(FloatTypeInput, { type: type, value: value, onChange: onChange });
37
- }
38
- else {
39
- return _jsx(MismatchingTypeError, { expected: "float", actual: value });
40
- }
24
+ return _jsx(FloatTypeInput, { type: type, value: value, onChange: onChange });
41
25
  case "IntegerType":
42
- if (typeof value === "number" && Number.isInteger(value)) {
43
- return _jsx(IntegerTypeInput, { type: type, value: value, onChange: onChange });
44
- }
45
- else {
46
- return _jsx(MismatchingTypeError, { expected: "integer", actual: value });
47
- }
26
+ return _jsx(IntegerTypeInput, { type: type, value: value, onChange: onChange });
48
27
  case "StringType":
49
- if (typeof value === "string") {
50
- return _jsx(StringTypeInput, { type: type, value: value, onChange: onChange });
51
- }
52
- else {
53
- return _jsx(MismatchingTypeError, { expected: "string", actual: value });
54
- }
28
+ return _jsx(StringTypeInput, { type: type, value: value, onChange: onChange });
55
29
  case "ArrayType":
56
- if (Array.isArray(value)) {
57
- return (_jsx(ArrayTypeInput, { type: type, value: value, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: onChange }));
58
- }
59
- else {
60
- return _jsx(MismatchingTypeError, { expected: "array", actual: value });
61
- }
30
+ return (_jsx(ArrayTypeInput, { type: type, path: path, value: value, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: onChange }));
62
31
  case "ObjectType":
63
- if (typeof value === "object" && value !== null && !Array.isArray(value)) {
64
- return (_jsx(ObjectTypeInput, { type: type, value: value, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: onChange }));
65
- }
66
- else {
67
- return _jsx(MismatchingTypeError, { expected: "object", actual: value });
68
- }
32
+ return (_jsx(ObjectTypeInput, { type: type, path: path, value: value, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: onChange }));
69
33
  case "TypeArgumentType":
70
34
  return _jsx(TypeArgumentTypeInput, { type: type });
71
35
  case "ReferenceIdentifierType":
72
- if (typeof value === "string") {
73
- return (_jsx(ReferenceIdentifierTypeInput, { type: type, value: value, instanceNamesByEntity: instanceNamesByEntity, onChange: onChange }));
74
- }
75
- else {
76
- return _jsx(MismatchingTypeError, { expected: "string identifier", actual: value });
77
- }
36
+ return (_jsx(ReferenceIdentifierTypeInput, { type: type, value: value, instanceNamesByEntity: instanceNamesByEntity, onChange: onChange }));
78
37
  case "IncludeIdentifierType":
79
- return (_jsx(IncludeIdentifierTypeInput, { type: type, value: value, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: onChange }));
38
+ return (_jsx(IncludeIdentifierTypeInput, { type: type, path: path, value: value, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: onChange }));
80
39
  case "NestedEntityMapType":
81
- if (typeof value === "object" && value !== null && !Array.isArray(value)) {
82
- return (_jsx(NestedEntityMapTypeInput, { type: type, value: value, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: onChange }));
83
- }
84
- else {
85
- return _jsx(MismatchingTypeError, { expected: "entity map", actual: value });
86
- }
40
+ return (_jsx(NestedEntityMapTypeInput, { type: type, path: path, value: value, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: onChange }));
87
41
  case "EnumType":
88
- return (_jsx(EnumTypeInput, { type: type, value: value, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: onChange }));
42
+ return (_jsx(EnumTypeInput, { type: type, path: path, value: value, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: onChange }));
89
43
  default:
90
44
  return assertExhaustive(type);
91
45
  }
92
46
  };
93
- const MemoizedTypeInput = memo(TypeInput, (prevProps, nextProps) => deepEqual(prevProps.value, nextProps.value));
47
+ const MemoizedTypeInput = memo(TypeInput, (prevProps, nextProps) => prevProps.value === nextProps.value && prevProps.onChange === nextProps.onChange);
94
48
  export { MemoizedTypeInput as TypeInput };
@@ -77,7 +77,7 @@ export const CreateInstance = () => {
77
77
  { url: `/entities/${entity.name}`, label: entity.name },
78
78
  ], children: [_jsx("div", { class: "header-with-btns", children: _jsx("h1", { class: instanceName.length === 0 ? "empty-name" : undefined, children: instanceName || defaultName }) }), isLocaleEntity && (_jsxs("div", { class: "field field--id", children: [_jsx("label", { htmlFor: "id", children: "ID" }), _jsx("p", { className: "comment", children: "The instance\u2019s identifier. An IETF language tag (BCP47)." }), _jsx("input", { type: "text", id: "id", value: customId, required: true, pattern: "[a-z]{2,3}(-[A-Z]{2,3})?", placeholder: "en-US, de-DE, \u2026", onInput: event => {
79
79
  setCustomId(event.currentTarget.value);
80
- }, "aria-invalid": idErrors.length > 0 }), _jsx(ValidationErrors, { errors: idErrors })] })), _jsxs("form", { onSubmit: handleSubmit, children: [_jsx(TypeInput, { type: entity.type, value: instance, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: value => {
80
+ }, "aria-invalid": idErrors.length > 0 }), _jsx(ValidationErrors, { errors: idErrors })] })), _jsxs("form", { onSubmit: handleSubmit, children: [_jsx(TypeInput, { type: entity.type, path: undefined, value: instance, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: value => {
81
81
  console.log("onChange", value);
82
82
  setInstance(value);
83
83
  } }), _jsxs("div", { class: "form-footer btns", children: [_jsx("button", { type: "submit", class: "primary", name: "save", children: "Save" }), _jsx("button", { type: "submit", class: "primary", name: "saveandcontinue", children: "Save and Continue" }), _jsx("button", { type: "submit", class: "primary", name: "saveandaddanother", children: "Save and Add Another" })] })] })] }));
@@ -9,6 +9,7 @@ import { TypeInput } from "../components/typeInputs/TypeInput.js";
9
9
  import { useEntityFromRoute } from "../hooks/useEntityFromRoute.js";
10
10
  import { useInstanceNamesByEntity } from "../hooks/useInstanceNamesByEntity.js";
11
11
  import { useGetDeclFromDeclName } from "../hooks/useSecondaryDeclarations.js";
12
+ import { printJson } from "../utils/debug.js";
12
13
  import { NotFound } from "./NotFound.js";
13
14
  export const Instance = () => {
14
15
  const { params: { name, id }, } = useRoute();
@@ -19,7 +20,7 @@ export const Instance = () => {
19
20
  const [originalInstance, setOriginalInstance] = useState();
20
21
  const { route } = useLocation();
21
22
  useEffect(() => {
22
- if (entityFromRoute && instance && id) {
23
+ if (entityFromRoute?.entity && instance?.content && id) {
23
24
  const defaultName = id;
24
25
  const instanceName = getSerializedDisplayNameFromEntityInstance(entityFromRoute.entity, instance.content, defaultName);
25
26
  const entityName = entityFromRoute.entity.name;
@@ -28,7 +29,7 @@ export const Instance = () => {
28
29
  else {
29
30
  document.title = "Not found — TSONDB";
30
31
  }
31
- }, [entityFromRoute, id, instance]);
32
+ }, [entityFromRoute?.entity, id, instance?.content]);
32
33
  useEffect(() => {
33
34
  if (name && id) {
34
35
  getInstanceByEntityNameAndId(name, id)
@@ -89,5 +90,5 @@ export const Instance = () => {
89
90
  }
90
91
  });
91
92
  }
92
- }, children: "Delete" })] }), _jsxs("form", { onSubmit: handleSubmit, children: [_jsx(TypeInput, { type: entityFromRoute.entity.type, value: instance.content, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: handleOnChange }), _jsx("div", { class: "form-footer btns", children: _jsx("button", { type: "submit", name: "save", class: "primary", children: "Save" }) })] })] }));
93
+ }, children: "Delete" })] }), _jsxs("div", { class: "debug-compare", style: { display: "flex", gap: "1rem", width: "100%" }, children: [_jsxs("div", { style: { flex: "1 1 0", position: "relative" }, children: [_jsx("p", { children: "Original" }), _jsx("pre", { style: { overflowX: "scroll", width: "40rem", maxWidth: "100%" }, children: _jsx("code", { dangerouslySetInnerHTML: { __html: printJson(originalInstance.content) } }) })] }), _jsxs("div", { style: { flex: "1 1 0", position: "relative" }, children: [_jsx("p", { children: "Current" }), _jsx("pre", { style: { overflowX: "scroll", width: "40rem", maxWidth: "100%" }, children: _jsx("code", { dangerouslySetInnerHTML: { __html: printJson(instance.content) } }) })] })] }), _jsxs("form", { onSubmit: handleSubmit, children: [_jsx(TypeInput, { type: entityFromRoute.entity.type, value: instance.content, path: undefined, instanceNamesByEntity: instanceNamesByEntity, getDeclFromDeclName: getDeclFromDeclName, onChange: handleOnChange }), _jsx("div", { class: "form-footer btns", children: _jsx("button", { type: "submit", name: "save", class: "primary", children: "Save" }) })] })] }));
93
94
  };
@@ -0,0 +1 @@
1
+ export declare const printJson: (data: unknown) => string;
@@ -0,0 +1,5 @@
1
+ export const printJson = (data) => JSON.stringify(data, undefined, 2)
2
+ .replace(/\n *([}\]],?)/g, " $1")
3
+ .replace(/((?:^|\n *)[{[])\n +/g, "$1 ")
4
+ .replace(/"(.+?)":/g, '<span style="color: darkorange">$1</span>:')
5
+ .replace(/ "(.*?)"([ ,])/g, ' <span style="color: darkgreen">"$1"</span>$2');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tsondb",
3
- "version": "0.5.10",
3
+ "version": "0.5.12",
4
4
  "description": "",
5
5
  "license": "ISC",
6
6
  "author": "Lukas Obermann",
@@ -292,13 +292,13 @@ input[type="checkbox"]:checked {
292
292
  input[type="checkbox"]:checked::before {
293
293
  content: "";
294
294
  display: block;
295
- border-width: 0 0 1px 1px;
295
+ border-width: 0 0 0.125rem 0.125rem;
296
296
  border-style: solid;
297
- width: 0.6rem;
298
- height: 0.3rem;
297
+ width: 0.8rem;
298
+ height: 0.4rem;
299
299
  border-color: var(--background);
300
300
  transform: rotate(-45deg);
301
- margin: calc(-0.2rem - 1px) 0 0 calc(-0.275rem - 1px);
301
+ margin: calc(-0.325rem) 0 0 calc(-0.4rem);
302
302
  }
303
303
 
304
304
  .select-wrapper {