strapi-plugin-json-schema-validation 0.0.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/README.md +3 -0
- package/dist/admin/en-BraAp_Lr.js +16 -0
- package/dist/admin/en-BraAp_Lr.js.map +1 -0
- package/dist/admin/en-Cum_oOSk.mjs +16 -0
- package/dist/admin/en-Cum_oOSk.mjs.map +1 -0
- package/dist/admin/index-BcXgK01l.js +4392 -0
- package/dist/admin/index-BcXgK01l.js.map +1 -0
- package/dist/admin/index-C3Q0T-w5.mjs +4393 -0
- package/dist/admin/index-C3Q0T-w5.mjs.map +1 -0
- package/dist/admin/index-C42REwDe.js +138 -0
- package/dist/admin/index-C42REwDe.js.map +1 -0
- package/dist/admin/index-C9Ge6gj7.mjs +135 -0
- package/dist/admin/index-C9Ge6gj7.mjs.map +1 -0
- package/dist/admin/index.js +6 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/index.mjs +6 -0
- package/dist/admin/index.mjs.map +1 -0
- package/dist/admin/src/components/Initializer.d.ts +5 -0
- package/dist/admin/src/components/JSONSchemaValidationInput/index.d.ts +3 -0
- package/dist/admin/src/components/JSONSchemaValidationInput/styled.d.ts +13 -0
- package/dist/admin/src/components/PluginIcon.d.ts +2 -0
- package/dist/admin/src/index.d.ts +13 -0
- package/dist/admin/src/pages/App.d.ts +2 -0
- package/dist/admin/src/pages/HomePage.d.ts +2 -0
- package/dist/admin/src/translations/en.json.d.ts +11 -0
- package/dist/admin/src/translations/types.d.ts +3 -0
- package/dist/admin/src/utils/getTranslation.d.ts +3 -0
- package/dist/admin/src/utils/prefixPluginTranslation.d.ts +3 -0
- package/dist/admin/src/utils/preloadedJsonSchema.d.ts +3 -0
- package/dist/server/index.js +164 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/index.mjs +161 -0
- package/dist/server/index.mjs.map +1 -0
- package/dist/server/src/bootstrap.d.ts +5 -0
- package/dist/server/src/config/index.d.ts +5 -0
- package/dist/server/src/content-types/index.d.ts +2 -0
- package/dist/server/src/controllers/controller.d.ts +9 -0
- package/dist/server/src/controllers/index.d.ts +25 -0
- package/dist/server/src/controllers/validation.d.ts +10 -0
- package/dist/server/src/destroy.d.ts +5 -0
- package/dist/server/src/index.d.ts +82 -0
- package/dist/server/src/middlewares/index.d.ts +2 -0
- package/dist/server/src/policies/index.d.ts +2 -0
- package/dist/server/src/register.d.ts +5 -0
- package/dist/server/src/routes/admin/index.d.ts +9 -0
- package/dist/server/src/routes/content-api/index.d.ts +12 -0
- package/dist/server/src/routes/index.d.ts +22 -0
- package/dist/server/src/services/index.d.ts +40 -0
- package/dist/server/src/services/service.d.ts +9 -0
- package/dist/server/src/services/validation.d.ts +31 -0
- package/dist/server/src/utils/ajv.d.ts +3 -0
- package/dist/server/src/utils/names.d.ts +4 -0
- package/package.json +96 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
4
|
+
const Editor = require("@monaco-editor/react");
|
|
5
|
+
const designSystem = require("@strapi/design-system");
|
|
6
|
+
const react = require("react");
|
|
7
|
+
const reactIntl = require("react-intl");
|
|
8
|
+
const admin = require("@strapi/strapi/admin");
|
|
9
|
+
const styled = require("styled-components");
|
|
10
|
+
const index = require("./index-BcXgK01l.js");
|
|
11
|
+
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
12
|
+
const Editor__default = /* @__PURE__ */ _interopDefault(Editor);
|
|
13
|
+
const styled__default = /* @__PURE__ */ _interopDefault(styled);
|
|
14
|
+
const Styled = {
|
|
15
|
+
FieldContainer: styled__default.default(designSystem.Flex)`
|
|
16
|
+
position: relative;
|
|
17
|
+
`,
|
|
18
|
+
ValidationButton: styled__default.default(designSystem.Button)``
|
|
19
|
+
};
|
|
20
|
+
const JSONSchemaValidationInput = react.forwardRef((props, ref) => {
|
|
21
|
+
const {
|
|
22
|
+
attribute,
|
|
23
|
+
description,
|
|
24
|
+
disabled,
|
|
25
|
+
error,
|
|
26
|
+
hint,
|
|
27
|
+
intlLabel,
|
|
28
|
+
label,
|
|
29
|
+
name,
|
|
30
|
+
onChange,
|
|
31
|
+
required,
|
|
32
|
+
value
|
|
33
|
+
} = props;
|
|
34
|
+
const editorRef = react.useRef(null);
|
|
35
|
+
function triggerEditorFormat() {
|
|
36
|
+
if (editorRef.current != null) {
|
|
37
|
+
editorRef.current.trigger("manual", "editor.action.formatDocument");
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const { formatMessage } = reactIntl.useIntl();
|
|
41
|
+
const { get, post } = admin.useFetchClient();
|
|
42
|
+
const [internalValue, setInternalValue] = react.useState(value);
|
|
43
|
+
const [internalError, setInternalError] = react.useState(error);
|
|
44
|
+
const validateJSONSchema = async (jsonSchema, data) => {
|
|
45
|
+
let parsedSchema;
|
|
46
|
+
let parsedData;
|
|
47
|
+
try {
|
|
48
|
+
parsedSchema = typeof jsonSchema === "string" ? JSON.parse(jsonSchema) : jsonSchema;
|
|
49
|
+
parsedData = typeof data === "string" ? JSON.parse(data) : data;
|
|
50
|
+
} catch (err) {
|
|
51
|
+
console.error("Error parsing JSON Schema or data:", err);
|
|
52
|
+
return { error: "Error parsing JSON Schema or data", isValid: false };
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
const response = await post(`/${index.PLUGIN_ID}/validateSchema`, {
|
|
56
|
+
schema: parsedSchema,
|
|
57
|
+
data: parsedData
|
|
58
|
+
});
|
|
59
|
+
return response.data;
|
|
60
|
+
} catch (err) {
|
|
61
|
+
console.error("Error while validating JSON Schema:", err);
|
|
62
|
+
return { error: "Error while validating JSON Schema", isValid: false };
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
const handleValidateClick = async () => {
|
|
66
|
+
triggerEditorFormat();
|
|
67
|
+
console.log("attribute", attribute);
|
|
68
|
+
if (!internalValue) {
|
|
69
|
+
setInternalError("JSON Schema is required");
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const result = await validateJSONSchema(attribute["options"]["jsonSchema"], internalValue);
|
|
73
|
+
console.log("result", result);
|
|
74
|
+
if (result.data.isValid) {
|
|
75
|
+
setInternalError("");
|
|
76
|
+
onChange({ target: { name, value: internalValue } });
|
|
77
|
+
} else {
|
|
78
|
+
setInternalError(
|
|
79
|
+
result.data.errors ? `Validation errors: ${result.data.errors.map((e) => e.message).join("\n")}` : result.data.processingError ? `Processing error: ${result.data.processingError}` : "Invalid JSON Schema or data"
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
84
|
+
designSystem.Field.Root,
|
|
85
|
+
{
|
|
86
|
+
error: internalError,
|
|
87
|
+
hint: description?.id ? formatMessage(description) : hint,
|
|
88
|
+
name,
|
|
89
|
+
required,
|
|
90
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "stretch", direction: "column", gap: 1, children: [
|
|
91
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: intlLabel?.id ? formatMessage(intlLabel) : label }),
|
|
92
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "flex-start", direction: "row", gap: 2, ref, children: [
|
|
93
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
94
|
+
Editor__default.default,
|
|
95
|
+
{
|
|
96
|
+
defaultLanguage: "json",
|
|
97
|
+
height: "50rem",
|
|
98
|
+
loading: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: "Loading JSON Editor..." }),
|
|
99
|
+
options: {
|
|
100
|
+
fontSize: 13,
|
|
101
|
+
formatOnPaste: true,
|
|
102
|
+
formatOnType: true,
|
|
103
|
+
minimap: { enabled: true }
|
|
104
|
+
},
|
|
105
|
+
value: internalValue,
|
|
106
|
+
onChange: (value2) => setInternalValue(value2 || ""),
|
|
107
|
+
theme: "vs-dark",
|
|
108
|
+
beforeMount: (monaco) => {
|
|
109
|
+
if (monaco) {
|
|
110
|
+
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
|
|
111
|
+
validate: true,
|
|
112
|
+
schemas: [
|
|
113
|
+
{
|
|
114
|
+
// uri: MY_JSON_SCHEMA.id,
|
|
115
|
+
fileMatch: ["*"],
|
|
116
|
+
// Apply this schema to the current editor instance
|
|
117
|
+
schema: JSON.parse(attribute["options"]["jsonSchema"])
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
onMount: (editor) => {
|
|
124
|
+
editorRef.current = editor;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
),
|
|
128
|
+
/* @__PURE__ */ jsxRuntime.jsx(Styled.ValidationButton, { onClick: handleValidateClick, size: "S", children: "Validate" })
|
|
129
|
+
] }),
|
|
130
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {}),
|
|
131
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Error, {})
|
|
132
|
+
] })
|
|
133
|
+
}
|
|
134
|
+
);
|
|
135
|
+
});
|
|
136
|
+
exports.JSONSchemaValidationInput = JSONSchemaValidationInput;
|
|
137
|
+
exports.default = JSONSchemaValidationInput;
|
|
138
|
+
//# sourceMappingURL=index-C42REwDe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-C42REwDe.js","sources":["../../admin/src/components/JSONSchemaValidationInput/styled.tsx","../../admin/src/components/JSONSchemaValidationInput/index.tsx"],"sourcesContent":["import { Button, Flex } from '@strapi/design-system';\nimport styled from 'styled-components';\n\nexport const Styled = {\n FieldContainer: styled(Flex)`\n position: relative;\n `,\n\n ValidationButton: styled(Button)``,\n};\n\nexport default Styled;\n","import Editor, { EditorProps } from '@monaco-editor/react';\nimport { Field, Flex, Typography } from '@strapi/design-system';\nimport { useField } from '@strapi/strapi/admin';\nimport React, { forwardRef, useMemo, useRef, useState } from 'react';\nimport { useIntl } from 'react-intl';\nimport { useFetchClient } from '@strapi/strapi/admin';\n\nimport { Styled } from './styled';\nimport { PLUGIN_ID } from '../../../../shared/constants/plugin';\n\nexport const JSONSchemaValidationInput = forwardRef<HTMLElement, any>((props, ref) => {\n const {\n attribute,\n description,\n disabled,\n error,\n hint,\n intlLabel,\n label,\n name,\n onChange,\n required,\n value,\n } = props; // these are just some of the props passed by the content-manager\n\n const editorRef = useRef<Parameters<NonNullable<EditorProps['onMount']>>[0]>(null);\n\n function triggerEditorFormat() {\n if (editorRef.current != null) {\n // Manually trigger the format document action\n editorRef.current.trigger('manual', 'editor.action.formatDocument');\n }\n }\n\n const { formatMessage } = useIntl();\n const { get, post } = useFetchClient();\n\n const [internalValue, setInternalValue] = useState<string>(value);\n const [internalError, setInternalError] = useState<string>(error);\n\n const validateJSONSchema = async (jsonSchema: string | object, data: string | object) => {\n let parsedSchema: object;\n let parsedData: object;\n try {\n parsedSchema = typeof jsonSchema === 'string' ? JSON.parse(jsonSchema) : jsonSchema;\n parsedData = typeof data === 'string' ? JSON.parse(data) : data;\n } catch (err) {\n console.error('Error parsing JSON Schema or data:', err);\n return { error: 'Error parsing JSON Schema or data', isValid: false };\n }\n\n try {\n const response = await post(`/${PLUGIN_ID}/validateSchema`, {\n schema: parsedSchema,\n data: parsedData,\n });\n return response.data;\n } catch (err) {\n console.error('Error while validating JSON Schema:', err);\n return { error: 'Error while validating JSON Schema', isValid: false };\n }\n };\n // const { onChange, value, error } = useField(name);\n\n const handleValidateClick = async () => {\n triggerEditorFormat();\n console.log('attribute', attribute);\n\n if (!internalValue) {\n setInternalError('JSON Schema is required');\n return;\n }\n\n const result = await validateJSONSchema(attribute['options']['jsonSchema'], internalValue);\n\n console.log('result', result);\n\n if (result.data.isValid) {\n setInternalError('');\n onChange({ target: { name, value: internalValue } });\n } else {\n setInternalError(\n result.data.errors\n ? `Validation errors: ${result.data.errors.map((e) => e.message).join('\\n')}`\n : result.data.processingError\n ? `Processing error: ${result.data.processingError}`\n : 'Invalid JSON Schema or data'\n );\n }\n };\n\n return (\n <Field.Root\n error={internalError}\n hint={description?.id ? formatMessage(description) : hint}\n name={name}\n required={required}\n >\n <Flex alignItems=\"stretch\" direction=\"column\" gap={1}>\n <Field.Label>{intlLabel?.id ? formatMessage(intlLabel) : label}</Field.Label>\n <Flex alignItems={'flex-start'} direction={'row'} gap={2} ref={ref}>\n <Editor\n defaultLanguage=\"json\"\n height=\"50rem\"\n loading={<Typography>Loading JSON Editor...</Typography>}\n options={{\n fontSize: 13,\n formatOnPaste: true,\n formatOnType: true,\n minimap: { enabled: true },\n }}\n value={internalValue}\n onChange={(value) => setInternalValue(value || '')}\n theme=\"vs-dark\"\n beforeMount={(monaco) => {\n if (monaco) {\n monaco.languages.json.jsonDefaults.setDiagnosticsOptions({\n validate: true,\n schemas: [\n {\n // uri: MY_JSON_SCHEMA.id,\n fileMatch: ['*'], // Apply this schema to the current editor instance\n schema: JSON.parse(attribute['options']['jsonSchema']),\n },\n ],\n });\n }\n }}\n onMount={(editor) => {\n editorRef.current = editor;\n }}\n />\n <Styled.ValidationButton onClick={handleValidateClick} size=\"S\">\n Validate\n </Styled.ValidationButton>\n </Flex>\n <Field.Hint />\n <Field.Error />\n </Flex>\n </Field.Root>\n );\n});\n\nexport default JSONSchemaValidationInput;\n"],"names":["styled","Flex","Button","forwardRef","useRef","useIntl","useFetchClient","useState","PLUGIN_ID","jsx","Field","jsxs","Editor","Typography","value"],"mappings":"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"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import Editor from "@monaco-editor/react";
|
|
3
|
+
import { Button, Flex, Field, Typography } from "@strapi/design-system";
|
|
4
|
+
import { forwardRef, useRef, useState } from "react";
|
|
5
|
+
import { useIntl } from "react-intl";
|
|
6
|
+
import { useFetchClient } from "@strapi/strapi/admin";
|
|
7
|
+
import styled from "styled-components";
|
|
8
|
+
import { P as PLUGIN_ID } from "./index-C3Q0T-w5.mjs";
|
|
9
|
+
const Styled = {
|
|
10
|
+
FieldContainer: styled(Flex)`
|
|
11
|
+
position: relative;
|
|
12
|
+
`,
|
|
13
|
+
ValidationButton: styled(Button)``
|
|
14
|
+
};
|
|
15
|
+
const JSONSchemaValidationInput = forwardRef((props, ref) => {
|
|
16
|
+
const {
|
|
17
|
+
attribute,
|
|
18
|
+
description,
|
|
19
|
+
disabled,
|
|
20
|
+
error,
|
|
21
|
+
hint,
|
|
22
|
+
intlLabel,
|
|
23
|
+
label,
|
|
24
|
+
name,
|
|
25
|
+
onChange,
|
|
26
|
+
required,
|
|
27
|
+
value
|
|
28
|
+
} = props;
|
|
29
|
+
const editorRef = useRef(null);
|
|
30
|
+
function triggerEditorFormat() {
|
|
31
|
+
if (editorRef.current != null) {
|
|
32
|
+
editorRef.current.trigger("manual", "editor.action.formatDocument");
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const { formatMessage } = useIntl();
|
|
36
|
+
const { get, post } = useFetchClient();
|
|
37
|
+
const [internalValue, setInternalValue] = useState(value);
|
|
38
|
+
const [internalError, setInternalError] = useState(error);
|
|
39
|
+
const validateJSONSchema = async (jsonSchema, data) => {
|
|
40
|
+
let parsedSchema;
|
|
41
|
+
let parsedData;
|
|
42
|
+
try {
|
|
43
|
+
parsedSchema = typeof jsonSchema === "string" ? JSON.parse(jsonSchema) : jsonSchema;
|
|
44
|
+
parsedData = typeof data === "string" ? JSON.parse(data) : data;
|
|
45
|
+
} catch (err) {
|
|
46
|
+
console.error("Error parsing JSON Schema or data:", err);
|
|
47
|
+
return { error: "Error parsing JSON Schema or data", isValid: false };
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
const response = await post(`/${PLUGIN_ID}/validateSchema`, {
|
|
51
|
+
schema: parsedSchema,
|
|
52
|
+
data: parsedData
|
|
53
|
+
});
|
|
54
|
+
return response.data;
|
|
55
|
+
} catch (err) {
|
|
56
|
+
console.error("Error while validating JSON Schema:", err);
|
|
57
|
+
return { error: "Error while validating JSON Schema", isValid: false };
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
const handleValidateClick = async () => {
|
|
61
|
+
triggerEditorFormat();
|
|
62
|
+
console.log("attribute", attribute);
|
|
63
|
+
if (!internalValue) {
|
|
64
|
+
setInternalError("JSON Schema is required");
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const result = await validateJSONSchema(attribute["options"]["jsonSchema"], internalValue);
|
|
68
|
+
console.log("result", result);
|
|
69
|
+
if (result.data.isValid) {
|
|
70
|
+
setInternalError("");
|
|
71
|
+
onChange({ target: { name, value: internalValue } });
|
|
72
|
+
} else {
|
|
73
|
+
setInternalError(
|
|
74
|
+
result.data.errors ? `Validation errors: ${result.data.errors.map((e) => e.message).join("\n")}` : result.data.processingError ? `Processing error: ${result.data.processingError}` : "Invalid JSON Schema or data"
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
return /* @__PURE__ */ jsx(
|
|
79
|
+
Field.Root,
|
|
80
|
+
{
|
|
81
|
+
error: internalError,
|
|
82
|
+
hint: description?.id ? formatMessage(description) : hint,
|
|
83
|
+
name,
|
|
84
|
+
required,
|
|
85
|
+
children: /* @__PURE__ */ jsxs(Flex, { alignItems: "stretch", direction: "column", gap: 1, children: [
|
|
86
|
+
/* @__PURE__ */ jsx(Field.Label, { children: intlLabel?.id ? formatMessage(intlLabel) : label }),
|
|
87
|
+
/* @__PURE__ */ jsxs(Flex, { alignItems: "flex-start", direction: "row", gap: 2, ref, children: [
|
|
88
|
+
/* @__PURE__ */ jsx(
|
|
89
|
+
Editor,
|
|
90
|
+
{
|
|
91
|
+
defaultLanguage: "json",
|
|
92
|
+
height: "50rem",
|
|
93
|
+
loading: /* @__PURE__ */ jsx(Typography, { children: "Loading JSON Editor..." }),
|
|
94
|
+
options: {
|
|
95
|
+
fontSize: 13,
|
|
96
|
+
formatOnPaste: true,
|
|
97
|
+
formatOnType: true,
|
|
98
|
+
minimap: { enabled: true }
|
|
99
|
+
},
|
|
100
|
+
value: internalValue,
|
|
101
|
+
onChange: (value2) => setInternalValue(value2 || ""),
|
|
102
|
+
theme: "vs-dark",
|
|
103
|
+
beforeMount: (monaco) => {
|
|
104
|
+
if (monaco) {
|
|
105
|
+
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
|
|
106
|
+
validate: true,
|
|
107
|
+
schemas: [
|
|
108
|
+
{
|
|
109
|
+
// uri: MY_JSON_SCHEMA.id,
|
|
110
|
+
fileMatch: ["*"],
|
|
111
|
+
// Apply this schema to the current editor instance
|
|
112
|
+
schema: JSON.parse(attribute["options"]["jsonSchema"])
|
|
113
|
+
}
|
|
114
|
+
]
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
onMount: (editor) => {
|
|
119
|
+
editorRef.current = editor;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
),
|
|
123
|
+
/* @__PURE__ */ jsx(Styled.ValidationButton, { onClick: handleValidateClick, size: "S", children: "Validate" })
|
|
124
|
+
] }),
|
|
125
|
+
/* @__PURE__ */ jsx(Field.Hint, {}),
|
|
126
|
+
/* @__PURE__ */ jsx(Field.Error, {})
|
|
127
|
+
] })
|
|
128
|
+
}
|
|
129
|
+
);
|
|
130
|
+
});
|
|
131
|
+
export {
|
|
132
|
+
JSONSchemaValidationInput,
|
|
133
|
+
JSONSchemaValidationInput as default
|
|
134
|
+
};
|
|
135
|
+
//# sourceMappingURL=index-C9Ge6gj7.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-C9Ge6gj7.mjs","sources":["../../admin/src/components/JSONSchemaValidationInput/styled.tsx","../../admin/src/components/JSONSchemaValidationInput/index.tsx"],"sourcesContent":["import { Button, Flex } from '@strapi/design-system';\nimport styled from 'styled-components';\n\nexport const Styled = {\n FieldContainer: styled(Flex)`\n position: relative;\n `,\n\n ValidationButton: styled(Button)``,\n};\n\nexport default Styled;\n","import Editor, { EditorProps } from '@monaco-editor/react';\nimport { Field, Flex, Typography } from '@strapi/design-system';\nimport { useField } from '@strapi/strapi/admin';\nimport React, { forwardRef, useMemo, useRef, useState } from 'react';\nimport { useIntl } from 'react-intl';\nimport { useFetchClient } from '@strapi/strapi/admin';\n\nimport { Styled } from './styled';\nimport { PLUGIN_ID } from '../../../../shared/constants/plugin';\n\nexport const JSONSchemaValidationInput = forwardRef<HTMLElement, any>((props, ref) => {\n const {\n attribute,\n description,\n disabled,\n error,\n hint,\n intlLabel,\n label,\n name,\n onChange,\n required,\n value,\n } = props; // these are just some of the props passed by the content-manager\n\n const editorRef = useRef<Parameters<NonNullable<EditorProps['onMount']>>[0]>(null);\n\n function triggerEditorFormat() {\n if (editorRef.current != null) {\n // Manually trigger the format document action\n editorRef.current.trigger('manual', 'editor.action.formatDocument');\n }\n }\n\n const { formatMessage } = useIntl();\n const { get, post } = useFetchClient();\n\n const [internalValue, setInternalValue] = useState<string>(value);\n const [internalError, setInternalError] = useState<string>(error);\n\n const validateJSONSchema = async (jsonSchema: string | object, data: string | object) => {\n let parsedSchema: object;\n let parsedData: object;\n try {\n parsedSchema = typeof jsonSchema === 'string' ? JSON.parse(jsonSchema) : jsonSchema;\n parsedData = typeof data === 'string' ? JSON.parse(data) : data;\n } catch (err) {\n console.error('Error parsing JSON Schema or data:', err);\n return { error: 'Error parsing JSON Schema or data', isValid: false };\n }\n\n try {\n const response = await post(`/${PLUGIN_ID}/validateSchema`, {\n schema: parsedSchema,\n data: parsedData,\n });\n return response.data;\n } catch (err) {\n console.error('Error while validating JSON Schema:', err);\n return { error: 'Error while validating JSON Schema', isValid: false };\n }\n };\n // const { onChange, value, error } = useField(name);\n\n const handleValidateClick = async () => {\n triggerEditorFormat();\n console.log('attribute', attribute);\n\n if (!internalValue) {\n setInternalError('JSON Schema is required');\n return;\n }\n\n const result = await validateJSONSchema(attribute['options']['jsonSchema'], internalValue);\n\n console.log('result', result);\n\n if (result.data.isValid) {\n setInternalError('');\n onChange({ target: { name, value: internalValue } });\n } else {\n setInternalError(\n result.data.errors\n ? `Validation errors: ${result.data.errors.map((e) => e.message).join('\\n')}`\n : result.data.processingError\n ? `Processing error: ${result.data.processingError}`\n : 'Invalid JSON Schema or data'\n );\n }\n };\n\n return (\n <Field.Root\n error={internalError}\n hint={description?.id ? formatMessage(description) : hint}\n name={name}\n required={required}\n >\n <Flex alignItems=\"stretch\" direction=\"column\" gap={1}>\n <Field.Label>{intlLabel?.id ? formatMessage(intlLabel) : label}</Field.Label>\n <Flex alignItems={'flex-start'} direction={'row'} gap={2} ref={ref}>\n <Editor\n defaultLanguage=\"json\"\n height=\"50rem\"\n loading={<Typography>Loading JSON Editor...</Typography>}\n options={{\n fontSize: 13,\n formatOnPaste: true,\n formatOnType: true,\n minimap: { enabled: true },\n }}\n value={internalValue}\n onChange={(value) => setInternalValue(value || '')}\n theme=\"vs-dark\"\n beforeMount={(monaco) => {\n if (monaco) {\n monaco.languages.json.jsonDefaults.setDiagnosticsOptions({\n validate: true,\n schemas: [\n {\n // uri: MY_JSON_SCHEMA.id,\n fileMatch: ['*'], // Apply this schema to the current editor instance\n schema: JSON.parse(attribute['options']['jsonSchema']),\n },\n ],\n });\n }\n }}\n onMount={(editor) => {\n editorRef.current = editor;\n }}\n />\n <Styled.ValidationButton onClick={handleValidateClick} size=\"S\">\n Validate\n </Styled.ValidationButton>\n </Flex>\n <Field.Hint />\n <Field.Error />\n </Flex>\n </Field.Root>\n );\n});\n\nexport default JSONSchemaValidationInput;\n"],"names":["value"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const Styled: {
|
|
2
|
+
FieldContainer: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<Omit<Omit<import('@strapi/design-system').FlexProps<import('react').ElementType<any, keyof import("react").JSX.IntrinsicElements>>, "ref"> & import('react').RefAttributes<unknown>, "ref"> & {
|
|
3
|
+
ref?: ((instance: unknown) => void | import('react').DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof import('react').DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | import('react').RefObject<unknown> | null | undefined;
|
|
4
|
+
}, never> & Partial<Pick<Omit<Omit<import('@strapi/design-system').FlexProps<import('react').ElementType<any, keyof import("react").JSX.IntrinsicElements>>, "ref"> & import('react').RefAttributes<unknown>, "ref"> & {
|
|
5
|
+
ref?: ((instance: unknown) => void | import('react').DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof import('react').DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | import('react').RefObject<unknown> | null | undefined;
|
|
6
|
+
}, never>>> & string & Omit<(<C extends React.ElementType<any, keyof React.JSX.IntrinsicElements> = "div">(props: React.PropsWithoutRef<import('@strapi/design-system').FlexProps<C>> & React.RefAttributes<unknown>) => React.ReactNode), keyof import('react').Component<any, {}, any>>;
|
|
7
|
+
ValidationButton: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<Omit<Omit<import('@strapi/design-system').ButtonProps<import('react').ElementType<any, keyof import("react").JSX.IntrinsicElements>>, "ref"> & import('react').RefAttributes<unknown>, "ref"> & {
|
|
8
|
+
ref?: ((instance: unknown) => void | import('react').DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof import('react').DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | import('react').RefObject<unknown> | null | undefined;
|
|
9
|
+
}, never> & Partial<Pick<Omit<Omit<import('@strapi/design-system').ButtonProps<import('react').ElementType<any, keyof import("react").JSX.IntrinsicElements>>, "ref"> & import('react').RefAttributes<unknown>, "ref"> & {
|
|
10
|
+
ref?: ((instance: unknown) => void | import('react').DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof import('react').DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | import('react').RefObject<unknown> | null | undefined;
|
|
11
|
+
}, never>>> & string & Omit<(<C extends React.ElementType<any, keyof React.JSX.IntrinsicElements> = "button">(props: React.PropsWithoutRef<import('@strapi/design-system').ButtonProps<C>> & React.RefAttributes<unknown>) => React.ReactNode), keyof import('react').Component<any, {}, any>>;
|
|
12
|
+
};
|
|
13
|
+
export default Styled;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { StrapiApp } from '@strapi/strapi/admin';
|
|
2
|
+
declare const _default: {
|
|
3
|
+
register(app: StrapiApp): void;
|
|
4
|
+
registerTrads({ locales }: {
|
|
5
|
+
locales: string[];
|
|
6
|
+
}): Promise<{
|
|
7
|
+
data: {
|
|
8
|
+
[x: string]: string;
|
|
9
|
+
};
|
|
10
|
+
locale: string;
|
|
11
|
+
}[]>;
|
|
12
|
+
};
|
|
13
|
+
export default _default;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
"name": "JSON Schema Validation",
|
|
3
|
+
"description": "Provide JSON Schema validation custom field and utilities",
|
|
4
|
+
"field.label": "JSON Schema Validation",
|
|
5
|
+
"field.description": "Enter a JSON Schema to validate the content of this field.",
|
|
6
|
+
"options.base.jsonSchema.label": "JSON Schema",
|
|
7
|
+
"options.base.jsonSchema.description": "The JSON Schema to validate the content of this field against. Follow JSON schema DRAFT 2020-12 specification."
|
|
8
|
+
}
|
|
9
|
+
;
|
|
10
|
+
|
|
11
|
+
export default _default;
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
|
+
const addFormats = require("ajv-formats");
|
|
4
|
+
const Ajv2020 = require("ajv/dist/2020");
|
|
5
|
+
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
6
|
+
const addFormats__default = /* @__PURE__ */ _interopDefault(addFormats);
|
|
7
|
+
const Ajv2020__default = /* @__PURE__ */ _interopDefault(Ajv2020);
|
|
8
|
+
const bootstrap = ({ strapi: _strapi }) => {
|
|
9
|
+
};
|
|
10
|
+
const config = {
|
|
11
|
+
default: {},
|
|
12
|
+
validator() {
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
const contentTypes = {};
|
|
16
|
+
const PLUGIN_ID = "strapi-plugin-json-schema-validation";
|
|
17
|
+
const PLUGIN_CUSTOM_JSON_FIELD_NAME = "json-schema-validation";
|
|
18
|
+
const getHandlerName = (handler) => {
|
|
19
|
+
return handler;
|
|
20
|
+
};
|
|
21
|
+
const getServiceName = (service2) => {
|
|
22
|
+
return service2;
|
|
23
|
+
};
|
|
24
|
+
const controller = ({ strapi }) => ({
|
|
25
|
+
index(ctx) {
|
|
26
|
+
ctx.body = strapi.plugin(PLUGIN_ID).service(getServiceName("service")).getWelcomeMessage();
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
const validation$1 = ({ strapi }) => ({
|
|
30
|
+
async validateSchemaStructure(ctx) {
|
|
31
|
+
const { schema } = ctx.request.body;
|
|
32
|
+
const validationService = strapi.plugin(PLUGIN_ID).service(getServiceName("validation"));
|
|
33
|
+
const result = validationService.validateSchemaStructure(schema);
|
|
34
|
+
ctx.body = { data: result };
|
|
35
|
+
},
|
|
36
|
+
async validateSchema(ctx) {
|
|
37
|
+
const { schema, data } = ctx.request.body;
|
|
38
|
+
const validationService = strapi.plugin(PLUGIN_ID).service(getServiceName("validation"));
|
|
39
|
+
const result = validationService.validateSchema(schema, data);
|
|
40
|
+
ctx.body = { data: result };
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
const controllers = {
|
|
44
|
+
[
|
|
45
|
+
"controller"
|
|
46
|
+
/* Controller */
|
|
47
|
+
]: controller,
|
|
48
|
+
[
|
|
49
|
+
"validation"
|
|
50
|
+
/* Validation */
|
|
51
|
+
]: validation$1
|
|
52
|
+
};
|
|
53
|
+
const destroy = ({ strapi: _strapi }) => {
|
|
54
|
+
};
|
|
55
|
+
const middlewares = {};
|
|
56
|
+
const policies = {};
|
|
57
|
+
const register = ({ strapi }) => {
|
|
58
|
+
strapi.customFields.register({
|
|
59
|
+
inputSize: {
|
|
60
|
+
default: 12,
|
|
61
|
+
isResizable: true
|
|
62
|
+
},
|
|
63
|
+
name: PLUGIN_CUSTOM_JSON_FIELD_NAME,
|
|
64
|
+
plugin: PLUGIN_ID,
|
|
65
|
+
type: "json"
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
const adminAPIRoutes = () => ({
|
|
69
|
+
routes: [
|
|
70
|
+
{
|
|
71
|
+
method: "POST",
|
|
72
|
+
path: "/validateSchemaStructure",
|
|
73
|
+
handler: getHandlerName("validation.validateSchemaStructure")
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
method: "POST",
|
|
77
|
+
path: "/validateSchema",
|
|
78
|
+
handler: getHandlerName("validation.validateSchema")
|
|
79
|
+
}
|
|
80
|
+
],
|
|
81
|
+
type: "admin"
|
|
82
|
+
});
|
|
83
|
+
const contentAPIRoutes = () => ({
|
|
84
|
+
routes: [
|
|
85
|
+
{
|
|
86
|
+
config: {
|
|
87
|
+
policies: []
|
|
88
|
+
},
|
|
89
|
+
// name of the controller file & the method.
|
|
90
|
+
handler: getHandlerName("controller.index"),
|
|
91
|
+
method: "GET",
|
|
92
|
+
path: "/"
|
|
93
|
+
}
|
|
94
|
+
],
|
|
95
|
+
type: "content-api"
|
|
96
|
+
});
|
|
97
|
+
const routes = {
|
|
98
|
+
admin: adminAPIRoutes,
|
|
99
|
+
"content-api": contentAPIRoutes
|
|
100
|
+
};
|
|
101
|
+
const service = ({ strapi: _strapi }) => ({
|
|
102
|
+
getWelcomeMessage() {
|
|
103
|
+
return "Welcome to Strapi 🚀";
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
const ajv = new Ajv2020__default.default();
|
|
107
|
+
addFormats__default.default(ajv);
|
|
108
|
+
const validation = ({ strapi: _strapi }) => ({
|
|
109
|
+
/**
|
|
110
|
+
* This service method validates the structure of a JSON Schema using AJV against DRAFT-2020-12 specs
|
|
111
|
+
* @param jsonSchema - The JSON Schema string to validate
|
|
112
|
+
* @returns
|
|
113
|
+
*/
|
|
114
|
+
validateSchemaStructure(jsonSchema) {
|
|
115
|
+
try {
|
|
116
|
+
const parsedSchema = JSON.parse(jsonSchema);
|
|
117
|
+
const isValid = ajv.validateSchema(parsedSchema);
|
|
118
|
+
return {
|
|
119
|
+
errors: ajv.errors,
|
|
120
|
+
isValid
|
|
121
|
+
};
|
|
122
|
+
} catch (err) {
|
|
123
|
+
console.error("Error while validating JSON Schema structure:", err);
|
|
124
|
+
return { processingError: "Error while validating JSON Schema structure", isValid: false };
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
validateSchema(schema, data) {
|
|
128
|
+
try {
|
|
129
|
+
const validate = ajv.compile(schema);
|
|
130
|
+
const valid = validate(data);
|
|
131
|
+
return {
|
|
132
|
+
errors: validate.errors,
|
|
133
|
+
isValid: valid
|
|
134
|
+
};
|
|
135
|
+
} catch (err) {
|
|
136
|
+
console.error("Error while validating JSON Schema:", err);
|
|
137
|
+
return { processingError: `Error while validating JSON Schema: ${err}`, isValid: false };
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
const services = {
|
|
142
|
+
[
|
|
143
|
+
"service"
|
|
144
|
+
/* Service */
|
|
145
|
+
]: service,
|
|
146
|
+
[
|
|
147
|
+
"validation"
|
|
148
|
+
/* Validation */
|
|
149
|
+
]: validation
|
|
150
|
+
};
|
|
151
|
+
const index = {
|
|
152
|
+
bootstrap,
|
|
153
|
+
config,
|
|
154
|
+
contentTypes,
|
|
155
|
+
controllers,
|
|
156
|
+
destroy,
|
|
157
|
+
middlewares,
|
|
158
|
+
policies,
|
|
159
|
+
register,
|
|
160
|
+
routes,
|
|
161
|
+
services
|
|
162
|
+
};
|
|
163
|
+
exports.default = index;
|
|
164
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../server/src/bootstrap.ts","../../server/src/config/index.ts","../../server/src/content-types/index.ts","../../shared/constants/plugin.ts","../../server/src/utils/names.ts","../../server/src/controllers/controller.ts","../../server/src/controllers/validation.ts","../../server/src/controllers/index.ts","../../server/src/destroy.ts","../../server/src/middlewares/index.ts","../../server/src/policies/index.ts","../../server/src/register.ts","../../server/src/routes/admin/index.ts","../../server/src/routes/content-api/index.ts","../../server/src/routes/index.ts","../../server/src/services/service.ts","../../server/src/utils/ajv.ts","../../server/src/services/validation.ts","../../server/src/services/index.ts","../../server/src/index.ts"],"sourcesContent":["import type { Core } from '@strapi/strapi';\n\nconst bootstrap = ({ strapi: _strapi }: { strapi: Core.Strapi }) => {\n // bootstrap phase\n};\n\nexport default bootstrap;\n","export default {\n default: {},\n validator() {},\n};\n","export default {};\n","export const PLUGIN_ID = 'strapi-plugin-json-schema-validation';\nexport const PLUGIN_NAME = 'JSON Schema Validation';\nexport const PLUGIN_CUSTOM_JSON_FIELD_NAME = 'json-schema-validation';\n\nexport const JSON_SCHEMA_FIELD_OPTIONS_KEY = {\n base: {\n jsonSchema: 'jsonSchema',\n },\n};\n","import { HandlerName } from '../controllers';\nimport { ServiceName } from '../services';\n\nexport const getHandlerName = (handler: HandlerName) => {\n return handler;\n};\n\nexport const getServiceName = (service: `${ServiceName}`) => {\n return service;\n};\n","import type { Core } from '@strapi/strapi';\n\nimport { PLUGIN_ID } from '../../../shared/constants/plugin';\nimport { Service } from '../services/service';\nimport { getServiceName } from '../utils/names';\n\nconst controller = ({ strapi }: { strapi: Core.Strapi }) => ({\n index(ctx) {\n ctx.body = strapi\n .plugin(PLUGIN_ID)\n // the name of the service file & the method.\n .service<Service>(getServiceName('service'))\n .getWelcomeMessage();\n },\n});\n\nexport type Controller = ReturnType<typeof controller>;\nexport type ControllerMethod = keyof Controller;\n\nexport default controller;\n","import type { Core } from '@strapi/strapi';\n\nimport { PLUGIN_ID } from '../../../shared/constants/plugin';\nimport { ValidationService } from '../services/validation';\nimport { getServiceName } from '../utils/names';\n\nconst validation = ({ strapi }: { strapi: Core.Strapi }) => ({\n async validateSchemaStructure(ctx) {\n const { schema } = ctx.request.body;\n const validationService = strapi\n .plugin(PLUGIN_ID)\n .service<ValidationService>(getServiceName('validation'));\n const result = validationService.validateSchemaStructure(schema);\n ctx.body = { data: result };\n },\n\n async validateSchema(ctx) {\n const { schema, data } = ctx.request.body;\n const validationService = strapi\n .plugin(PLUGIN_ID)\n .service<ValidationService>(getServiceName('validation'));\n const result = validationService.validateSchema(schema, data);\n ctx.body = { data: result };\n },\n});\n\nexport type ValidationController = ReturnType<typeof validation>;\nexport type ValidationControllerMethod = keyof ValidationController;\n\nexport default validation;\n","import controller, { Controller, ControllerMethod } from './controller';\nimport validation, { ValidationController, ValidationControllerMethod } from './validation';\n\nexport enum ControllerName {\n Controller = 'controller',\n Validation = 'validation',\n}\n\nexport type Controllers = {\n [ControllerName.Controller]: Controller;\n [ControllerName.Validation]: ValidationController;\n};\n\nexport type HandlerName =\n | `${ControllerName.Controller}.${ControllerMethod}`\n | `${ControllerName.Validation}.${ValidationControllerMethod}`;\n\nexport default {\n [ControllerName.Controller]: controller,\n [ControllerName.Validation]: validation,\n};\n","import type { Core } from '@strapi/strapi';\n\nconst destroy = ({ strapi: _strapi }: { strapi: Core.Strapi }) => {\n // destroy phase\n};\n\nexport default destroy;\n","export default {};\n","export default {};\n","import type { Core } from '@strapi/strapi';\n\nimport { PLUGIN_CUSTOM_JSON_FIELD_NAME, PLUGIN_ID } from '../../shared/constants/plugin';\n\nconst register = ({ strapi }: { strapi: Core.Strapi }) => {\n // register phase\n strapi.customFields.register({\n inputSize: {\n default: 12,\n isResizable: true,\n },\n name: PLUGIN_CUSTOM_JSON_FIELD_NAME,\n plugin: PLUGIN_ID,\n type: 'json',\n });\n};\n\nexport default register;\n","import { Core } from '@strapi/strapi';\nimport { getHandlerName } from '../../utils/names';\n\nexport default () => ({\n routes: [\n {\n method: 'POST',\n path: '/validateSchemaStructure',\n handler: getHandlerName('validation.validateSchemaStructure'),\n },\n {\n method: 'POST',\n path: '/validateSchema',\n handler: getHandlerName('validation.validateSchema'),\n },\n ] satisfies Partial<Core.Route>[],\n type: 'admin',\n});\n","import { getHandlerName } from '../../utils/names';\n\nexport default () => ({\n routes: [\n {\n config: {\n policies: [],\n },\n // name of the controller file & the method.\n handler: getHandlerName('controller.index'),\n method: 'GET',\n path: '/',\n },\n ],\n type: 'content-api',\n});\n","import adminAPIRoutes from './admin';\nimport contentAPIRoutes from './content-api';\n\nconst routes = {\n admin: adminAPIRoutes,\n 'content-api': contentAPIRoutes,\n};\n\nexport default routes;\n","import type { Core } from '@strapi/strapi';\n\nimport ajv from '../utils/ajv';\n\nconst service = ({ strapi: _strapi }: { strapi: Core.Strapi }) => ({\n getWelcomeMessage() {\n return 'Welcome to Strapi 🚀';\n },\n});\n\nexport type Service = ReturnType<typeof service>;\nexport type ServiceMethod = keyof Service;\n\nexport default service;\n","import addFormats from 'ajv-formats';\nimport Ajv2020 from 'ajv/dist/2020';\n\nconst ajv = new Ajv2020();\naddFormats(ajv);\n\nexport default ajv;\n","import type { Core } from '@strapi/strapi';\n\nimport ajv from '../utils/ajv';\n\nconst validation = ({ strapi: _strapi }: { strapi: Core.Strapi }) => ({\n /**\n * This service method validates the structure of a JSON Schema using AJV against DRAFT-2020-12 specs\n * @param jsonSchema - The JSON Schema string to validate\n * @returns\n */\n validateSchemaStructure(jsonSchema: string) {\n try {\n const parsedSchema = JSON.parse(jsonSchema);\n const isValid = ajv.validateSchema(parsedSchema);\n return {\n errors: ajv.errors,\n isValid,\n };\n } catch (err) {\n console.error('Error while validating JSON Schema structure:', err);\n return { processingError: 'Error while validating JSON Schema structure', isValid: false };\n }\n },\n\n validateSchema(schema: object, data: object) {\n try {\n const validate = ajv.compile(schema);\n\n const valid = validate(data);\n return {\n errors: validate.errors,\n isValid: valid,\n };\n } catch (err) {\n console.error('Error while validating JSON Schema:', err);\n return { processingError: `Error while validating JSON Schema: ${err}`, isValid: false };\n }\n },\n});\n\nexport type ValidationService = ReturnType<typeof validation>;\nexport type ValidationServiceMethod = keyof ValidationService;\n\nexport default validation;\n","import service, { Service } from './service';\nimport validation, { ValidationService } from './validation';\n\nexport enum ServiceName {\n Service = 'service',\n Validation = 'validation',\n}\n\nexport type Services = {\n [ServiceName.Service]: Service;\n [ServiceName.Validation]: ValidationService;\n};\n\nexport default {\n [ServiceName.Service]: service,\n [ServiceName.Validation]: validation,\n};\n","/**\n * Application methods\n */\nimport bootstrap from './bootstrap';\n/**\n * Plugin server methods\n */\nimport config from './config';\nimport contentTypes from './content-types';\nimport controllers from './controllers';\nimport destroy from './destroy';\nimport middlewares from './middlewares';\nimport policies from './policies';\nimport register from './register';\nimport routes from './routes';\nimport services from './services';\n\nexport default {\n bootstrap,\n config,\n contentTypes,\n controllers,\n destroy,\n middlewares,\n policies,\n register,\n routes,\n services,\n};\n"],"names":["service","validation","Ajv2020","addFormats"],"mappings":"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"}
|