@narrative.io/jsonforms-provider-protocols 1.0.3

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 (69) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +200 -0
  3. package/dist/_virtual/_plugin-vue_export-helper.js +11 -0
  4. package/dist/_virtual/_plugin-vue_export-helper.js.map +1 -0
  5. package/dist/core/cache.d.ts +8 -0
  6. package/dist/core/cache.d.ts.map +1 -0
  7. package/dist/core/cache.js +27 -0
  8. package/dist/core/cache.js.map +1 -0
  9. package/dist/core/jsonpath.d.ts +2 -0
  10. package/dist/core/jsonpath.d.ts.map +1 -0
  11. package/dist/core/jsonpath.js +40 -0
  12. package/dist/core/jsonpath.js.map +1 -0
  13. package/dist/core/registry.d.ts +8 -0
  14. package/dist/core/registry.d.ts.map +1 -0
  15. package/dist/core/registry.js +17 -0
  16. package/dist/core/registry.js.map +1 -0
  17. package/dist/core/templating.d.ts +3 -0
  18. package/dist/core/templating.d.ts.map +1 -0
  19. package/dist/core/templating.js +32 -0
  20. package/dist/core/templating.js.map +1 -0
  21. package/dist/core/types.d.ts +44 -0
  22. package/dist/core/types.d.ts.map +1 -0
  23. package/dist/index.d.ts +18 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +30 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/jsonforms-provider-protocols.css +4 -0
  28. package/dist/protocols/rest_api.d.ts +22 -0
  29. package/dist/protocols/rest_api.d.ts.map +1 -0
  30. package/dist/protocols/rest_api.js +92 -0
  31. package/dist/protocols/rest_api.js.map +1 -0
  32. package/dist/vue/components/ProviderAutocomplete.vue.d.ts +9 -0
  33. package/dist/vue/components/ProviderAutocomplete.vue.d.ts.map +1 -0
  34. package/dist/vue/components/ProviderAutocomplete.vue.js +68 -0
  35. package/dist/vue/components/ProviderAutocomplete.vue.js.map +1 -0
  36. package/dist/vue/components/ProviderAutocomplete.vue2.js +5 -0
  37. package/dist/vue/components/ProviderAutocomplete.vue2.js.map +1 -0
  38. package/dist/vue/components/ProviderSelect.vue.d.ts +9 -0
  39. package/dist/vue/components/ProviderSelect.vue.d.ts.map +1 -0
  40. package/dist/vue/components/ProviderSelect.vue.js +8 -0
  41. package/dist/vue/components/ProviderSelect.vue.js.map +1 -0
  42. package/dist/vue/components/ProviderSelect.vue2.js +74 -0
  43. package/dist/vue/components/ProviderSelect.vue2.js.map +1 -0
  44. package/dist/vue/composables/useProvider.d.ts +14 -0
  45. package/dist/vue/composables/useProvider.d.ts.map +1 -0
  46. package/dist/vue/composables/useProvider.js +76 -0
  47. package/dist/vue/composables/useProvider.js.map +1 -0
  48. package/dist/vue/index.d.ts +19 -0
  49. package/dist/vue/index.d.ts.map +1 -0
  50. package/dist/vue/index.js +36 -0
  51. package/dist/vue/index.js.map +1 -0
  52. package/dist/vue/testers.d.ts +2 -0
  53. package/dist/vue/testers.d.ts.map +1 -0
  54. package/dist/vue/testers.js +12 -0
  55. package/dist/vue/testers.js.map +1 -0
  56. package/package.json +100 -0
  57. package/src/core/cache.ts +23 -0
  58. package/src/core/jsonpath.ts +41 -0
  59. package/src/core/registry.ts +15 -0
  60. package/src/core/templating.ts +27 -0
  61. package/src/core/types.ts +46 -0
  62. package/src/index.ts +36 -0
  63. package/src/protocols/rest_api.ts +136 -0
  64. package/src/vue/components/ProviderAutocomplete.vue +54 -0
  65. package/src/vue/components/ProviderSelect.vue +70 -0
  66. package/src/vue/composables/useProvider.ts +111 -0
  67. package/src/vue/index.ts +44 -0
  68. package/src/vue/testers.ts +19 -0
  69. package/src/vue-shim.d.ts +9 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rest_api.js","sources":["../../src/protocols/rest_api.ts"],"sourcesContent":["import { jp } from \"../core/jsonpath\";\nimport { renderObj, renderTpl } from \"../core/templating\";\nimport type {\n Protocol,\n ProviderItem,\n ProviderOutput,\n AuthConfig,\n} from \"../core/types\";\n\nexport type RestApiCfg = {\n url: string;\n method?: \"GET\" | \"POST\";\n headers?: Record<string, string>;\n query?: Record<string, unknown>;\n body?: unknown;\n items: string; // JSONPath to array; e.g. \"$.items[*]\"\n map: { label: string; value: string; meta?: Record<string, string> }; // relative to each item\n paginate?: { cursorPath: string; param: string; maxPages?: number };\n auth?: AuthConfig;\n};\n\nfunction buildAuthHeaders(\n auth?: AuthConfig,\n globalAuth?: Record<string, unknown>,\n): Record<string, string> {\n const headers: Record<string, string> = {};\n\n if (!auth) return headers;\n\n // Handle \"use\" reference to global auth\n if (auth.use && globalAuth?.[auth.use]) {\n const globalValue = globalAuth[auth.use];\n const value =\n typeof globalValue === \"function\" ? globalValue() : globalValue;\n\n if (auth.use === \"apiKey\") {\n headers[\"X-API-Key\"] = String(value);\n } else if (auth.use === \"bearer\") {\n headers[\"Authorization\"] = `Bearer ${value}`;\n } else if (auth.use === \"token\") {\n headers[\"Authorization\"] = `Token ${value}`;\n }\n return headers;\n }\n\n // Handle direct auth values\n if (auth.apiKey) {\n const value =\n typeof auth.apiKey === \"function\" ? auth.apiKey() : auth.apiKey;\n headers[\"X-API-Key\"] = String(value);\n }\n\n if (auth.bearer) {\n const value =\n typeof auth.bearer === \"function\" ? auth.bearer() : auth.bearer;\n headers[\"Authorization\"] = `Bearer ${value}`;\n }\n\n if (auth.token) {\n const value = typeof auth.token === \"function\" ? auth.token() : auth.token;\n headers[\"Authorization\"] = `Token ${value}`;\n }\n\n // Handle custom auth fields\n for (const [key, value] of Object.entries(auth)) {\n if (\n ![\"use\", \"apiKey\", \"bearer\", \"token\"].includes(key) &&\n value !== undefined\n ) {\n const authValue = typeof value === \"function\" ? value() : value;\n headers[key] = String(authValue);\n }\n }\n\n return headers;\n}\n\nexport const RestApiProtocol = (): Protocol<RestApiCfg> => ({\n protocol: \"rest_api\",\n async resolve(cfg, ctx): Promise<ProviderOutput> {\n const ac = ctx.signal;\n const out: ProviderItem[] = [];\n let cursor: unknown = null;\n let page = 0;\n do {\n const url = new URL(renderTpl(cfg.url, { data: ctx.data, ui: ctx.ui }));\n const q = renderObj(cfg.query ?? {}, {\n data: ctx.data,\n ui: ctx.ui,\n }) as Record<string, unknown>;\n for (const [k, v] of Object.entries(q))\n if (v !== undefined && v !== \"\") url.searchParams.set(k, String(v));\n if (cursor && cfg.paginate)\n url.searchParams.set(cfg.paginate.param, String(cursor));\n\n // Build headers with auth\n const baseHeaders = renderObj(cfg.headers ?? {}, {\n data: ctx.data,\n }) as Record<string, string>;\n const authHeaders = buildAuthHeaders(cfg.auth, ctx.auth);\n const headers = { ...baseHeaders, ...authHeaders };\n\n const method = cfg.method ?? \"GET\";\n const requestInit: RequestInit = {\n method,\n headers,\n signal: ac,\n };\n\n // Only include body for non-GET requests\n if (method !== \"GET\" && cfg.body) {\n requestInit.body = JSON.stringify(\n renderObj(cfg.body, { data: ctx.data }),\n );\n }\n\n const res = await fetch(url.toString(), requestInit);\n if (!res.ok) throw new Error(`REST ${res.status}`);\n const json = await res.json();\n const items = jp(json, cfg.items);\n for (const it of items) {\n const label = jp(it, cfg.map.label)[0];\n const value = jp(it, cfg.map.value)[0];\n const meta = cfg.map.meta\n ? Object.fromEntries(\n Object.entries(cfg.map.meta).map(([k, p]) => [k, jp(it, p)[0]]),\n )\n : undefined;\n out.push({ label: String(label ?? \"\"), value, meta });\n }\n cursor = cfg.paginate ? jp(json, cfg.paginate.cursorPath)[0] : null;\n page += 1;\n } while (cfg.paginate && cursor && page < (cfg.paginate.maxPages ?? 5));\n return { items: out, ttl: 300 };\n },\n});\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { ControlElement, JsonSchema } from "@jsonforms/core";
2
+ type __VLS_Props = {
3
+ uischema: ControlElement;
4
+ schema: JsonSchema;
5
+ path: string;
6
+ };
7
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
8
+ export default _default;
9
+ //# sourceMappingURL=ProviderAutocomplete.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProviderAutocomplete.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/components/ProviderAutocomplete.vue"],"names":[],"mappings":"AAwDA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAKlE,KAAK,WAAW,GAAG;IACjB,QAAQ,EAAE,cAAc,CAAC;IACzB,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;;AAyGF,wBAEG"}
@@ -0,0 +1,68 @@
1
+ import { defineComponent, computed, ref, watch, createElementBlock, openBlock, createElementVNode, withDirectives, createCommentVNode, toDisplayString, unref, vModelText, Fragment, renderList } from "vue";
2
+ import { useJsonFormsControl } from "@jsonforms/vue";
3
+ import { useProvider } from "../composables/useProvider.js";
4
+ const _hoisted_1 = { class: "provider-autocomplete" };
5
+ const _hoisted_2 = ["placeholder"];
6
+ const _hoisted_3 = { key: 0 };
7
+ const _hoisted_4 = ["onClick"];
8
+ const _hoisted_5 = {
9
+ key: 1,
10
+ role: "alert"
11
+ };
12
+ const _sfc_main = /* @__PURE__ */ defineComponent({
13
+ __name: "ProviderAutocomplete",
14
+ props: {
15
+ uischema: {},
16
+ schema: {},
17
+ path: {}
18
+ },
19
+ setup(__props) {
20
+ const props = __props;
21
+ const { control, handleChange } = useJsonFormsControl(props);
22
+ const binding = computed(() => {
23
+ const provider = control.value.uischema?.options?.provider;
24
+ if (provider && typeof provider === "object" && !provider.load) {
25
+ return { ...provider, load: "query" };
26
+ }
27
+ return provider;
28
+ });
29
+ const query = ref("");
30
+ const { items, loading, error, reload } = useProvider(binding, {
31
+ data: control.value.data,
32
+ path: control.value.path,
33
+ uiQuery: query.value
34
+ });
35
+ watch(query, () => {
36
+ if (binding.value?.load === "query") reload();
37
+ });
38
+ const value = computed({
39
+ get: () => control.value.data,
40
+ set: (v) => handleChange(control.value.path, v)
41
+ });
42
+ return (_ctx, _cache) => {
43
+ return openBlock(), createElementBlock("div", _hoisted_1, [
44
+ createElementVNode("label", null, toDisplayString(unref(control).schema.title), 1),
45
+ withDirectives(createElementVNode("input", {
46
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => query.value = $event),
47
+ placeholder: unref(loading) ? "Loading…" : "Type to search…",
48
+ type: "text"
49
+ }, null, 8, _hoisted_2), [
50
+ [vModelText, query.value]
51
+ ]),
52
+ unref(items).length ? (openBlock(), createElementBlock("ul", _hoisted_3, [
53
+ (openBlock(true), createElementBlock(Fragment, null, renderList(unref(items), (it) => {
54
+ return openBlock(), createElementBlock("li", {
55
+ key: String(it.value),
56
+ onClick: ($event) => value.value = it.value
57
+ }, toDisplayString(it.label), 9, _hoisted_4);
58
+ }), 128))
59
+ ])) : createCommentVNode("", true),
60
+ unref(error) ? (openBlock(), createElementBlock("small", _hoisted_5, "Failed: " + toDisplayString(unref(error)), 1)) : createCommentVNode("", true)
61
+ ]);
62
+ };
63
+ }
64
+ });
65
+ export {
66
+ _sfc_main as default
67
+ };
68
+ //# sourceMappingURL=ProviderAutocomplete.vue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProviderAutocomplete.vue.js","sources":["../../../src/vue/components/ProviderAutocomplete.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ControlElement, JsonSchema } from \"@jsonforms/core\";\nimport { useJsonFormsControl } from \"@jsonforms/vue\";\nimport { computed, ref, watch } from \"vue\";\nimport { useProvider } from \"../composables/useProvider\";\n\nconst props = defineProps<{\n uischema: ControlElement;\n schema: JsonSchema;\n path: string;\n}>();\nconst { control, handleChange } = useJsonFormsControl(props);\n\nconst binding = computed(() => {\n const provider = control.value.uischema?.options?.provider;\n // Ensure load property is set to 'query' by default for autocomplete\n if (provider && typeof provider === \"object\" && !provider.load) {\n return { ...provider, load: \"query\" };\n }\n return provider;\n});\nconst query = ref(\"\");\nconst { items, loading, error, reload } = useProvider(binding, {\n data: control.value.data,\n path: control.value.path,\n uiQuery: query.value,\n});\n\nwatch(query, () => {\n if (binding.value?.load === \"query\") reload();\n});\n\nconst value = computed({\n get: () => control.value.data,\n set: (v) => handleChange(control.value.path, v),\n});\n</script>\n\n<template>\n <div class=\"provider-autocomplete\">\n <label>{{ control.schema.title }}</label>\n <input\n v-model=\"query\"\n :placeholder=\"loading ? 'Loading…' : 'Type to search…'\"\n type=\"text\"\n />\n <ul v-if=\"items.length\">\n <li v-for=\"it in items\" :key=\"String(it.value)\" @click=\"value = it.value\">\n {{ it.label }}\n </li>\n </ul>\n <small v-if=\"error\" role=\"alert\">Failed: {{ error }}</small>\n </div>\n</template>\n"],"names":["_openBlock","_createElementBlock","_createElementVNode","_toDisplayString","_unref","_Fragment","_renderList"],"mappings":";;;;;;;;;;;;;;;;;;;AAMA,UAAM,QAAQ;AAKd,UAAM,EAAE,SAAS,iBAAiB,oBAAoB,KAAK;AAE3D,UAAM,UAAU,SAAS,MAAM;AAC7B,YAAM,WAAW,QAAQ,MAAM,UAAU,SAAS;AAElD,UAAI,YAAY,OAAO,aAAa,YAAY,CAAC,SAAS,MAAM;AAC9D,eAAO,EAAE,GAAG,UAAU,MAAM,QAAA;AAAA,MAC9B;AACA,aAAO;AAAA,IACT,CAAC;AACD,UAAM,QAAQ,IAAI,EAAE;AACpB,UAAM,EAAE,OAAO,SAAS,OAAO,OAAA,IAAW,YAAY,SAAS;AAAA,MAC7D,MAAM,QAAQ,MAAM;AAAA,MACpB,MAAM,QAAQ,MAAM;AAAA,MACpB,SAAS,MAAM;AAAA,IAAA,CAChB;AAED,UAAM,OAAO,MAAM;AACjB,UAAI,QAAQ,OAAO,SAAS,QAAS,QAAA;AAAA,IACvC,CAAC;AAED,UAAM,QAAQ,SAAS;AAAA,MACrB,KAAK,MAAM,QAAQ,MAAM;AAAA,MACzB,KAAK,CAAC,MAAM,aAAa,QAAQ,MAAM,MAAM,CAAC;AAAA,IAAA,CAC/C;;AAIC,aAAAA,UAAA,GAAAC,mBAaM,OAbN,YAaM;AAAA,QAZJC,mBAAyC,SAAA,MAAAC,gBAA/BC,MAAA,OAAA,EAAQ,OAAO,KAAK,GAAA,CAAA;AAAA,uBAC9BF,mBAIE,SAAA;AAAA,uEAHS,MAAK,QAAA;AAAA,UACb,aAAaE,MAAA,OAAA,IAAO,aAAA;AAAA,UACrB,MAAK;AAAA,QAAA;uBAFI,MAAA,KAAK;AAAA,QAAA;QAINA,MAAA,KAAA,EAAM,uBAAhBH,mBAIK,MAAA,YAAA;AAAA,4BAHHA,mBAEKI,UAAA,MAAAC,WAFYF,MAAA,KAAA,GAAK,CAAX,OAAE;gCAAbH,mBAEK,MAAA;AAAA,cAFoB,KAAK,OAAO,GAAG,KAAK;AAAA,cAAI,SAAK,CAAA,WAAE,MAAA,QAAQ,GAAG;AAAA,YAAA,GAC9DE,gBAAA,GAAG,KAAK,GAAA,GAAA,UAAA;AAAA;;QAGFC,MAAA,KAAA,KAAbJ,aAAAC,mBAA4D,SAA5D,YAAiC,6BAAWG,MAAA,KAAA,CAAK,GAAA,CAAA;;;;;"}
@@ -0,0 +1,5 @@
1
+ import _sfc_main from "./ProviderAutocomplete.vue.js";
2
+ export {
3
+ _sfc_main as default
4
+ };
5
+ //# sourceMappingURL=ProviderAutocomplete.vue2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProviderAutocomplete.vue2.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
@@ -0,0 +1,9 @@
1
+ import type { ControlElement, JsonSchema } from "@jsonforms/core";
2
+ type __VLS_Props = {
3
+ uischema: ControlElement;
4
+ schema: JsonSchema;
5
+ path: string;
6
+ };
7
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
8
+ export default _default;
9
+ //# sourceMappingURL=ProviderSelect.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProviderSelect.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/components/ProviderSelect.vue"],"names":[],"mappings":"AAwEA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAKlE,KAAK,WAAW,GAAG;IACjB,QAAQ,EAAE,cAAc,CAAC;IACzB,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;;AAoHF,wBAEG"}
@@ -0,0 +1,8 @@
1
+ import _sfc_main from "./ProviderSelect.vue2.js";
2
+ /* empty css */
3
+ import _export_sfc from "../../_virtual/_plugin-vue_export-helper.js";
4
+ const ProviderSelect = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-1ad3fce8"]]);
5
+ export {
6
+ ProviderSelect as default
7
+ };
8
+ //# sourceMappingURL=ProviderSelect.vue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProviderSelect.vue.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
@@ -0,0 +1,74 @@
1
+ import { defineComponent, computed, watch, createElementBlock, openBlock, createElementVNode, withDirectives, createCommentVNode, toDisplayString, unref, Fragment, renderList, vModelSelect } from "vue";
2
+ import { useJsonFormsControl } from "@jsonforms/vue";
3
+ import { useProvider } from "../composables/useProvider.js";
4
+ const _hoisted_1 = { class: "provider-select" };
5
+ const _hoisted_2 = {
6
+ value: "",
7
+ disabled: ""
8
+ };
9
+ const _hoisted_3 = ["value"];
10
+ const _hoisted_4 = {
11
+ key: 0,
12
+ role: "alert"
13
+ };
14
+ const _sfc_main = /* @__PURE__ */ defineComponent({
15
+ __name: "ProviderSelect",
16
+ props: {
17
+ uischema: {},
18
+ schema: {},
19
+ path: {}
20
+ },
21
+ setup(__props) {
22
+ const props = __props;
23
+ const { control, handleChange } = useJsonFormsControl(props);
24
+ const binding = computed(() => {
25
+ const provider = control.value.uischema?.options?.provider;
26
+ if (provider && typeof provider === "object" && !provider.load) {
27
+ return { ...provider, load: "mount" };
28
+ }
29
+ return provider;
30
+ });
31
+ const deps = computed(
32
+ () => control.value.schema?.["x-provider"]?.dependsOn ?? []
33
+ );
34
+ const depValues = computed(() => deps.value.map(() => null));
35
+ const { items, loading, error, reload } = useProvider(binding, {
36
+ data: control.value.data,
37
+ path: control.value.path,
38
+ dependsOnValues: depValues.value
39
+ });
40
+ watch(
41
+ () => control.value.data,
42
+ () => {
43
+ reload();
44
+ }
45
+ );
46
+ const value = computed({
47
+ get: () => control.value.data,
48
+ set: (v) => handleChange(control.value.path, v)
49
+ });
50
+ return (_ctx, _cache) => {
51
+ return openBlock(), createElementBlock("div", _hoisted_1, [
52
+ createElementVNode("label", null, toDisplayString(unref(control).schema.title), 1),
53
+ withDirectives(createElementVNode("select", {
54
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => value.value = $event)
55
+ }, [
56
+ createElementVNode("option", _hoisted_2, toDisplayString(unref(loading) ? "Loading…" : "Select…"), 1),
57
+ (openBlock(true), createElementBlock(Fragment, null, renderList(unref(items), (it) => {
58
+ return openBlock(), createElementBlock("option", {
59
+ key: String(it.value),
60
+ value: it.value
61
+ }, toDisplayString(it.label), 9, _hoisted_3);
62
+ }), 128))
63
+ ], 512), [
64
+ [vModelSelect, value.value]
65
+ ]),
66
+ unref(error) ? (openBlock(), createElementBlock("small", _hoisted_4, "Failed to load: " + toDisplayString(unref(error)), 1)) : createCommentVNode("", true)
67
+ ]);
68
+ };
69
+ }
70
+ });
71
+ export {
72
+ _sfc_main as default
73
+ };
74
+ //# sourceMappingURL=ProviderSelect.vue2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProviderSelect.vue2.js","sources":["../../../src/vue/components/ProviderSelect.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ControlElement, JsonSchema } from \"@jsonforms/core\";\nimport { useJsonFormsControl } from \"@jsonforms/vue\";\nimport { computed, watch } from \"vue\";\nimport { useProvider } from \"../composables/useProvider\";\n\nconst props = defineProps<{\n uischema: ControlElement;\n schema: JsonSchema;\n path: string;\n}>();\nconst { control, handleChange } = useJsonFormsControl(props);\n\nconst binding = computed(() => {\n const provider = control.value.uischema?.options?.provider;\n // Ensure load property is set to 'mount' by default\n if (provider && typeof provider === \"object\" && !provider.load) {\n return { ...provider, load: \"mount\" };\n }\n return provider;\n});\n\nconst deps = computed(\n () =>\n ((\n (control.value.schema as Record<string, unknown>)?.[\n \"x-provider\"\n ] as Record<string, unknown>\n )?.dependsOn as string[]) ?? [],\n);\nconst depValues = computed(() => deps.value.map(() => null)); // you can resolve actual values via control.value.data & pointers\n\nconst { items, loading, error, reload } = useProvider(binding, {\n data: control.value.data,\n path: control.value.path,\n dependsOnValues: depValues.value,\n});\n\nwatch(\n () => control.value.data,\n () => {\n // if dependsOn changed → reload\n reload();\n },\n);\n\nconst value = computed({\n get: () => control.value.data,\n set: (v) => handleChange(control.value.path, v),\n});\n</script>\n\n<template>\n <div class=\"provider-select\">\n <label>{{ control.schema.title }}</label>\n <select v-model=\"value\">\n <option value=\"\" disabled>{{ loading ? \"Loading…\" : \"Select…\" }}</option>\n <option v-for=\"it in items\" :key=\"String(it.value)\" :value=\"it.value\">\n {{ it.label }}\n </option>\n </select>\n <small v-if=\"error\" role=\"alert\">Failed to load: {{ error }}</small>\n </div>\n</template>\n\n<style scoped>\n.provider-select select {\n min-width: 16rem;\n}\n</style>\n"],"names":["_openBlock","_createElementBlock","_createElementVNode","_toDisplayString","_unref","_Fragment","_renderList"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAMA,UAAM,QAAQ;AAKd,UAAM,EAAE,SAAS,iBAAiB,oBAAoB,KAAK;AAE3D,UAAM,UAAU,SAAS,MAAM;AAC7B,YAAM,WAAW,QAAQ,MAAM,UAAU,SAAS;AAElD,UAAI,YAAY,OAAO,aAAa,YAAY,CAAC,SAAS,MAAM;AAC9D,eAAO,EAAE,GAAG,UAAU,MAAM,QAAA;AAAA,MAC9B;AACA,aAAO;AAAA,IACT,CAAC;AAED,UAAM,OAAO;AAAA,MACX,MAEK,QAAQ,MAAM,SACb,YACF,GACC,aAA0B,CAAA;AAAA,IAAC;AAElC,UAAM,YAAY,SAAS,MAAM,KAAK,MAAM,IAAI,MAAM,IAAI,CAAC;AAE3D,UAAM,EAAE,OAAO,SAAS,OAAO,OAAA,IAAW,YAAY,SAAS;AAAA,MAC7D,MAAM,QAAQ,MAAM;AAAA,MACpB,MAAM,QAAQ,MAAM;AAAA,MACpB,iBAAiB,UAAU;AAAA,IAAA,CAC5B;AAED;AAAA,MACE,MAAM,QAAQ,MAAM;AAAA,MACpB,MAAM;AAEJ,eAAA;AAAA,MACF;AAAA,IAAA;AAGF,UAAM,QAAQ,SAAS;AAAA,MACrB,KAAK,MAAM,QAAQ,MAAM;AAAA,MACzB,KAAK,CAAC,MAAM,aAAa,QAAQ,MAAM,MAAM,CAAC;AAAA,IAAA,CAC/C;;AAIC,aAAAA,UAAA,GAAAC,mBASM,OATN,YASM;AAAA,QARJC,mBAAyC,SAAA,MAAAC,gBAA/BC,MAAA,OAAA,EAAQ,OAAO,KAAK,GAAA,CAAA;AAAA,uBAC9BF,mBAKS,UAAA;AAAA,uEALQ,MAAK,QAAA;AAAA,QAAA;UACpBA,mBAAyE,UAAzE,YAAyEC,gBAA5CC,MAAA,OAAA,IAAO,aAAA,SAAA,GAAA,CAAA;AAAA,4BACpCH,mBAESI,UAAA,MAAAC,WAFYF,MAAA,KAAA,GAAK,CAAX,OAAE;gCAAjBH,mBAES,UAAA;AAAA,cAFoB,KAAK,OAAO,GAAG,KAAK;AAAA,cAAI,OAAO,GAAG;AAAA,YAAA,GAC1DE,gBAAA,GAAG,KAAK,GAAA,GAAA,UAAA;AAAA;;yBAHE,MAAA,KAAK;AAAA,QAAA;QAMTC,MAAA,KAAA,KAAbJ,aAAAC,mBAAoE,SAApE,YAAiC,qCAAmBG,MAAA,KAAA,CAAK,GAAA,CAAA;;;;;"}
@@ -0,0 +1,14 @@
1
+ import { type ComputedRef, type Ref } from "vue";
2
+ import type { ProviderBinding, ProviderItem } from "../../core/types";
3
+ export declare function useProvider(binding: ProviderBinding | Ref<ProviderBinding> | ComputedRef<ProviderBinding>, ctxBits: {
4
+ data: unknown;
5
+ path: string;
6
+ dependsOnValues?: unknown[];
7
+ uiQuery?: string;
8
+ }): {
9
+ items: Ref<ProviderItem[], ProviderItem[]>;
10
+ loading: Ref<boolean, boolean>;
11
+ error: Ref<string | undefined, string | undefined>;
12
+ reload: () => Promise<void>;
13
+ };
14
+ //# sourceMappingURL=useProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useProvider.d.ts","sourceRoot":"","sources":["../../../src/vue/composables/useProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,WAAW,EAIhB,KAAK,GAAG,EAIT,MAAM,KAAK,CAAC;AAGb,OAAO,KAAK,EAEV,eAAe,EACf,YAAY,EAEb,MAAM,kBAAkB,CAAC;AAE1B,wBAAgB,WAAW,CACzB,OAAO,EACH,eAAe,GACf,GAAG,CAAC,eAAe,CAAC,GACpB,WAAW,CAAC,eAAe,CAAC,EAChC,OAAO,EAAE;IACP,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;;;;;EAqEF"}
@@ -0,0 +1,76 @@
1
+ import { inject, ref, computed, unref, onBeforeUnmount, watch } from "vue";
2
+ import { cache } from "../../core/cache.js";
3
+ import { registry } from "../../core/registry.js";
4
+ function useProvider(binding, ctxBits) {
5
+ const registry$1 = inject("providerRegistry", registry);
6
+ const cache$1 = inject("providerCache", cache);
7
+ const auth = inject("providerAuth", {});
8
+ const items = ref([]);
9
+ const loading = ref(false);
10
+ const error = ref(void 0);
11
+ const ac = new AbortController();
12
+ const cacheKey = computed(
13
+ () => JSON.stringify({
14
+ b: unref(binding),
15
+ d: ctxBits.dependsOnValues ?? [],
16
+ q: ctxBits.uiQuery ?? ""
17
+ })
18
+ );
19
+ async function load() {
20
+ const bindingValue = unref(binding);
21
+ if (!bindingValue) return;
22
+ loading.value = true;
23
+ error.value = void 0;
24
+ const hit = cache$1.get(cacheKey.value);
25
+ if (hit) {
26
+ items.value = hit.items;
27
+ loading.value = false;
28
+ return;
29
+ }
30
+ try {
31
+ const driver = registry$1.get(bindingValue.protocol);
32
+ if (!driver) {
33
+ throw new Error(
34
+ `No provider registered for protocol: ${bindingValue.protocol}`
35
+ );
36
+ }
37
+ const out = await driver.resolve(bindingValue.config ?? {}, {
38
+ data: ctxBits.data,
39
+ path: ctxBits.path,
40
+ ui: { query: ctxBits.uiQuery },
41
+ signal: ac.signal,
42
+ auth: resolveAuth(bindingValue.auth, auth)
43
+ });
44
+ items.value = out.items;
45
+ cache$1.set(cacheKey.value, out, bindingValue.cacheTTL ?? out.ttl ?? 0);
46
+ } catch (e) {
47
+ error.value = e?.message ?? String(e);
48
+ items.value = [];
49
+ } finally {
50
+ loading.value = false;
51
+ }
52
+ }
53
+ onBeforeUnmount(() => ac.abort());
54
+ watch(
55
+ [cacheKey],
56
+ () => {
57
+ const bindingValue = unref(binding);
58
+ if (bindingValue?.load === "mount" || bindingValue?.load === "query")
59
+ load();
60
+ },
61
+ { immediate: unref(binding)?.load === "mount" }
62
+ );
63
+ return { items, loading, error, reload: load };
64
+ }
65
+ function resolveAuth(spec, authBag) {
66
+ if (!spec) return {};
67
+ if (spec.use && typeof authBag[spec.use] === "function") {
68
+ const authFunc = authBag[spec.use];
69
+ return { [spec.use]: authFunc() };
70
+ }
71
+ return spec;
72
+ }
73
+ export {
74
+ useProvider
75
+ };
76
+ //# sourceMappingURL=useProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useProvider.js","sources":["../../../src/vue/composables/useProvider.ts"],"sourcesContent":["import {\n type ComputedRef,\n computed,\n inject,\n onBeforeUnmount,\n type Ref,\n ref,\n unref,\n watch,\n} from \"vue\";\nimport { cache as globalCache } from \"../../core/cache\";\nimport { registry as globalRegistry } from \"../../core/registry\";\nimport type {\n AuthConfig,\n ProviderBinding,\n ProviderItem,\n ProviderOutput,\n} from \"../../core/types\";\n\nexport function useProvider(\n binding:\n | ProviderBinding\n | Ref<ProviderBinding>\n | ComputedRef<ProviderBinding>,\n ctxBits: {\n data: unknown;\n path: string;\n dependsOnValues?: unknown[];\n uiQuery?: string;\n },\n) {\n const registry = inject(\"providerRegistry\", globalRegistry);\n const cache = inject(\"providerCache\", globalCache);\n const auth = inject(\"providerAuth\", {}) as Record<\n string,\n (() => string) | string\n >;\n\n const items = ref<ProviderItem[]>([]);\n const loading = ref(false);\n const error = ref<string | undefined>(undefined);\n const ac = new AbortController();\n\n const cacheKey = computed(() =>\n JSON.stringify({\n b: unref(binding),\n d: ctxBits.dependsOnValues ?? [],\n q: ctxBits.uiQuery ?? \"\",\n }),\n );\n\n async function load() {\n const bindingValue = unref(binding);\n if (!bindingValue) return;\n loading.value = true;\n error.value = undefined;\n const hit = cache.get(cacheKey.value) as ProviderOutput | undefined;\n if (hit) {\n items.value = hit.items;\n loading.value = false;\n return;\n }\n try {\n const driver = registry.get(bindingValue.protocol);\n if (!driver) {\n throw new Error(\n `No provider registered for protocol: ${bindingValue.protocol}`,\n );\n }\n const out = await driver.resolve(bindingValue.config ?? {}, {\n data: ctxBits.data,\n path: ctxBits.path,\n ui: { query: ctxBits.uiQuery },\n signal: ac.signal,\n auth: resolveAuth(bindingValue.auth, auth),\n });\n items.value = out.items;\n cache.set(cacheKey.value, out, bindingValue.cacheTTL ?? out.ttl ?? 0);\n } catch (e) {\n error.value = (e as Error)?.message ?? String(e);\n items.value = [];\n } finally {\n loading.value = false;\n }\n }\n\n onBeforeUnmount(() => ac.abort());\n watch(\n [cacheKey],\n () => {\n const bindingValue = unref(binding);\n if (bindingValue?.load === \"mount\" || bindingValue?.load === \"query\")\n load();\n },\n { immediate: unref(binding)?.load === \"mount\" },\n );\n\n return { items, loading, error, reload: load };\n}\n\nfunction resolveAuth(\n spec: AuthConfig | undefined,\n authBag: Record<string, (() => string) | string>,\n): AuthConfig {\n if (!spec) return {};\n if (spec.use && typeof authBag[spec.use] === \"function\") {\n const authFunc = authBag[spec.use] as () => string;\n return { [spec.use]: authFunc() };\n }\n return spec;\n}\n"],"names":["registry","globalRegistry","cache","globalCache"],"mappings":";;;AAmBO,SAAS,YACd,SAIA,SAMA;AACA,QAAMA,aAAW,OAAO,oBAAoBC,QAAc;AAC1D,QAAMC,UAAQ,OAAO,iBAAiBC,KAAW;AACjD,QAAM,OAAO,OAAO,gBAAgB,EAAE;AAKtC,QAAM,QAAQ,IAAoB,EAAE;AACpC,QAAM,UAAU,IAAI,KAAK;AACzB,QAAM,QAAQ,IAAwB,MAAS;AAC/C,QAAM,KAAK,IAAI,gBAAA;AAEf,QAAM,WAAW;AAAA,IAAS,MACxB,KAAK,UAAU;AAAA,MACb,GAAG,MAAM,OAAO;AAAA,MAChB,GAAG,QAAQ,mBAAmB,CAAA;AAAA,MAC9B,GAAG,QAAQ,WAAW;AAAA,IAAA,CACvB;AAAA,EAAA;AAGH,iBAAe,OAAO;AACpB,UAAM,eAAe,MAAM,OAAO;AAClC,QAAI,CAAC,aAAc;AACnB,YAAQ,QAAQ;AAChB,UAAM,QAAQ;AACd,UAAM,MAAMD,QAAM,IAAI,SAAS,KAAK;AACpC,QAAI,KAAK;AACP,YAAM,QAAQ,IAAI;AAClB,cAAQ,QAAQ;AAChB;AAAA,IACF;AACA,QAAI;AACF,YAAM,SAASF,WAAS,IAAI,aAAa,QAAQ;AACjD,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI;AAAA,UACR,wCAAwC,aAAa,QAAQ;AAAA,QAAA;AAAA,MAEjE;AACA,YAAM,MAAM,MAAM,OAAO,QAAQ,aAAa,UAAU,IAAI;AAAA,QAC1D,MAAM,QAAQ;AAAA,QACd,MAAM,QAAQ;AAAA,QACd,IAAI,EAAE,OAAO,QAAQ,QAAA;AAAA,QACrB,QAAQ,GAAG;AAAA,QACX,MAAM,YAAY,aAAa,MAAM,IAAI;AAAA,MAAA,CAC1C;AACD,YAAM,QAAQ,IAAI;AAClBE,cAAM,IAAI,SAAS,OAAO,KAAK,aAAa,YAAY,IAAI,OAAO,CAAC;AAAA,IACtE,SAAS,GAAG;AACV,YAAM,QAAS,GAAa,WAAW,OAAO,CAAC;AAC/C,YAAM,QAAQ,CAAA;AAAA,IAChB,UAAA;AACE,cAAQ,QAAQ;AAAA,IAClB;AAAA,EACF;AAEA,kBAAgB,MAAM,GAAG,OAAO;AAChC;AAAA,IACE,CAAC,QAAQ;AAAA,IACT,MAAM;AACJ,YAAM,eAAe,MAAM,OAAO;AAClC,UAAI,cAAc,SAAS,WAAW,cAAc,SAAS;AAC3D,aAAA;AAAA,IACJ;AAAA,IACA,EAAE,WAAW,MAAM,OAAO,GAAG,SAAS,QAAA;AAAA,EAAQ;AAGhD,SAAO,EAAE,OAAO,SAAS,OAAO,QAAQ,KAAA;AAC1C;AAEA,SAAS,YACP,MACA,SACY;AACZ,MAAI,CAAC,KAAM,QAAO,CAAA;AAClB,MAAI,KAAK,OAAO,OAAO,QAAQ,KAAK,GAAG,MAAM,YAAY;AACvD,UAAM,WAAW,QAAQ,KAAK,GAAG;AACjC,WAAO,EAAE,CAAC,KAAK,GAAG,GAAG,WAAS;AAAA,EAChC;AACA,SAAO;AACT;"}
@@ -0,0 +1,19 @@
1
+ import type { UISchemaElement } from "@jsonforms/core";
2
+ import ProviderAutocomplete from "./components/ProviderAutocomplete.vue";
3
+ import ProviderSelect from "./components/ProviderSelect.vue";
4
+ export declare const providerRenderers: {
5
+ tester: (uischema: UISchemaElement, schema: import("@jsonforms/core").JsonSchema, context: import("@jsonforms/core").TesterContext) => number;
6
+ renderer: import("vue").DefineComponent<{
7
+ uischema: import("@jsonforms/core").ControlElement;
8
+ schema: import("@jsonforms/core").JsonSchema;
9
+ path: string;
10
+ }, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{
11
+ uischema: import("@jsonforms/core").ControlElement;
12
+ schema: import("@jsonforms/core").JsonSchema;
13
+ path: string;
14
+ }> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
15
+ }[];
16
+ export { ProviderAutocomplete, ProviderSelect };
17
+ export { useProvider } from "./composables/useProvider";
18
+ export * from "./testers";
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vue/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AASvD,OAAO,oBAAoB,MAAM,uCAAuC,CAAC;AACzE,OAAO,cAAc,MAAM,iCAAiC,CAAC;AA0B7D,eAAO,MAAM,iBAAiB;;;;;;;;;;;GAG7B,CAAC;AAEF,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,cAAc,WAAW,CAAC"}
@@ -0,0 +1,36 @@
1
+ import { rankWith, and, or, isStringControl, isNumberControl, isIntegerControl } from "@jsonforms/core";
2
+ import _sfc_main from "./components/ProviderAutocomplete.vue.js";
3
+ import ProviderSelect from "./components/ProviderSelect.vue.js";
4
+ import { useProvider } from "./composables/useProvider.js";
5
+ import { providerTester } from "./testers.js";
6
+ const hasProvider = (uischema) => {
7
+ return uischema?.options?.provider !== void 0;
8
+ };
9
+ const providerSelectTester = rankWith(
10
+ 6,
11
+ and(
12
+ or(isStringControl, isNumberControl, isIntegerControl),
13
+ hasProvider,
14
+ (uischema) => !uischema?.options?.autocomplete
15
+ )
16
+ );
17
+ const providerAutocompleteTester = rankWith(
18
+ 7,
19
+ and(
20
+ or(isStringControl, isNumberControl, isIntegerControl),
21
+ hasProvider,
22
+ (uischema) => uischema?.options?.autocomplete === true
23
+ )
24
+ );
25
+ const providerRenderers = [
26
+ { tester: providerSelectTester, renderer: ProviderSelect },
27
+ { tester: providerAutocompleteTester, renderer: _sfc_main }
28
+ ];
29
+ export {
30
+ _sfc_main as ProviderAutocomplete,
31
+ ProviderSelect,
32
+ providerRenderers,
33
+ providerTester,
34
+ useProvider
35
+ };
36
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../src/vue/index.ts"],"sourcesContent":["import type { UISchemaElement } from \"@jsonforms/core\";\nimport {\n and,\n isIntegerControl,\n isNumberControl,\n isStringControl,\n or,\n rankWith,\n} from \"@jsonforms/core\";\nimport ProviderAutocomplete from \"./components/ProviderAutocomplete.vue\";\nimport ProviderSelect from \"./components/ProviderSelect.vue\";\n\n// Custom tester that checks if provider option exists (as object or boolean)\nconst hasProvider = (uischema: UISchemaElement) => {\n return uischema?.options?.provider !== undefined;\n};\n\n// Create specific testers for each component type\nconst providerSelectTester = rankWith(\n 6,\n and(\n or(isStringControl, isNumberControl, isIntegerControl),\n hasProvider,\n (uischema) => !uischema?.options?.autocomplete,\n ),\n);\n\nconst providerAutocompleteTester = rankWith(\n 7,\n and(\n or(isStringControl, isNumberControl, isIntegerControl),\n hasProvider,\n (uischema) => uischema?.options?.autocomplete === true,\n ),\n);\n\nexport const providerRenderers = [\n { tester: providerSelectTester, renderer: ProviderSelect },\n { tester: providerAutocompleteTester, renderer: ProviderAutocomplete },\n];\n\nexport { ProviderAutocomplete, ProviderSelect };\nexport { useProvider } from \"./composables/useProvider\";\nexport * from \"./testers\";\n"],"names":["ProviderAutocomplete"],"mappings":";;;;;AAaA,MAAM,cAAc,CAAC,aAA8B;AACjD,SAAO,UAAU,SAAS,aAAa;AACzC;AAGA,MAAM,uBAAuB;AAAA,EAC3B;AAAA,EACA;AAAA,IACE,GAAG,iBAAiB,iBAAiB,gBAAgB;AAAA,IACrD;AAAA,IACA,CAAC,aAAa,CAAC,UAAU,SAAS;AAAA,EAAA;AAEtC;AAEA,MAAM,6BAA6B;AAAA,EACjC;AAAA,EACA;AAAA,IACE,GAAG,iBAAiB,iBAAiB,gBAAgB;AAAA,IACrD;AAAA,IACA,CAAC,aAAa,UAAU,SAAS,iBAAiB;AAAA,EAAA;AAEtD;AAEO,MAAM,oBAAoB;AAAA,EAC/B,EAAE,QAAQ,sBAAsB,UAAU,eAAA;AAAA,EAC1C,EAAE,QAAQ,4BAA4B,UAAUA,UAAA;AAClD;"}
@@ -0,0 +1,2 @@
1
+ export declare const providerTester: (uischema: import("@jsonforms/core").UISchemaElement, schema: import("@jsonforms/core").JsonSchema, context: import("@jsonforms/core").TesterContext) => number;
2
+ //# sourceMappingURL=testers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testers.d.ts","sourceRoot":"","sources":["../../src/vue/testers.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,cAAc,iKAQ1B,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { rankWith, and, or, isStringControl, isNumberControl, isIntegerControl } from "@jsonforms/core";
2
+ const providerTester = rankWith(
3
+ 5,
4
+ and(
5
+ or(isStringControl, isNumberControl, isIntegerControl),
6
+ (uischema) => uischema?.options?.provider !== void 0 && uischema?.options?.provider !== null
7
+ )
8
+ );
9
+ export {
10
+ providerTester
11
+ };
12
+ //# sourceMappingURL=testers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testers.js","sources":["../../src/vue/testers.ts"],"sourcesContent":["import {\n and,\n isIntegerControl,\n isNumberControl,\n isStringControl,\n or,\n rankWith,\n} from \"@jsonforms/core\";\n\n// Tester that checks if provider option exists (as object or boolean)\nexport const providerTester = rankWith(\n 5,\n and(\n or(isStringControl, isNumberControl, isIntegerControl),\n (uischema: import(\"@jsonforms/core\").UISchemaElement) =>\n uischema?.options?.provider !== undefined &&\n uischema?.options?.provider !== null,\n ),\n);\n"],"names":[],"mappings":";AAUO,MAAM,iBAAiB;AAAA,EAC5B;AAAA,EACA;AAAA,IACE,GAAG,iBAAiB,iBAAiB,gBAAgB;AAAA,IACrD,CAAC,aACC,UAAU,SAAS,aAAa,UAChC,UAAU,SAAS,aAAa;AAAA,EAAA;AAEtC;"}
package/package.json ADDED
@@ -0,0 +1,100 @@
1
+ {
2
+ "name": "@narrative.io/jsonforms-provider-protocols",
3
+ "version": "1.0.3",
4
+ "description": "Dynamic data provider capabilities for JSONForms with Vue 3 integration",
5
+ "type": "module",
6
+ "author": "Narrative I/O",
7
+ "license": "MIT",
8
+ "homepage": "https://github.com/narrative-io/jsonforms-provider-protocols#readme",
9
+ "documentation": "https://github.com/narrative-io/jsonforms-provider-protocols/tree/main/docs",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/narrative-io/jsonforms-provider-protocols.git"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/narrative-io/jsonforms-provider-protocols/issues"
16
+ },
17
+ "keywords": [
18
+ "jsonforms",
19
+ "vue",
20
+ "vue3",
21
+ "forms",
22
+ "json-schema",
23
+ "data-provider",
24
+ "rest-api",
25
+ "dynamic-forms"
26
+ ],
27
+ "engines": {
28
+ "node": ">=20.19.0"
29
+ },
30
+ "publishConfig": {
31
+ "access": "public",
32
+ "registry": "https://registry.npmjs.org/"
33
+ },
34
+ "main": "./dist/index.js",
35
+ "module": "./dist/index.js",
36
+ "types": "./dist/index.d.ts",
37
+ "exports": {
38
+ ".": {
39
+ "import": "./dist/index.js",
40
+ "types": "./dist/index.d.ts"
41
+ },
42
+ "./vue": {
43
+ "import": "./dist/vue/index.js",
44
+ "types": "./dist/vue/index.d.ts"
45
+ },
46
+ "./protocols/rest_api": {
47
+ "import": "./dist/protocols/rest_api.js",
48
+ "types": "./dist/protocols/rest_api.d.ts"
49
+ },
50
+ "./style.css": "./dist/jsonforms-provider-protocols.css"
51
+ },
52
+ "files": [
53
+ "dist",
54
+ "src"
55
+ ],
56
+ "scripts": {
57
+ "build": "bun run build:lib && bun run build:types",
58
+ "build:lib": "vite build",
59
+ "build:types": "vue-tsc -p tsconfig.build.json --declaration --emitDeclarationOnly",
60
+ "build:clean": "rm -rf dist",
61
+ "prepare": "bun-git-hooks",
62
+ "prepublishOnly": "bun run build",
63
+ "test": "bun test",
64
+ "test:watch": "bun test --watch",
65
+ "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix",
66
+ "lint:check": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts",
67
+ "format": "prettier --write src/"
68
+ },
69
+ "devDependencies": {
70
+ "@commitlint/config-conventional": "^19.8.1",
71
+ "@eslint/js": "^9.34.0",
72
+ "@jsonforms/core": "^3.6.0",
73
+ "@jsonforms/vue": "^3.6.0",
74
+ "@jsonforms/vue-vanilla": "^3.6.0",
75
+ "@types/bun": "latest",
76
+ "@vitejs/plugin-vue": "^6.0.1",
77
+ "@vue/eslint-config-typescript": "^14.6.0",
78
+ "@vue/runtime-core": "^3.5.20",
79
+ "bun-git-hooks": "^0.2.19",
80
+ "commitlint": "^19.8.1",
81
+ "eslint": "^9.34.0",
82
+ "eslint-config-prettier": "^10.1.8",
83
+ "eslint-plugin-vue": "^10.4.0",
84
+ "globals": "^16.3.0",
85
+ "prettier": "^3.6.2",
86
+ "typescript": "^5.9.2",
87
+ "typescript-eslint": "^8.41.0",
88
+ "vite": "^7.1.3",
89
+ "vue": "^3.5.20",
90
+ "vue-tsc": "^3.0.6"
91
+ },
92
+ "peerDependencies": {
93
+ "typescript": "^5",
94
+ "vue": "^3.4.0 || ^3.5.0",
95
+ "@jsonforms/core": "^3.6.0",
96
+ "@jsonforms/vue": "^3.6.0",
97
+ "@jsonforms/vue-vanilla": "^3.6.0"
98
+ },
99
+ "dependencies": {}
100
+ }
@@ -0,0 +1,23 @@
1
+ type Entry<T> = { value: T; expiresAt: number };
2
+ export class TTLCache<T> {
3
+ private m = new Map<string, Entry<T>>();
4
+ get(k: string) {
5
+ const e = this.m.get(k);
6
+ if (!e) return undefined;
7
+ if (e.expiresAt !== 0 && Date.now() > e.expiresAt) {
8
+ this.m.delete(k);
9
+ return undefined;
10
+ }
11
+ return e.value;
12
+ }
13
+ set(k: string, v: T, ttlSec = 0) {
14
+ this.m.set(k, {
15
+ value: v,
16
+ expiresAt: ttlSec ? Date.now() + ttlSec * 1000 : 0,
17
+ });
18
+ }
19
+ del(k: string) {
20
+ this.m.delete(k);
21
+ }
22
+ }
23
+ export const cache = new TTLCache<unknown>();
@@ -0,0 +1,41 @@
1
+ export function jp(obj: unknown, path: string): unknown[] {
2
+ // naive: support "$.a.b[*].c" & "$.items[*]"
3
+ if (path === "$") return [obj];
4
+ if (path === "") return [obj]; // Empty string should behave like "$"
5
+ if (!path || typeof path !== "string") return [];
6
+
7
+ // Handle array at root with $[*]
8
+ if (path.startsWith("$[*]")) {
9
+ if (!Array.isArray(obj)) return [];
10
+ const remainingPath = path.slice(4); // Remove "$[*]"
11
+ if (!remainingPath) return obj;
12
+ if (remainingPath.startsWith(".")) {
13
+ // Continue with remaining path for each array element
14
+ const subPath = remainingPath.slice(1);
15
+ const results: unknown[] = [];
16
+ for (const item of obj) {
17
+ results.push(...jp(item, subPath));
18
+ }
19
+ return results;
20
+ }
21
+ return [];
22
+ }
23
+
24
+ const parts = path.replace(/^\$\./, "").split(".");
25
+ let current: unknown[] = [obj];
26
+ for (const part of parts) {
27
+ const next: unknown[] = [];
28
+ const m = part.match(/^(\w+)(\[\*\])?$/);
29
+ if (!m) return [];
30
+ const key = m[1];
31
+ if (!key) return [];
32
+ const star = !!m[2];
33
+ for (const c of current) {
34
+ const v = (c as Record<string, unknown>)?.[key];
35
+ if (star && Array.isArray(v)) next.push(...v);
36
+ else if (!star && v !== undefined) next.push(v);
37
+ }
38
+ current = next;
39
+ }
40
+ return current;
41
+ }
@@ -0,0 +1,15 @@
1
+ import type { Protocol } from "./types";
2
+
3
+ export class ProtocolRegistry {
4
+ private drivers = new Map<string, Protocol>();
5
+ register(p: Protocol) {
6
+ this.drivers.set(p.protocol, p);
7
+ }
8
+ get(name: string): Protocol {
9
+ const p = this.drivers.get(name);
10
+ if (!p) throw new Error(`Protocol '${name}' not registered`);
11
+ return p;
12
+ }
13
+ }
14
+
15
+ export const registry = new ProtocolRegistry();