@quazardous/qdadm 1.21.0 → 1.22.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quazardous/qdadm",
3
- "version": "1.21.0",
3
+ "version": "1.22.0",
4
4
  "description": "Vue 3 framework for admin dashboards with PrimeVue",
5
5
  "author": "quazardous",
6
6
  "license": "MIT",
@@ -6,10 +6,17 @@
6
6
  *
7
7
  * Usage:
8
8
  * <VanillaJsonEditor v-model="jsonData" mode="tree" />
9
+ *
10
+ * Inline JSON Schema validation (errors highlighted live in the editor):
11
+ * <VanillaJsonEditor v-model="jsonData" :schema="mySchema" />
12
+ *
13
+ * Or a raw validator for advanced cases (takes precedence over `schema`):
14
+ * <VanillaJsonEditor v-model="jsonData" :validator="myValidator" />
9
15
  */
10
16
 
11
17
  import { ref, watch, onMounted, onUnmounted, nextTick } from 'vue'
12
18
  import { JSONEditor, type Content, type ContentErrors, type OnChangeStatus, type Mode } from 'vanilla-jsoneditor'
19
+ import { buildJsonValidator, type Validator, type JSONSchema, type JsonValidatorOptions } from './jsonValidator'
13
20
 
14
21
  type JsonValue = Record<string, unknown> | unknown[] | string | null
15
22
 
@@ -21,6 +28,14 @@ interface Props {
21
28
  mainMenuBar?: boolean
22
29
  navigationBar?: boolean
23
30
  statusBar?: boolean
31
+ /** JSON Schema for inline Ajv validation (errors highlighted in the editor). */
32
+ schema?: JSONSchema
33
+ /** Raw validator function — takes precedence over `schema`. */
34
+ validator?: Validator
35
+ /** Optional `$ref` definitions passed through to the Ajv validator. */
36
+ schemaDefinitions?: JsonValidatorOptions['schemaDefinitions']
37
+ /** Optional Ajv options passed through to the Ajv validator. */
38
+ ajvOptions?: JsonValidatorOptions['ajvOptions']
24
39
  }
25
40
 
26
41
  const props = withDefaults(defineProps<Props>(), {
@@ -30,9 +45,23 @@ const props = withDefaults(defineProps<Props>(), {
30
45
  readOnly: false,
31
46
  mainMenuBar: true,
32
47
  navigationBar: true,
33
- statusBar: true
48
+ statusBar: true,
49
+ schema: undefined,
50
+ validator: undefined,
51
+ schemaDefinitions: undefined,
52
+ ajvOptions: undefined
34
53
  })
35
54
 
55
+ // Resolve the effective validator from props (raw validator > schema > none).
56
+ function resolveValidator(): Validator | undefined {
57
+ return buildJsonValidator({
58
+ validator: props.validator,
59
+ schema: props.schema,
60
+ schemaDefinitions: props.schemaDefinitions,
61
+ ajvOptions: props.ajvOptions
62
+ })
63
+ }
64
+
36
65
  const emit = defineEmits<{
37
66
  'update:modelValue': [value: JsonValue]
38
67
  'change': [value: JsonValue]
@@ -76,6 +105,7 @@ onMounted(() => {
76
105
  mainMenuBar: props.mainMenuBar,
77
106
  navigationBar: props.navigationBar,
78
107
  statusBar: props.statusBar,
108
+ validator: resolveValidator(),
79
109
  onChange: (updatedContent: Content, _previousContent: Content, { contentErrors }: OnChangeStatus) => {
80
110
  // Skip if this change came from a programmatic prop update
81
111
  if (updatingFromProp.value) return
@@ -144,6 +174,17 @@ watch(() => props.readOnly, (newReadOnly: boolean) => {
144
174
  }
145
175
  })
146
176
 
177
+ // Watch validator/schema changes — rebuild and re-apply so edits re-validate live
178
+ watch(
179
+ () => [props.validator, props.schema, props.schemaDefinitions, props.ajvOptions],
180
+ () => {
181
+ if (editor) {
182
+ editor.updateProps({ validator: resolveValidator() })
183
+ }
184
+ },
185
+ { deep: true }
186
+ )
187
+
147
188
  // Cleanup
148
189
  onUnmounted(() => {
149
190
  if (editor) {
@@ -0,0 +1,44 @@
1
+ /**
2
+ * jsonValidator - build a vanilla-jsoneditor `Validator` from wrapper props.
3
+ *
4
+ * Pure helper extracted from VanillaJsonEditor so the resolution logic
5
+ * (raw validator vs JSON Schema vs none) is unit-testable without mounting the
6
+ * Svelte editor. See qdadm #1050.
7
+ */
8
+ import {
9
+ createAjvValidator,
10
+ type Validator,
11
+ type JSONSchema,
12
+ type AjvValidatorOptions,
13
+ } from 'vanilla-jsoneditor'
14
+
15
+ export type { Validator, JSONSchema }
16
+
17
+ export interface JsonValidatorOptions {
18
+ /** Raw validator function — takes precedence over `schema` when both are set. */
19
+ validator?: Validator
20
+ /** JSON Schema; compiled to a validator via Ajv (bundled in vanilla-jsoneditor). */
21
+ schema?: JSONSchema
22
+ /** Optional `$ref` definitions passed through to `createAjvValidator`. */
23
+ schemaDefinitions?: AjvValidatorOptions['schemaDefinitions']
24
+ /** Optional Ajv options passed through to `createAjvValidator`. */
25
+ ajvOptions?: AjvValidatorOptions['ajvOptions']
26
+ }
27
+
28
+ /**
29
+ * Resolve the effective validator:
30
+ * - an explicit `validator` wins;
31
+ * - otherwise a `schema` is compiled with `createAjvValidator`;
32
+ * - otherwise `undefined` (no validation — the wrapper's default behavior).
33
+ */
34
+ export function buildJsonValidator(options: JsonValidatorOptions): Validator | undefined {
35
+ if (options.validator) return options.validator
36
+ if (options.schema) {
37
+ return createAjvValidator({
38
+ schema: options.schema,
39
+ schemaDefinitions: options.schemaDefinitions,
40
+ ajvOptions: options.ajvOptions,
41
+ })
42
+ }
43
+ return undefined
44
+ }
@@ -1,46 +0,0 @@
1
- /**
2
- * TestManager - Auto-generated EntityManager
3
- *
4
- * Generated by qdadm/gen/generateManagers
5
- * DO NOT EDIT MANUALLY - Changes will be overwritten
6
- *
7
- * Entity: test
8
- * Endpoint: /test
9
- */
10
-
11
- import { EntityManager } from '@quazardous/qdadm'
12
- import type { EntityRecord } from '@quazardous/qdadm'
13
- import { ApiStorage } from '@quazardous/qdadm'
14
-
15
- export interface TestEntity extends EntityRecord {
16
- }
17
-
18
- /**
19
- * Schema definition for test
20
- */
21
- export const testSchema = {
22
- name: "test",
23
- endpoint: "/test",
24
- fields: {}
25
- } as const
26
-
27
- /**
28
- * Storage options for test
29
- */
30
- const storageOptions = {
31
- endpoint: "/test"
32
- }
33
-
34
- /**
35
- * TestManager instance
36
- *
37
- * Provides CRUD operations for test entity.
38
- */
39
- export const testManager = new EntityManager<TestEntity>({
40
- ...{
41
- name: "test",
42
- idField: "id",
43
- fields: {}
44
- },
45
- storage: new ApiStorage<TestEntity>(storageOptions)
46
- })