@piveau/sdk-vue 0.0.0-alpha-2.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.
Files changed (68) hide show
  1. package/README.md +66 -0
  2. package/dist/__tests__/defineResourceGetters.test.d.ts +1 -0
  3. package/dist/__tests__/defineResourceGetters.test.js +119 -0
  4. package/dist/__tests__/testUtils.d.ts +10 -0
  5. package/dist/__tests__/testUtils.js +10 -0
  6. package/dist/__tests__/useResourceFactory.test.d.ts +1 -0
  7. package/dist/__tests__/useResourceFactory.test.js +125 -0
  8. package/dist/__tests__/useSearchFactory.test.d.ts +1 -0
  9. package/dist/__tests__/useSearchFactory.test.js +102 -0
  10. package/dist/__tests__/useSearchQueryParams.test.d.ts +1 -0
  11. package/dist/__tests__/useSearchQueryParams.test.js +89 -0
  12. package/dist/composables/locale.d.ts +27 -0
  13. package/dist/composables/locale.js +8 -0
  14. package/dist/composables/usePropertyTable.d.ts +1 -0
  15. package/dist/composables/usePropertyTable.js +2 -0
  16. package/dist/defineHubSearch.d.ts +37 -0
  17. package/dist/defineHubSearch.js +91 -0
  18. package/dist/getters.d.ts +26 -0
  19. package/dist/getters.js +28 -0
  20. package/dist/index.d.ts +19 -0
  21. package/dist/index.js +29 -0
  22. package/dist/integrations/__tests__/dcatAp.test.d.ts +1 -0
  23. package/dist/integrations/__tests__/dcatAp.test.js +36 -0
  24. package/dist/integrations/__tests__/https-data-paysdelaloire-fr-explore-dataset-agenda-culture-de-la-region-des-pays-de-la-loire-.json +647 -0
  25. package/dist/integrations/dcatAp/dcatAp.d.ts +1107 -0
  26. package/dist/integrations/dcatAp/dcatAp.js +185 -0
  27. package/dist/integrations/dcatAp/index.d.ts +2 -0
  28. package/dist/integrations/dcatAp/index.js +2 -0
  29. package/dist/integrations/dcatAp/properties.d.ts +9 -0
  30. package/dist/integrations/dcatAp/properties.js +142 -0
  31. package/dist/integrations/index.d.ts +1 -0
  32. package/dist/integrations/index.js +1 -0
  33. package/dist/locale/__tests__/index.test.d.ts +1 -0
  34. package/dist/locale/__tests__/index.test.js +12 -0
  35. package/dist/locale/adapters/default.d.ts +6 -0
  36. package/dist/locale/adapters/default.js +60 -0
  37. package/dist/locale/de.d.ts +2096 -0
  38. package/dist/locale/de.js +2096 -0
  39. package/dist/locale/en.d.ts +2101 -0
  40. package/dist/locale/en.js +2101 -0
  41. package/dist/locale/index.d.ts +2 -0
  42. package/dist/locale/index.js +2 -0
  43. package/dist/mock/db.json +10862 -0
  44. package/dist/mock/mockedHubSearch.d.ts +4 -0
  45. package/dist/mock/mockedHubSearch.js +40 -0
  46. package/dist/types.d.ts +2 -0
  47. package/dist/types.js +0 -0
  48. package/dist/useGettersFactory.d.ts +7 -0
  49. package/dist/useGettersFactory.js +10 -0
  50. package/dist/useMetrics.d.ts +14 -0
  51. package/dist/useMetrics.js +22 -0
  52. package/dist/useResourceFactory.d.ts +41 -0
  53. package/dist/useResourceFactory.js +89 -0
  54. package/dist/useSearchFactory.d.ts +91 -0
  55. package/dist/useSearchFactory.js +161 -0
  56. package/dist/useSearchQueryParams.d.ts +223 -0
  57. package/dist/useSearchQueryParams.js +91 -0
  58. package/dist/utils/__tests__/propertyTable.test.d.ts +1 -0
  59. package/dist/utils/__tests__/propertyTable.test.js +372 -0
  60. package/dist/utils/helpers.d.ts +92 -0
  61. package/dist/utils/helpers.js +46 -0
  62. package/dist/utils/propertyTable.d.ts +82 -0
  63. package/dist/utils/propertyTable.js +113 -0
  64. package/dist/utils/vHelpers.d.ts +58 -0
  65. package/dist/utils/vHelpers.js +50 -0
  66. package/dist/utils.d.ts +61 -0
  67. package/dist/utils.js +37 -0
  68. package/package.json +54 -0
package/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # @piveau/sdk-vue
2
+
3
+ Asynchronous state management for interacting with piveau services in Vue.js.
4
+
5
+ Looking for a standalone API client? Try @piveau/sdk-core
6
+
7
+ ## Quick Features
8
+
9
+ - Provides intelligent client-side caching, background updates, and optimistic updates of piveau backend data state in a declarative way, powered by [@tanstack/vue-query](https://github.com/TanStack/query)
10
+ - Composable utility functions to help you model real-world use cases easier, e.g., facets, search, and pagination
11
+ - Runtime resource schema validation and model type inference powered by [Zod](https://zod.dev/)
12
+ - Shape data from API to your data model using getters
13
+ - Vue 3 compatible
14
+ - Supports Server-Side Rendering with Nuxt
15
+ - Written with TypeScript
16
+
17
+ ## Usage
18
+
19
+ <table>
20
+ <tbody valign=top align=left>
21
+ <tr><th>
22
+ Node 20+, Vue 3
23
+ </th><td>
24
+
25
+ Install with <code>npm/pnpm install @piveau/sdk-vue</code>, or <code>yarn add @piveau/sdk-vue</code>. For better devtooling, we recommend installing @piveau/sdk-core and vue-query with <code>npm/pnpm install @piveau/sdk-core @tanstack/vue-query@5</code>.
26
+
27
+ **Recommended**: In `main.ts`, setup the plugin:
28
+ ```js
29
+ import { createApp } from 'vue'
30
+ import { plugin } from '@piveau/sdk-vue'
31
+ import { QueryClient, VueQueryPlugin } from '@tanstack/vue-query'
32
+ import App from './App.vue'
33
+
34
+ const qc = new QueryClient()
35
+
36
+ const app = createApp(App)
37
+
38
+ app.use(VueQueryPlugin, {
39
+ queryClient: qc,
40
+ })
41
+
42
+ app.use(plugin, {
43
+ queryClient: qc,
44
+ })
45
+ ```
46
+
47
+ </td></tr>
48
+ <tr><th>
49
+ Node 20+, Nuxt 3
50
+ </th><td>
51
+ *Work in Progress* See https://tanstack.com/query/latest/docs/framework/vue/guides/ssr and register the sdk-vue plugin as above
52
+ </td></tr>
53
+ </tbody>
54
+ </table>
55
+
56
+ ## piveau API Support
57
+
58
+ - `/search/filter={filter}` for searching resources
59
+ - `/search/{index}/{id}` for fetching a single resource
60
+
61
+ ## Work in Progress
62
+
63
+ - hub
64
+ - consus
65
+ - metrics
66
+ - statistics
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,119 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import * as z from "zod";
3
+ import { nextTick, ref } from "vue-demi";
4
+ import { defineResourceSearchOptions } from "../createUseResourceSearch.js";
5
+ import { defineGetters, toComputedGetters } from "../getters.js";
6
+ describe("defineResourceGetters", () => {
7
+ it("should work", async () => {
8
+ const ctx = defineResourceSearchOptions({
9
+ baseUrl: `https://open.bydata.de/api/hub/search`,
10
+ index: "dataset",
11
+ schema: z.object({
12
+ foo: z.string(),
13
+ bar: z.number()
14
+ }),
15
+ facets: ["categories", "publisher", "catalog"]
16
+ });
17
+ const getters = defineGetters({
18
+ schema: z.object({
19
+ foo: z.string(),
20
+ bar: z.number()
21
+ }),
22
+ ctx,
23
+ getters: {
24
+ /**
25
+ * Gets the test result
26
+ */
27
+ getTestResult: (data) => {
28
+ return `${data.foo}${data.bar}`;
29
+ },
30
+ getOtherTestResult: () => {
31
+ return "otherTest";
32
+ },
33
+ getBaseUrl: (_, ctx2) => {
34
+ return ctx2?.baseUrl;
35
+ },
36
+ getFullTestResult: (data, ctx2) => {
37
+ return `${data.foo}${data.bar}${ctx2?.baseUrl}`;
38
+ }
39
+ }
40
+ });
41
+ expect(
42
+ getters.getTestResult({
43
+ foo: "test",
44
+ bar: 123
45
+ })
46
+ ).toBe("test123");
47
+ expect(getters.getOtherTestResult()).toBe("otherTest");
48
+ expect(
49
+ getters.getBaseUrl(
50
+ {
51
+ foo: "test",
52
+ bar: 123
53
+ },
54
+ ctx
55
+ )
56
+ ).toBe(ctx.baseUrl);
57
+ expect(
58
+ getters.getFullTestResult(
59
+ {
60
+ foo: "test",
61
+ bar: 123
62
+ },
63
+ ctx
64
+ )
65
+ ).toBe(`test123${ctx.baseUrl}`);
66
+ });
67
+ it("should work with computed getters", async () => {
68
+ const ctx = defineResourceSearchOptions({
69
+ baseUrl: `https://open.bydata.de/api/hub/search`,
70
+ index: "dataset",
71
+ schema: z.object({
72
+ foo: z.string(),
73
+ bar: z.number()
74
+ }),
75
+ facets: ["categories", "publisher", "catalog"]
76
+ });
77
+ const getters = defineGetters({
78
+ schema: z.object({
79
+ foo: z.string(),
80
+ bar: z.number()
81
+ }),
82
+ ctx,
83
+ getters: {
84
+ getTestResult: (data2) => {
85
+ return `${data2.foo}${data2.bar}`;
86
+ },
87
+ getOtherTestResult: () => {
88
+ return "otherTest";
89
+ },
90
+ getBaseUrl: (_, ctx2) => {
91
+ return ctx2?.baseUrl;
92
+ },
93
+ getFullTestResult: (data2, ctx2) => {
94
+ return `${data2.foo}${data2.bar}${ctx2?.baseUrl}`;
95
+ }
96
+ }
97
+ });
98
+ const data = ref({
99
+ foo: "test",
100
+ bar: 123
101
+ });
102
+ const computedGetters = toComputedGetters(
103
+ { data, getters, ctx }
104
+ );
105
+ expect(computedGetters.getTestResult.value).toBe("test123");
106
+ expect(computedGetters.getOtherTestResult.value).toBe("otherTest");
107
+ expect(computedGetters.getBaseUrl.value).toBe(ctx.baseUrl);
108
+ expect(computedGetters.getFullTestResult.value).toBe(`test123${ctx.baseUrl}`);
109
+ data.value = {
110
+ foo: "foo",
111
+ bar: 456
112
+ };
113
+ await nextTick();
114
+ expect(computedGetters.getTestResult.value).toBe("foo456");
115
+ expect(computedGetters.getOtherTestResult.value).toBe("otherTest");
116
+ expect(computedGetters.getBaseUrl.value).toBe(ctx.baseUrl);
117
+ expect(computedGetters.getFullTestResult.value).toBe(`foo456${ctx.baseUrl}`);
118
+ });
119
+ });
@@ -0,0 +1,10 @@
1
+ export declare const defaultQueryClientConfig: {
2
+ defaultOptions: {
3
+ queries: {
4
+ refetchOnWindowFocus: false;
5
+ retry: false;
6
+ staleTime: number;
7
+ gcTime: number;
8
+ };
9
+ };
10
+ };
@@ -0,0 +1,10 @@
1
+ export const defaultQueryClientConfig = {
2
+ defaultOptions: {
3
+ queries: {
4
+ refetchOnWindowFocus: false,
5
+ retry: false,
6
+ staleTime: Number.POSITIVE_INFINITY,
7
+ gcTime: Number.POSITIVE_INFINITY
8
+ }
9
+ }
10
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,125 @@
1
+ import { beforeEach, describe, expect, it, vi } from "vitest";
2
+ import * as z from "zod";
3
+ import { QueryClient } from "@tanstack/vue-query";
4
+ import { computed, effectScope, nextTick, reactive, ref, toRef, toValue, watch } from "vue-demi";
5
+ import { syncRef, until, watchOnce } from "@vueuse/core";
6
+ import { useResourceFactory } from "../useResourceFactory.js";
7
+ import { defaultQueryClientConfig } from "./testUtils.js";
8
+ const schema = z.object({
9
+ foo: z.string()
10
+ });
11
+ function createUseResource(qc, cb) {
12
+ const useResource = useResourceFactory({
13
+ baseUrl: "https://example.org",
14
+ schema,
15
+ index: "dataset",
16
+ indexSearch: "dataset",
17
+ qc,
18
+ enabled: true,
19
+ ctx: {
20
+ locale: "en"
21
+ },
22
+ fetcherFn: cb
23
+ }, (data, ctx) => {
24
+ const getHelloFoo = computed(() => `$hello ${toValue(data)?.foo}`);
25
+ const getFoo = computed(() => toValue(data)?.foo);
26
+ const getFooCapitalized = computed(() => toValue(data)?.foo.toUpperCase());
27
+ const getContextualFoo = computed(() => `${toValue(data)?.foo}-${toValue(ctx)?.locale}`);
28
+ return {
29
+ getHelloFoo,
30
+ getFoo,
31
+ getFooCapitalized,
32
+ getContextualFoo
33
+ };
34
+ });
35
+ return useResource;
36
+ }
37
+ describe("useResourceFactory", () => {
38
+ const fetcherSpy = vi.fn(({ id }) => {
39
+ const mockResult = {
40
+ success: true,
41
+ result: {
42
+ foo: id ?? "bar"
43
+ }
44
+ };
45
+ return Promise.resolve(mockResult);
46
+ });
47
+ let useResource = {};
48
+ beforeEach(() => {
49
+ vi.clearAllMocks();
50
+ const qc = new QueryClient(defaultQueryClientConfig);
51
+ useResource = createUseResource(qc, fetcherSpy);
52
+ });
53
+ it("should return a function", async () => {
54
+ expect(useResource).toBeTypeOf("function");
55
+ });
56
+ it("should call fetcherFn", async () => {
57
+ const scope = effectScope(true);
58
+ const hasResult = ref(false);
59
+ const result = ref({});
60
+ const helloFoo = ref("");
61
+ const id = ref("some-id");
62
+ const headers = ref({ foo: "bar" });
63
+ await scope.run(async () => {
64
+ const resourceQuery = useResource(id, { headers });
65
+ syncRef(resourceQuery.result, result, { direction: "ltr" });
66
+ watchOnce(() => resourceQuery.query.isSuccess.value, async (_count) => {
67
+ if (resourceQuery.isSuccess.value === true)
68
+ resourceQuery.result.value;
69
+ await nextTick();
70
+ hasResult.value = true;
71
+ });
72
+ watch(() => resourceQuery.resultEnhanced.value?.getHelloFoo, (value) => {
73
+ helloFoo.value = value;
74
+ });
75
+ });
76
+ await until(() => !!hasResult.value).toBe(true);
77
+ expect(fetcherSpy).toHaveBeenCalledTimes(1);
78
+ expect(fetcherSpy).toHaveBeenCalledWith({
79
+ baseUrl: "https://example.org",
80
+ resource: "dataset",
81
+ id: "some-id",
82
+ headers: { foo: "bar" }
83
+ });
84
+ expect(result.value).toEqual({ foo: "some-id" });
85
+ id.value = "some-other-id";
86
+ headers.value = { foo: "baz" };
87
+ await nextTick();
88
+ await nextTick();
89
+ expect(fetcherSpy).toHaveBeenCalledTimes(2);
90
+ await until(() => !!result.value).toBe(true);
91
+ expect(result.value).toEqual({ foo: "some-other-id" });
92
+ expect(helloFoo.value).toBe("$hello some-other-id");
93
+ });
94
+ it("should properly apply setup", async () => {
95
+ const scope = effectScope(true);
96
+ const hasResult = ref(false);
97
+ const result = ref({});
98
+ const id = ref("some-id");
99
+ await scope.run(async () => {
100
+ const resourceQuery = reactive(useResource(id));
101
+ syncRef(toRef(resourceQuery.result), result, { direction: "ltr" });
102
+ watchOnce(() => resourceQuery.isSuccess, async (_count) => {
103
+ await nextTick();
104
+ hasResult.value = true;
105
+ });
106
+ await until(() => !!resourceQuery.isSuccess).toBe(true);
107
+ await nextTick();
108
+ expect(resourceQuery.isSuccess).toBe(true);
109
+ if (resourceQuery.isSuccess) {
110
+ expect(resourceQuery.resultEnhanced.getFoo).toBe("some-id");
111
+ expect(resourceQuery.resultEnhanced.getFooCapitalized).toBe("SOME-ID");
112
+ expect(resourceQuery.resultEnhanced.getContextualFoo).toBe("some-id-en");
113
+ }
114
+ id.value = "some-other-id";
115
+ await nextTick();
116
+ await until(() => !!resourceQuery.isSuccess).toBe(true);
117
+ expect(resourceQuery.isSuccess).toBe(true);
118
+ if (resourceQuery.isSuccess) {
119
+ expect(resourceQuery.resultEnhanced.getFoo).toBe("some-other-id");
120
+ expect(resourceQuery.resultEnhanced.getFooCapitalized).toBe("SOME-OTHER-ID");
121
+ expect(resourceQuery.resultEnhanced.getContextualFoo).toBe("some-other-id-en");
122
+ }
123
+ });
124
+ });
125
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,102 @@
1
+ import { beforeEach, describe, expect, it, vi } from "vitest";
2
+ import * as z from "zod";
3
+ import { QueryClient } from "@tanstack/vue-query";
4
+ import { computed, effectScope, nextTick, ref, toValue } from "vue-demi";
5
+ import { until, watchOnce } from "@vueuse/core";
6
+ import { useSearchFactory } from "../useSearchFactory.js";
7
+ import { defaultQueryClientConfig } from "./testUtils.js";
8
+ function createUseSearch(qc, cb) {
9
+ const useSearch = useSearchFactory({
10
+ ctx: {
11
+ baseUrl: "https://foo.bar"
12
+ },
13
+ schema: z.object({
14
+ foo: z.string(),
15
+ bar: z.number()
16
+ }),
17
+ index: "dataset",
18
+ qc,
19
+ fetcherFn: cb
20
+ }, (data) => {
21
+ const v = toValue(data);
22
+ return {
23
+ foobar: computed(() => `${v?.foo}${v?.bar}`),
24
+ barfoo: computed(() => `${v?.bar}${v?.foo}`),
25
+ nono: 123
26
+ };
27
+ });
28
+ return useSearch;
29
+ }
30
+ describe("useSearchFactory", () => {
31
+ const fetcherSpy = vi.fn((_) => {
32
+ const mockResult = {
33
+ result: {
34
+ count: 1e3,
35
+ facets: [],
36
+ index: "dataset",
37
+ results: [{ foo: "test", bar: 123 }, { foo: "test2", bar: 456 }]
38
+ }
39
+ };
40
+ return Promise.resolve(mockResult);
41
+ });
42
+ let useSearch = {};
43
+ beforeEach(() => {
44
+ vi.clearAllMocks();
45
+ const qc = new QueryClient(defaultQueryClientConfig);
46
+ useSearch = createUseSearch(qc, fetcherSpy);
47
+ });
48
+ it("should return a function", async () => {
49
+ expect(useSearch).toBeTypeOf("function");
50
+ });
51
+ it("should call fetcherFn", async () => {
52
+ const scope = effectScope(true);
53
+ const qExpected = "query";
54
+ const limitExpected = 123;
55
+ const headerExpected = {
56
+ foo: "bar"
57
+ };
58
+ const q = ref(qExpected);
59
+ const limit = ref(limitExpected);
60
+ const headers = ref(headerExpected);
61
+ const count = ref(-1);
62
+ const results = ref([]);
63
+ await scope.run(async () => {
64
+ const { getSearchResultsCount, getSearchResultsEnhanced } = useSearch({
65
+ queryParams: {
66
+ q,
67
+ limit
68
+ },
69
+ headers
70
+ });
71
+ watchOnce(() => getSearchResultsCount.value, (_count) => {
72
+ count.value = _count;
73
+ if (getSearchResultsEnhanced.value) {
74
+ results.value = getSearchResultsEnhanced.value;
75
+ }
76
+ });
77
+ });
78
+ await until(() => count.value !== -1).toBe(true);
79
+ expect(fetcherSpy).toHaveBeenCalledTimes(1);
80
+ expect(fetcherSpy.mock.calls[0]?.[0].params.q).toBe(qExpected);
81
+ expect(fetcherSpy.mock.calls[0]?.[0].params.limit).toBe(limitExpected);
82
+ expect(fetcherSpy.mock.calls[0]?.[0].params.facets).toEqual({});
83
+ expect(fetcherSpy.mock.calls[0]?.[0].headers.foo).toBe("bar");
84
+ expect(results.value).toHaveLength(2);
85
+ expect(results.value[0].foobar).toBe("test123");
86
+ expect(results.value[0].barfoo).toBe("123test");
87
+ expect(results.value[1].foobar).toBe("test2456");
88
+ expect(results.value[1].barfoo).toBe("456test2");
89
+ q.value = "foo";
90
+ q.value = "new query";
91
+ limit.value = 456;
92
+ headers.value = {
93
+ foo: "baz"
94
+ };
95
+ await nextTick();
96
+ expect(fetcherSpy).toHaveBeenCalledTimes(2);
97
+ expect(fetcherSpy.mock.calls[1]?.[0].params.q).toBe("new query");
98
+ expect(fetcherSpy.mock.calls[1]?.[0].params.limit).toBe(456);
99
+ expect(fetcherSpy.mock.calls[1]?.[0].params.facets).toEqual({});
100
+ expect(fetcherSpy.mock.calls[1]?.[0].headers.foo).toBe("baz");
101
+ });
102
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,89 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { reactive, ref } from "vue-demi";
3
+ import { useSearchQueryParams } from "../useSearchQueryParams.js";
4
+ describe("useSearchQueryParams", () => {
5
+ it("should provide queryParams", () => {
6
+ const { queryParams } = useSearchQueryParams();
7
+ expect(queryParams).toBeDefined();
8
+ expect(reactive(queryParams)).toStrictEqual({
9
+ aggregation: null,
10
+ aggregationAllFields: null,
11
+ aggregationFields: null,
12
+ autocomplete: null,
13
+ bboxMaxLat: null,
14
+ bboxMaxLon: null,
15
+ bboxMinLat: null,
16
+ bboxMinLon: null,
17
+ boost: null,
18
+ countryData: null,
19
+ dataServices: null,
20
+ facetGroupOperator: null,
21
+ facetOperator: null,
22
+ fields: null,
23
+ filterDistributions: null,
24
+ globalAggregation: null,
25
+ includes: null,
26
+ limit: null,
27
+ maxDate: null,
28
+ minDate: null,
29
+ maxScoring: null,
30
+ minScoring: null,
31
+ page: null,
32
+ q: null,
33
+ scroll: null,
34
+ sort: null,
35
+ showScore: null,
36
+ vocabulary: null,
37
+ superCatalogue: null
38
+ });
39
+ });
40
+ it("should reactively update queryParams when using setters", () => {
41
+ const {
42
+ queryParams,
43
+ setFacetOperator,
44
+ setDataScope,
45
+ setDataServices,
46
+ setSuperCatalogue,
47
+ setDatasetGeoBounds,
48
+ setFacetGroupOperator,
49
+ setLimit,
50
+ setMinScoring,
51
+ setPage,
52
+ setQuery,
53
+ setSort
54
+ } = useSearchQueryParams();
55
+ setFacetOperator("AND");
56
+ setDataScope(true);
57
+ setDataServices(false);
58
+ setSuperCatalogue("test");
59
+ setDatasetGeoBounds({ minLon: 1, maxLon: 2, minLat: 3, maxLat: 4 });
60
+ setFacetGroupOperator("OR");
61
+ setLimit(10);
62
+ setMinScoring(0.5);
63
+ setPage(1);
64
+ setQuery("test");
65
+ setSort("title+asc");
66
+ expect(queryParams.facetOperator.value).toBe("AND");
67
+ expect(queryParams.countryData.value).toBe(true);
68
+ expect(queryParams.dataServices.value).toBe(false);
69
+ expect(queryParams.superCatalogue.value).toBe("test");
70
+ expect(queryParams.bboxMinLon.value).toBe(1);
71
+ expect(queryParams.bboxMaxLon.value).toBe(2);
72
+ expect(queryParams.bboxMinLat.value).toBe(3);
73
+ expect(queryParams.bboxMaxLat.value).toBe(4);
74
+ expect(queryParams.facetGroupOperator.value).toBe("OR");
75
+ expect(queryParams.limit.value).toBe(10);
76
+ expect(queryParams.minScoring.value).toBe(0.5);
77
+ expect(queryParams.page.value).toBe(1);
78
+ expect(queryParams.q.value).toBe("test");
79
+ expect(queryParams.sort.value).toBe("title+asc");
80
+ });
81
+ it("should reactively update queryParams when updating reactive params", () => {
82
+ const facetOperator = ref("AND");
83
+ const { queryParams } = useSearchQueryParams({
84
+ facetOperator
85
+ });
86
+ facetOperator.value = "OR";
87
+ expect(queryParams.facetOperator.value).toBe("OR");
88
+ });
89
+ });
@@ -0,0 +1,27 @@
1
+ import type { InjectionKey, MaybeRefOrGetter } from 'vue-demi';
2
+ export interface LocaleMessages {
3
+ [key: string]: LocaleMessages | string;
4
+ }
5
+ export type DateFormats = 'short' | 'medium' | 'long';
6
+ export type DateLike = Date | string | number;
7
+ export type DateFormatStrings = {
8
+ [key in DateFormats]?: string;
9
+ };
10
+ export interface LocaleInstance {
11
+ name: string;
12
+ messages: MaybeRefOrGetter<LocaleMessages>;
13
+ currentLocale: MaybeRefOrGetter<string>;
14
+ fallbackLocale: MaybeRefOrGetter<string>;
15
+ t: (key: string, ...params: unknown[]) => string;
16
+ n: (value: number) => string;
17
+ d: (value: DateLike, format?: DateFormats, locale?: Intl.LocalesArgument) => string;
18
+ }
19
+ export interface LocaleOptions {
20
+ messages?: LocaleMessages;
21
+ locale?: string;
22
+ fallback?: string;
23
+ dateFormatStrings?: DateFormatStrings;
24
+ adapter?: LocaleInstance;
25
+ }
26
+ export declare const localeKey: InjectionKey<LocaleInstance>;
27
+ export declare function useLocale(): LocaleInstance;
@@ -0,0 +1,8 @@
1
+ import { inject } from "vue-demi";
2
+ export const localeKey = Symbol("locale");
3
+ export function useLocale() {
4
+ const locale = inject(localeKey);
5
+ if (!locale)
6
+ throw new Error("[piveau-kit] Could not inject locale instance. Did you forget to install the `@piveau/sdk-vue` plugin?");
7
+ return locale;
8
+ }
@@ -0,0 +1 @@
1
+ export declare function usePropertyTable(): void;
@@ -0,0 +1,2 @@
1
+ export function usePropertyTable() {
2
+ }
@@ -0,0 +1,37 @@
1
+ import type { SearchParamsBase, SearchResult } from '@piveau/sdk-core';
2
+ import type { ComputedRef, MaybeRefOrGetter, Ref } from 'vue-demi';
3
+ import type * as z from 'zod';
4
+ import type { QueryClient } from '@tanstack/vue-query';
5
+ export interface DefineHubSearchOptions<TIndex extends string, TFacetNames extends string, TModelSchema> {
6
+ baseUrl: string;
7
+ index: TIndex;
8
+ indexDetails?: string;
9
+ enabled?: MaybeRefOrGetter<boolean>;
10
+ schema: z.Schema<TModelSchema>;
11
+ facets?: TFacetNames[];
12
+ defaultOptions?: {
13
+ dateFormatter?: (datetime: string) => string;
14
+ locale?: MaybeRefOrGetter<string>;
15
+ searchFetcherFn?: () => Promise<SearchResult<TModelSchema>>;
16
+ resourceFetcherFn?: () => Promise<SearchResult<TModelSchema>>;
17
+ qc?: QueryClient;
18
+ };
19
+ }
20
+ export type _ExtractComputedRefsFromSetup<TSetup> = {
21
+ [K in keyof TSetup as TSetup[K] extends ComputedRef ? K : never]: TSetup[K];
22
+ };
23
+ export type _ExtractComputedRefsFromSetupUnrwapped<TSetup> = TSetup extends _ExtractComputedRefsFromSetup<TSetup> ? {
24
+ [K in keyof _ExtractComputedRefsFromSetup<TSetup>]: TSetup[K] extends ComputedRef<infer t> ? t : never;
25
+ } : never;
26
+ export declare function defineHubSearch<TIndex extends string, TFacetNames extends string, TModelSchema, TSetup extends object>(options: DefineHubSearchOptions<TIndex, TFacetNames, TModelSchema>, setup?: (data: MaybeRefOrGetter<TModelSchema | undefined>, ctx?: DefineHubSearchOptions<TIndex, TFacetNames, TModelSchema>) => TSetup): {
27
+ useSearch: (params: import("./useSearchFactory.js").UseSearchParams<TFacetNames>) => import("./useSearchFactory.js").UseSearchFactoryReturn<TFacetNames, TModelSchema, TSetup>;
28
+ useResource: import("./useResourceFactory.js").UseResourceFunction<TSetup, TModelSchema | undefined>;
29
+ refSyncedWithRouteQuery: <T extends string | number, K = T extends string ? string : T extends number ? number : never>(searchParam: keyof SearchParamsBase, defaultValue?: MaybeRefOrGetter<T> | undefined) => Ref<K>;
30
+ refSyncedWithRouteQueryFacet: <T_1 extends string[]>(searchParam: TFacetNames, defaultValue?: MaybeRefOrGetter<T_1> | undefined) => Ref<string[]>;
31
+ setup: ((data: MaybeRefOrGetter<TModelSchema | undefined>, ctx?: DefineHubSearchOptions<TIndex, TFacetNames, TModelSchema>) => TSetup) | undefined;
32
+ };
33
+ export type HubSearchIntegrationOptions<TModelSchema> = DefineHubSearchOptions<string, string, TModelSchema>;
34
+ export declare function defineHubSearchIntegration<TModelSchema, TSetup>(schema: z.Schema<TModelSchema>, setup: (data: MaybeRefOrGetter<TModelSchema | undefined>, ctx?: HubSearchIntegrationOptions<TModelSchema>) => TSetup): {
35
+ setup: (data: MaybeRefOrGetter<TModelSchema | undefined>, ctx?: HubSearchIntegrationOptions<TModelSchema>) => TSetup;
36
+ schema: z.ZodType<TModelSchema, z.ZodTypeDef, TModelSchema>;
37
+ };