@hf-chimera/vue 0.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.
package/README.md ADDED
@@ -0,0 +1,235 @@
1
+ # ChimeraEntityStore Vue Integration
2
+
3
+ This package provides Vue 3 composables for seamless integration with ChimeraEntityStore, enabling fully reactive data queries in Vue applications.
4
+
5
+ ## Features
6
+
7
+ - **Vue Composables**: Use `useChimeraCollection` and `useChimeraItem` with the Composition API
8
+ - **TypeScript Support**: Strong typing for entities, queries, and repositories
9
+ - **Automatic Reactivity**: Components update automatically on data, status, and error changes
10
+ - **Query Builder Support**: Fluent query builder function for strong types and readability
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ # Install both the core store and Vue adapter
16
+ npm install @hf-chimera/store @hf-chimera/vue
17
+
18
+ # Vue is a peer dependency
19
+ npm install vue
20
+
21
+ # Or install all at once
22
+ npm install @hf-chimera/store @hf-chimera/vue vue
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ ### For Vue Applications
28
+
29
+ Import from the Vue-specific entry point:
30
+
31
+ ```ts
32
+ import { createChimeraComposables } from "@hf-chimera/store/vue";
33
+ // In your app, call createChimeraComposables(store) and export the returned composables
34
+ ```
35
+
36
+ ### For Non-Vue Usage
37
+
38
+ Import and use the core store directly:
39
+
40
+ ```ts
41
+ import { createChimeraEntityStore } from "@hf-chimera/store";
42
+ import { createChimeraStoreComposables } from "@hf-chimera/vue";
43
+ ```
44
+
45
+ ## Quick Start
46
+
47
+ ### 1. Prepare composables for the store
48
+
49
+ Use `createChimeraStoreComposables` to create Vue composables bound to your entity store instance.
50
+
51
+ ```ts
52
+ import { createChimeraEntityStore } from "@hf-chimera/store";
53
+ import { createChimeraStoreComposables } from "@hf-chimera/vue";
54
+
55
+ // Define your entity type
56
+ type Customer = {
57
+ id: number;
58
+ name: string;
59
+ email: string;
60
+ };
61
+
62
+ // Create your entity store instance
63
+ const customerStore = createChimeraEntityStore<"customer", Customer>({
64
+ name: "customer",
65
+ idGetter: "id",
66
+ async collectionFetcher(params, requestParams) {
67
+ const response = await fetch("/api/customers", {
68
+ method: "POST",
69
+ headers: { "Content-Type": "application/json" },
70
+ body: JSON.stringify({ filter: params.filter, order: params.order }),
71
+ signal: requestParams.signal,
72
+ });
73
+ return { data: await response.json() };
74
+ },
75
+ async itemFetcher(params, requestParams) {
76
+ const response = await fetch(`/api/customers/${params.id}`, {
77
+ signal: requestParams.signal,
78
+ });
79
+ return { data: await response.json() };
80
+ },
81
+ // ... other CRUD operations
82
+ });
83
+
84
+ // Create composables bound to your customer store
85
+ // This generates: useChimeraCustomerStore, useChimeraCustomerCollection, useChimeraCustomerItem
86
+ export const {
87
+ useChimeraCustomerStore,
88
+ useChimeraCustomerCollection,
89
+ useChimeraCustomerItem,
90
+ } = createChimeraStoreComposables(customerStore);
91
+ ```
92
+
93
+ ### 2. Use Collection Queries in a component
94
+
95
+ `useChimeraCustomerCollection` returns a Vue `Ref` to a `ChimeraCollectionQuery`. In `<template>`, refs are auto-unwrapped. In `<script setup>`, access via `.value`.
96
+
97
+ ```vue
98
+ <script setup lang="ts">
99
+ import { useChimeraCustomerCollection } from "@/store/chimera";
100
+
101
+ const customers = useChimeraCustomerCollection({
102
+ filter: { status: "active" },
103
+ order: [{ field: "name", direction: "asc" }],
104
+ });
105
+
106
+ function addCustomer() {
107
+ customers.value.create({ name: "New Customer" });
108
+ }
109
+ </script>
110
+
111
+ <template>
112
+ <div>
113
+ <div v-if="!customers.ready">Loading...</div>
114
+ <div v-else-if="customers.lastError">
115
+ Error: {{ String(customers.lastError) }}
116
+ </div>
117
+ <template v-else>
118
+ <div v-for="c in customers" :key="c.id">
119
+ {{ c.name }}
120
+ <button @click="customers.delete(c.id)">Delete</button>
121
+ </div>
122
+ <button @click="addCustomer">Add Customer</button>
123
+ </template>
124
+ </div>
125
+ </template>
126
+ ```
127
+
128
+ ### 3. Use Item Queries in a component
129
+
130
+ ```vue
131
+ <script setup lang="ts">
132
+ import { useChimeraCustomerItem } from "@/store/chimera";
133
+
134
+ interface Props {
135
+ customerId: string;
136
+ }
137
+ const props = defineProps<Props>();
138
+
139
+ const customer = useChimeraCustomerItem(() => props.customerId);
140
+
141
+ function updateName() {
142
+ if (!customer.value.data) return;
143
+ customer.value.mutable.name = "Updated Name";
144
+ customer.value.commit();
145
+ }
146
+ </script>
147
+
148
+ <template>
149
+ <div>
150
+ <div v-if="!customer.ready">Loading...</div>
151
+ <div v-else-if="customer.lastError">
152
+ Error: {{ String(customer.lastError) }}
153
+ </div>
154
+ <div v-else-if="!customer.data">Customer not found</div>
155
+ <div v-else>
156
+ <h3>{{ customer.data.name }}</h3>
157
+ <button @click="updateName">Update Name</button>
158
+ </div>
159
+ </div>
160
+ </template>
161
+ ```
162
+
163
+ ### 4. Using the Query Builder
164
+
165
+ You can pass a builder function instead of a params object. The composable will call it to build the query.
166
+
167
+ ```ts
168
+ import { useChimeraCollection } from "@/store/chimera";
169
+
170
+ const activeUsers = useChimeraCollection("customer", (q) => {
171
+ q.where("email", "contains", "@example.com").orderBy("createdAt", true);
172
+ });
173
+ ```
174
+
175
+ Complex example with groups:
176
+
177
+ ```ts
178
+ const featuredOrders = useChimeraCollection("order", (q) => {
179
+ q.where("status", "eq", "completed")
180
+ // Must be either high value OR from VIP customer
181
+ .group("or", (group) => {
182
+ group
183
+ .where("totalAmount", "gte", 1000)
184
+ .where("customerId", "in", [1, 2, 3]);
185
+ })
186
+ // But not cancelled
187
+ .whereNot("status", "eq", "cancelled")
188
+ .orderBy("totalAmount", true);
189
+ });
190
+ ```
191
+
192
+ For more information on the query builder, see the [ChimeraQueryBuilder documentation](../../qb/README.md).
193
+
194
+ ## API Reference
195
+
196
+ ### Composables
197
+
198
+ #### `useChimeraCustomerCollection<Meta>(params)`
199
+
200
+ Composable for collection queries with automatic reactivity.
201
+
202
+ Parameters:
203
+
204
+ - `entityName: EntityName` — Entity name
205
+ - `params: ChimeraCollectionParams | QueryBuilderCreator | Ref | Getter` — Query params or builder; can be a value, a `ref`, or a function getter
206
+
207
+ Returns: `Ref<ChimeraCollectionQuery<Item, OperatorsMap>>` — see [ChimeraCollectionQuery](../../../README.md#chimeracollectionquery)
208
+
209
+ #### `useChimeraItem<EntityName, Meta>(entityName, id, meta?)`
210
+
211
+ Composable for single item queries with automatic reactivity.
212
+
213
+ Parameters:
214
+
215
+ - `entityName: EntityName` — Entity name
216
+ - `id: ChimeraEntityId | Ref | Getter` — Item ID (can be reactive)
217
+ - `meta?: Meta | Ref | Getter` — Optional metadata (can be reactive)
218
+
219
+ Returns: `Ref<ChimeraItemQuery<Item>>` — see [ChimeraItemQuery](../../../README.md#chimeraitemquery)
220
+
221
+ ## Vue-specific Notes
222
+
223
+ - All composables return Vue `Ref`s. In `<template>`, refs are automatically unwrapped; in `<script>`, access via `.value`.
224
+ - Subscribes internally to store events and triggers updates on:
225
+ - Collections: `ready`, `updated`, `selfUpdated`, `selfItemCreated`, `itemAdded`, `itemUpdated`, `selfItemUpdated`, `itemDeleted`, `selfItemDeleted`, `error`.
226
+ - Items: `initialized`, `selfCreated`, `ready`, `updated`, `selfUpdated`, `deleted`, `selfDeleted`, `error`.
227
+ - You can pass reactive inputs (refs or getters) to `entityName`, `params`, `id`, and `meta`. The composables will react to changes automatically.
228
+
229
+ ## Tips
230
+
231
+ 1. **Type Safety**: Consider exposing a typed facade (e.g., `getChimeraTypedComposables`) in your project for strict types.
232
+ 2. **Error Handling**: Always check `ready` and `lastError` before rendering critical UI.
233
+ 3. **Optimistic Updates**: Use the `mutable` object on item queries and call `commit()`.
234
+ 4. **Batch Operations**: Prefer collection-level operations when possible.
235
+ 5. **Query Builder**: Prefer the builder function for complex filtering and ordering with strong types.
package/dist/index.cjs ADDED
@@ -0,0 +1,44 @@
1
+ let _hf_chimera_adapters_shared = require("@hf-chimera/adapters-shared");
2
+ let _hf_chimera_query_builder = require("@hf-chimera/query-builder");
3
+ let vue = require("vue");
4
+
5
+ //#region composables.ts
6
+ const isFunction = (value) => typeof value === "function";
7
+ const toValue = (value) => isFunction(value) ? value() : (0, vue.isRef)(value) ? value.value : value;
8
+ const capitalize = (s) => s !== "" ? s[0].toUpperCase() + s.slice(1) : "";
9
+ const createEmitterRef = (value, events, name) => (0, vue.customRef)((track, trigger) => {
10
+ (0, vue.watch)(value, (value$1, _, onCleanup) => {
11
+ const actualValue = toValue(value$1);
12
+ const handler = () => trigger();
13
+ events.forEach((event) => {
14
+ actualValue.on(event, handler);
15
+ });
16
+ onCleanup(() => events.forEach((event) => {
17
+ actualValue.off(event, handler);
18
+ }));
19
+ }, { immediate: true });
20
+ return {
21
+ get() {
22
+ track();
23
+ return toValue(value);
24
+ },
25
+ set() {
26
+ console.warn(`${name} ref is readonly`);
27
+ }
28
+ };
29
+ });
30
+ function createChimeraStoreComposables(store, createQueryBuilder) {
31
+ createQueryBuilder ||= () => new _hf_chimera_query_builder.DefaultChimeraQueryBuilder();
32
+ return {
33
+ [`useChimera${capitalize(store.name)}Store`]: () => createEmitterRef(store, _hf_chimera_adapters_shared.CHIMERA_ENTITY_STORE_UPDATE_EVENTS, "ChimeraEntityStore"),
34
+ [`useChimera${capitalize(store.name)}Collection`]: (params) => {
35
+ const normalizedParams = (0, vue.computed)(() => (0, _hf_chimera_adapters_shared.normalizeParams)(createQueryBuilder, toValue(params)));
36
+ return createEmitterRef((0, vue.computed)(() => store.getCollection(normalizedParams.value)), _hf_chimera_adapters_shared.CHIMERA_COLLECTION_UPDATE_EVENTS, "ChimeraCollectionQuery");
37
+ },
38
+ [`useChimera${capitalize(store.name)}Item`]: (id, meta) => createEmitterRef((0, vue.computed)(() => store.getItem(toValue(id), toValue(meta))), _hf_chimera_adapters_shared.CHIMERA_ITEM_UPDATE_EVENTS, "ChimeraItemQuery")
39
+ };
40
+ }
41
+
42
+ //#endregion
43
+ exports.createChimeraStoreComposables = createChimeraStoreComposables;
44
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["value","DefaultChimeraQueryBuilder","CHIMERA_ENTITY_STORE_UPDATE_EVENTS","CHIMERA_COLLECTION_UPDATE_EVENTS","CHIMERA_ITEM_UPDATE_EVENTS"],"sources":["../composables.ts"],"sourcesContent":["import {\n\ttype AnyChimeraParams,\n\tCHIMERA_COLLECTION_UPDATE_EVENTS,\n\tCHIMERA_ENTITY_STORE_UPDATE_EVENTS,\n\tCHIMERA_ITEM_UPDATE_EVENTS,\n\tnormalizeParams,\n} from \"@hf-chimera/adapters-shared\";\nimport type { ChimeraQueryBuilder } from \"@hf-chimera/query-builder\";\nimport { DefaultChimeraQueryBuilder } from \"@hf-chimera/query-builder\";\nimport type {\n\tAnyChimeraEntityStore,\n\tAnyChimeraEventEmitter,\n\tChimeraCollectionQuery,\n\tChimeraEntityId,\n\tChimeraEntityStoreEntity,\n\tChimeraEntityStoreName,\n\tChimeraEntityStoreOperatorsMap,\n\tChimeraEventEmitterEventNames,\n\tChimeraItemQuery,\n} from \"@hf-chimera/store\";\nimport { computed, customRef, isRef, type Ref, watch } from \"vue\";\n\ntype MaybeRef<T> = T | Ref<T>;\ntype MaybeRefOrGetter<T> = MaybeRef<T> | (() => T);\n\ntype ChimeraComposables<\n\tTStore extends AnyChimeraEntityStore,\n\tTQueryBuilder extends ChimeraQueryBuilder<TStore>,\n\tTEntityName extends ChimeraEntityStoreName<TStore> = ChimeraEntityStoreName<TStore>,\n> = {\n\t[K in TEntityName as `useChimera${Capitalize<K>}Store`]: () => Ref<TStore>;\n} & {\n\t[K in TEntityName as `useChimera${Capitalize<K>}Collection`]: <TMeta = any>(\n\t\tparams: MaybeRefOrGetter<AnyChimeraParams<TStore, TMeta, Extract<TQueryBuilder, ChimeraQueryBuilder<TStore>>>>,\n\t) => Ref<\n\t\tChimeraCollectionQuery<\n\t\t\tChimeraEntityStoreName<TStore>,\n\t\t\tChimeraEntityStoreEntity<TStore>,\n\t\t\tChimeraEntityStoreOperatorsMap<TStore>\n\t\t>\n\t>;\n} & {\n\t[K in TEntityName as `useChimera${Capitalize<K>}Item`]: <TMeta = any>(\n\t\tid: MaybeRefOrGetter<ChimeraEntityId>,\n\t\tmeta?: MaybeRefOrGetter<TMeta>,\n\t) => Ref<ChimeraItemQuery<ChimeraEntityStoreName<TStore>, ChimeraEntityStoreEntity<TStore>>>;\n};\n\nconst isFunction = (value: any): value is () => any => typeof value === \"function\";\nconst toValue = <T>(value: MaybeRefOrGetter<T>): T =>\n\tisFunction(value) ? value() : isRef(value) ? value.value : value;\nconst capitalize = <T extends string>(s: T): Capitalize<T> =>\n\ts !== \"\" ? (((s[0] as string).toUpperCase() + s.slice(1)) as Capitalize<T>) : (\"\" as Capitalize<T>);\n\nconst createEmitterRef = <TEventEmitter extends AnyChimeraEventEmitter>(\n\tvalue: MaybeRefOrGetter<TEventEmitter>,\n\tevents: ChimeraEventEmitterEventNames<TEventEmitter>[],\n\tname: string,\n) =>\n\tcustomRef((track, trigger) => {\n\t\twatch(\n\t\t\tvalue,\n\t\t\t(value, _, onCleanup) => {\n\t\t\t\tconst actualValue = toValue(value);\n\n\t\t\t\tconst handler = () => trigger();\n\t\t\t\tevents.forEach((event) => {\n\t\t\t\t\tactualValue.on(event, handler);\n\t\t\t\t});\n\t\t\t\tonCleanup(() =>\n\t\t\t\t\tevents.forEach((event) => {\n\t\t\t\t\t\tactualValue.off(event, handler);\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t},\n\t\t\t{ immediate: true },\n\t\t);\n\n\t\treturn {\n\t\t\tget() {\n\t\t\t\ttrack();\n\t\t\t\treturn toValue(value);\n\t\t\t},\n\t\t\tset() {\n\t\t\t\tconsole.warn(`${name} ref is readonly`);\n\t\t\t},\n\t\t};\n\t});\n\nexport function createChimeraStoreComposables<TStore extends AnyChimeraEntityStore>(\n\tstore: TStore,\n): ChimeraComposables<TStore, DefaultChimeraQueryBuilder<TStore>>;\nexport function createChimeraStoreComposables<\n\tTStore extends AnyChimeraEntityStore,\n\tTQueryBuilder extends ChimeraQueryBuilder<TStore>,\n>(store: TStore, createQueryBuilder: () => TQueryBuilder): ChimeraComposables<TStore, TQueryBuilder>;\nexport function createChimeraStoreComposables<\n\tTStore extends AnyChimeraEntityStore,\n\tTQueryBuilder extends ChimeraQueryBuilder<TStore>,\n>(store: TStore, createQueryBuilder?: () => TQueryBuilder): ChimeraComposables<TStore, TQueryBuilder> {\n\tcreateQueryBuilder ||= () => new DefaultChimeraQueryBuilder() as unknown as TQueryBuilder;\n\n\treturn {\n\t\t[`useChimera${capitalize(store.name)}Store`]: () =>\n\t\t\tcreateEmitterRef(store, CHIMERA_ENTITY_STORE_UPDATE_EVENTS, \"ChimeraEntityStore\"),\n\t\t[`useChimera${capitalize(store.name)}Collection`]: <TMeta = any>(\n\t\t\tparams: MaybeRefOrGetter<AnyChimeraParams<TStore, TMeta, Extract<TQueryBuilder, ChimeraQueryBuilder<TStore>>>>,\n\t\t): Ref<\n\t\t\tChimeraCollectionQuery<\n\t\t\t\tChimeraEntityStoreName<TStore>,\n\t\t\t\tChimeraEntityStoreEntity<TStore>,\n\t\t\t\tChimeraEntityStoreOperatorsMap<TStore>\n\t\t\t>\n\t\t> => {\n\t\t\tconst normalizedParams = computed(() => normalizeParams(createQueryBuilder, toValue(params)));\n\t\t\treturn createEmitterRef(\n\t\t\t\tcomputed(() => store.getCollection(normalizedParams.value)),\n\t\t\t\tCHIMERA_COLLECTION_UPDATE_EVENTS,\n\t\t\t\t\"ChimeraCollectionQuery\",\n\t\t\t);\n\t\t},\n\t\t[`useChimera${capitalize(store.name)}Item`]: <TMeta = any>(\n\t\t\tid: MaybeRefOrGetter<ChimeraEntityId>,\n\t\t\tmeta?: MaybeRefOrGetter<TMeta>,\n\t\t): Ref<ChimeraItemQuery<ChimeraEntityStoreName<TStore>, ChimeraEntityStoreEntity<TStore>>> =>\n\t\t\tcreateEmitterRef(\n\t\t\t\tcomputed(() => store.getItem(toValue(id), toValue(meta))),\n\t\t\t\tCHIMERA_ITEM_UPDATE_EVENTS,\n\t\t\t\t\"ChimeraItemQuery\",\n\t\t\t),\n\t} as ChimeraComposables<TStore, TQueryBuilder>;\n}\n"],"mappings":";;;;;AAgDA,MAAM,cAAc,UAAmC,OAAO,UAAU;AACxE,MAAM,WAAc,UACnB,WAAW,MAAM,GAAG,OAAO,kBAAS,MAAM,GAAG,MAAM,QAAQ;AAC5D,MAAM,cAAgC,MACrC,MAAM,KAAQ,EAAE,GAAc,aAAa,GAAG,EAAE,MAAM,EAAE,GAAuB;AAEhF,MAAM,oBACL,OACA,QACA,6BAEW,OAAO,YAAY;AAC7B,gBACC,QACC,SAAO,GAAG,cAAc;EACxB,MAAM,cAAc,QAAQA,QAAM;EAElC,MAAM,gBAAgB,SAAS;AAC/B,SAAO,SAAS,UAAU;AACzB,eAAY,GAAG,OAAO,QAAQ;IAC7B;AACF,kBACC,OAAO,SAAS,UAAU;AACzB,eAAY,IAAI,OAAO,QAAQ;IAC9B,CACF;IAEF,EAAE,WAAW,MAAM,CACnB;AAED,QAAO;EACN,MAAM;AACL,UAAO;AACP,UAAO,QAAQ,MAAM;;EAEtB,MAAM;AACL,WAAQ,KAAK,GAAG,KAAK,kBAAkB;;EAExC;EACA;AASH,SAAgB,8BAGd,OAAe,oBAAqF;AACrG,8BAA6B,IAAIC,sDAA4B;AAE7D,QAAO;GACL,aAAa,WAAW,MAAM,KAAK,CAAC,eACpC,iBAAiB,OAAOC,gEAAoC,qBAAqB;GACjF,aAAa,WAAW,MAAM,KAAK,CAAC,eACpC,WAOI;GACJ,MAAM,4FAAkD,oBAAoB,QAAQ,OAAO,CAAC,CAAC;AAC7F,UAAO,yCACS,MAAM,cAAc,iBAAiB,MAAM,CAAC,EAC3DC,8DACA,yBACA;;GAED,aAAa,WAAW,MAAM,KAAK,CAAC,SACpC,IACA,SAEA,yCACgB,MAAM,QAAQ,QAAQ,GAAG,EAAE,QAAQ,KAAK,CAAC,CAAC,EACzDC,wDACA,mBACA;EACF"}
@@ -0,0 +1,14 @@
1
+ import { AnyChimeraParams } from "@hf-chimera/adapters-shared";
2
+ import { ChimeraQueryBuilder, DefaultChimeraQueryBuilder } from "@hf-chimera/query-builder";
3
+ import { AnyChimeraEntityStore, ChimeraCollectionQuery, ChimeraEntityId, ChimeraEntityStoreEntity, ChimeraEntityStoreName, ChimeraEntityStoreOperatorsMap, ChimeraItemQuery } from "@hf-chimera/store";
4
+ import { Ref } from "vue";
5
+
6
+ //#region composables.d.ts
7
+ type MaybeRef<T> = T | Ref<T>;
8
+ type MaybeRefOrGetter<T> = MaybeRef<T> | (() => T);
9
+ type ChimeraComposables<TStore extends AnyChimeraEntityStore, TQueryBuilder extends ChimeraQueryBuilder<TStore>, TEntityName extends ChimeraEntityStoreName<TStore> = ChimeraEntityStoreName<TStore>> = { [K in TEntityName as `useChimera${Capitalize<K>}Store`]: () => Ref<TStore> } & { [K in TEntityName as `useChimera${Capitalize<K>}Collection`]: <TMeta = any>(params: MaybeRefOrGetter<AnyChimeraParams<TStore, TMeta, Extract<TQueryBuilder, ChimeraQueryBuilder<TStore>>>>) => Ref<ChimeraCollectionQuery<ChimeraEntityStoreName<TStore>, ChimeraEntityStoreEntity<TStore>, ChimeraEntityStoreOperatorsMap<TStore>>> } & { [K in TEntityName as `useChimera${Capitalize<K>}Item`]: <TMeta = any>(id: MaybeRefOrGetter<ChimeraEntityId>, meta?: MaybeRefOrGetter<TMeta>) => Ref<ChimeraItemQuery<ChimeraEntityStoreName<TStore>, ChimeraEntityStoreEntity<TStore>>> };
10
+ declare function createChimeraStoreComposables<TStore extends AnyChimeraEntityStore>(store: TStore): ChimeraComposables<TStore, DefaultChimeraQueryBuilder<TStore>>;
11
+ declare function createChimeraStoreComposables<TStore extends AnyChimeraEntityStore, TQueryBuilder extends ChimeraQueryBuilder<TStore>>(store: TStore, createQueryBuilder: () => TQueryBuilder): ChimeraComposables<TStore, TQueryBuilder>;
12
+ //#endregion
13
+ export { createChimeraStoreComposables };
14
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../composables.ts"],"sourcesContent":[],"mappings":";;;;;;KAsBK,cAAc,IAAI,IAAI;AAFuC,KAG7D,gBADQ,CAAA,CAAA,CAAA,GACc,QADd,CACuB,CADvB,CAAA,GAAA,CAAA,GAAA,GACmC,CADnC,CAAA;KAGR,kBAHc,CAAA,eAIH,qBAJG,EAAA,sBAKI,mBALJ,CAKwB,MALxB,CAAA,EAAA,oBAME,sBANF,CAMyB,MANzB,CAAA,GAMmC,sBANnC,CAM0D,MAN1D,CAAA,CAAA,GAAA,QAQZ,WARoB,IAAA,aAQQ,UARR,CAQmB,CARnB,CAAA,OAAA,GAAA,GAAA,GAQqC,GARrC,CAQyC,MARzC,CAAA,EAAJ,GAAA,QAUhB,WAVmB,IAAA,aAUS,UAVT,CAUoB,CAVpB,CAAA,YAAA,GAAA,CAAA,QAAA,GAAA,CAAA,CAAA,MAAA,EAWhB,gBAXgB,CAWC,gBAXD,CAWkB,MAXlB,EAW0B,KAX1B,EAWiC,OAXjC,CAWyC,aAXzC,EAWwD,mBAXxD,CAW4E,MAX5E,CAAA,CAAA,CAAA,CAAA,EAAA,GAYpB,GAZoB,CAaxB,sBAbwB,CAcvB,sBAduB,CAcA,MAdA,CAAA,EAevB,wBAfuB,CAeE,MAfF,CAAA,EAgBvB,8BAhBuB,CAgBQ,MAhBR,CAAA,CAAA,CAAA,EAAA,GACrB,QAmBE,WAnB6B,IAAA,aAmBD,UAnBC,CAmBU,CAnBV,CAAA,MAAA,GAAA,CAAA,QAAA,GAAA,CAAA,CAAA,EAAA,EAoB9B,gBApB8B,CAoBb,eApBa,CAAA,EAAA,IAAA,CAAA,EAqB3B,gBArB2B,CAqBV,KArBU,CAAA,EAAA,GAsB9B,GAtB8B,CAsB1B,gBAtB0B,CAsBT,sBAtBS,CAsBc,MAtBd,CAAA,EAsBuB,wBAtBvB,CAsBgD,MAtBhD,CAAA,CAAA,CAAA,EAAT;AAAqB,iBAkEhC,6BAlEgC,CAAA,eAkEa,qBAlEb,CAAA,CAAA,KAAA,EAmExC,MAnEwC,CAAA,EAoE7C,kBApE6C,CAoE1B,MApE0B,EAoElB,0BApEkB,CAoES,MApET,CAAA,CAAA;AAAC,iBAqEjC,6BArEiC,CAAA,eAsEjC,qBAtEiC,EAAA,sBAuE1B,mBAvE0B,CAuEN,MAvEM,CAAA,CAAA,CAAA,KAAA,EAwExC,MAxEwC,EAAA,kBAAA,EAAA,GAAA,GAwEN,aAxEM,CAAA,EAwEU,kBAxEV,CAwE6B,MAxE7B,EAwEqC,aAxErC,CAAA"}
@@ -0,0 +1,14 @@
1
+ import { AnyChimeraParams } from "@hf-chimera/adapters-shared";
2
+ import { ChimeraQueryBuilder, DefaultChimeraQueryBuilder } from "@hf-chimera/query-builder";
3
+ import { Ref } from "vue";
4
+ import { AnyChimeraEntityStore, ChimeraCollectionQuery, ChimeraEntityId, ChimeraEntityStoreEntity, ChimeraEntityStoreName, ChimeraEntityStoreOperatorsMap, ChimeraItemQuery } from "@hf-chimera/store";
5
+
6
+ //#region composables.d.ts
7
+ type MaybeRef<T> = T | Ref<T>;
8
+ type MaybeRefOrGetter<T> = MaybeRef<T> | (() => T);
9
+ type ChimeraComposables<TStore extends AnyChimeraEntityStore, TQueryBuilder extends ChimeraQueryBuilder<TStore>, TEntityName extends ChimeraEntityStoreName<TStore> = ChimeraEntityStoreName<TStore>> = { [K in TEntityName as `useChimera${Capitalize<K>}Store`]: () => Ref<TStore> } & { [K in TEntityName as `useChimera${Capitalize<K>}Collection`]: <TMeta = any>(params: MaybeRefOrGetter<AnyChimeraParams<TStore, TMeta, Extract<TQueryBuilder, ChimeraQueryBuilder<TStore>>>>) => Ref<ChimeraCollectionQuery<ChimeraEntityStoreName<TStore>, ChimeraEntityStoreEntity<TStore>, ChimeraEntityStoreOperatorsMap<TStore>>> } & { [K in TEntityName as `useChimera${Capitalize<K>}Item`]: <TMeta = any>(id: MaybeRefOrGetter<ChimeraEntityId>, meta?: MaybeRefOrGetter<TMeta>) => Ref<ChimeraItemQuery<ChimeraEntityStoreName<TStore>, ChimeraEntityStoreEntity<TStore>>> };
10
+ declare function createChimeraStoreComposables<TStore extends AnyChimeraEntityStore>(store: TStore): ChimeraComposables<TStore, DefaultChimeraQueryBuilder<TStore>>;
11
+ declare function createChimeraStoreComposables<TStore extends AnyChimeraEntityStore, TQueryBuilder extends ChimeraQueryBuilder<TStore>>(store: TStore, createQueryBuilder: () => TQueryBuilder): ChimeraComposables<TStore, TQueryBuilder>;
12
+ //#endregion
13
+ export { createChimeraStoreComposables };
14
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../composables.ts"],"sourcesContent":[],"mappings":";;;;;;KAsBK,cAAc,IAAI,IAAI;AAFuC,KAG7D,gBADQ,CAAA,CAAA,CAAA,GACc,QADd,CACuB,CADvB,CAAA,GAAA,CAAA,GAAA,GACmC,CADnC,CAAA;KAGR,kBAHc,CAAA,eAIH,qBAJG,EAAA,sBAKI,mBALJ,CAKwB,MALxB,CAAA,EAAA,oBAME,sBANF,CAMyB,MANzB,CAAA,GAMmC,sBANnC,CAM0D,MAN1D,CAAA,CAAA,GAAA,QAQZ,WARoB,IAAA,aAQQ,UARR,CAQmB,CARnB,CAAA,OAAA,GAAA,GAAA,GAQqC,GARrC,CAQyC,MARzC,CAAA,EAAJ,GAAA,QAUhB,WAVmB,IAAA,aAUS,UAVT,CAUoB,CAVpB,CAAA,YAAA,GAAA,CAAA,QAAA,GAAA,CAAA,CAAA,MAAA,EAWhB,gBAXgB,CAWC,gBAXD,CAWkB,MAXlB,EAW0B,KAX1B,EAWiC,OAXjC,CAWyC,aAXzC,EAWwD,mBAXxD,CAW4E,MAX5E,CAAA,CAAA,CAAA,CAAA,EAAA,GAYpB,GAZoB,CAaxB,sBAbwB,CAcvB,sBAduB,CAcA,MAdA,CAAA,EAevB,wBAfuB,CAeE,MAfF,CAAA,EAgBvB,8BAhBuB,CAgBQ,MAhBR,CAAA,CAAA,CAAA,EAAA,GACrB,QAmBE,WAnB6B,IAAA,aAmBD,UAnBC,CAmBU,CAnBV,CAAA,MAAA,GAAA,CAAA,QAAA,GAAA,CAAA,CAAA,EAAA,EAoB9B,gBApB8B,CAoBb,eApBa,CAAA,EAAA,IAAA,CAAA,EAqB3B,gBArB2B,CAqBV,KArBU,CAAA,EAAA,GAsB9B,GAtB8B,CAsB1B,gBAtB0B,CAsBT,sBAtBS,CAsBc,MAtBd,CAAA,EAsBuB,wBAtBvB,CAsBgD,MAtBhD,CAAA,CAAA,CAAA,EAAT;AAAqB,iBAkEhC,6BAlEgC,CAAA,eAkEa,qBAlEb,CAAA,CAAA,KAAA,EAmExC,MAnEwC,CAAA,EAoE7C,kBApE6C,CAoE1B,MApE0B,EAoElB,0BApEkB,CAoES,MApET,CAAA,CAAA;AAAC,iBAqEjC,6BArEiC,CAAA,eAsEjC,qBAtEiC,EAAA,sBAuE1B,mBAvE0B,CAuEN,MAvEM,CAAA,CAAA,CAAA,KAAA,EAwExC,MAxEwC,EAAA,kBAAA,EAAA,GAAA,GAwEN,aAxEM,CAAA,EAwEU,kBAxEV,CAwE6B,MAxE7B,EAwEqC,aAxErC,CAAA"}
package/dist/index.mjs ADDED
@@ -0,0 +1,44 @@
1
+ import { CHIMERA_COLLECTION_UPDATE_EVENTS, CHIMERA_ENTITY_STORE_UPDATE_EVENTS, CHIMERA_ITEM_UPDATE_EVENTS, normalizeParams } from "@hf-chimera/adapters-shared";
2
+ import { DefaultChimeraQueryBuilder } from "@hf-chimera/query-builder";
3
+ import { computed, customRef, isRef, watch } from "vue";
4
+
5
+ //#region composables.ts
6
+ const isFunction = (value) => typeof value === "function";
7
+ const toValue = (value) => isFunction(value) ? value() : isRef(value) ? value.value : value;
8
+ const capitalize = (s) => s !== "" ? s[0].toUpperCase() + s.slice(1) : "";
9
+ const createEmitterRef = (value, events, name) => customRef((track, trigger) => {
10
+ watch(value, (value$1, _, onCleanup) => {
11
+ const actualValue = toValue(value$1);
12
+ const handler = () => trigger();
13
+ events.forEach((event) => {
14
+ actualValue.on(event, handler);
15
+ });
16
+ onCleanup(() => events.forEach((event) => {
17
+ actualValue.off(event, handler);
18
+ }));
19
+ }, { immediate: true });
20
+ return {
21
+ get() {
22
+ track();
23
+ return toValue(value);
24
+ },
25
+ set() {
26
+ console.warn(`${name} ref is readonly`);
27
+ }
28
+ };
29
+ });
30
+ function createChimeraStoreComposables(store, createQueryBuilder) {
31
+ createQueryBuilder ||= () => new DefaultChimeraQueryBuilder();
32
+ return {
33
+ [`useChimera${capitalize(store.name)}Store`]: () => createEmitterRef(store, CHIMERA_ENTITY_STORE_UPDATE_EVENTS, "ChimeraEntityStore"),
34
+ [`useChimera${capitalize(store.name)}Collection`]: (params) => {
35
+ const normalizedParams = computed(() => normalizeParams(createQueryBuilder, toValue(params)));
36
+ return createEmitterRef(computed(() => store.getCollection(normalizedParams.value)), CHIMERA_COLLECTION_UPDATE_EVENTS, "ChimeraCollectionQuery");
37
+ },
38
+ [`useChimera${capitalize(store.name)}Item`]: (id, meta) => createEmitterRef(computed(() => store.getItem(toValue(id), toValue(meta))), CHIMERA_ITEM_UPDATE_EVENTS, "ChimeraItemQuery")
39
+ };
40
+ }
41
+
42
+ //#endregion
43
+ export { createChimeraStoreComposables };
44
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["value"],"sources":["../composables.ts"],"sourcesContent":["import {\n\ttype AnyChimeraParams,\n\tCHIMERA_COLLECTION_UPDATE_EVENTS,\n\tCHIMERA_ENTITY_STORE_UPDATE_EVENTS,\n\tCHIMERA_ITEM_UPDATE_EVENTS,\n\tnormalizeParams,\n} from \"@hf-chimera/adapters-shared\";\nimport type { ChimeraQueryBuilder } from \"@hf-chimera/query-builder\";\nimport { DefaultChimeraQueryBuilder } from \"@hf-chimera/query-builder\";\nimport type {\n\tAnyChimeraEntityStore,\n\tAnyChimeraEventEmitter,\n\tChimeraCollectionQuery,\n\tChimeraEntityId,\n\tChimeraEntityStoreEntity,\n\tChimeraEntityStoreName,\n\tChimeraEntityStoreOperatorsMap,\n\tChimeraEventEmitterEventNames,\n\tChimeraItemQuery,\n} from \"@hf-chimera/store\";\nimport { computed, customRef, isRef, type Ref, watch } from \"vue\";\n\ntype MaybeRef<T> = T | Ref<T>;\ntype MaybeRefOrGetter<T> = MaybeRef<T> | (() => T);\n\ntype ChimeraComposables<\n\tTStore extends AnyChimeraEntityStore,\n\tTQueryBuilder extends ChimeraQueryBuilder<TStore>,\n\tTEntityName extends ChimeraEntityStoreName<TStore> = ChimeraEntityStoreName<TStore>,\n> = {\n\t[K in TEntityName as `useChimera${Capitalize<K>}Store`]: () => Ref<TStore>;\n} & {\n\t[K in TEntityName as `useChimera${Capitalize<K>}Collection`]: <TMeta = any>(\n\t\tparams: MaybeRefOrGetter<AnyChimeraParams<TStore, TMeta, Extract<TQueryBuilder, ChimeraQueryBuilder<TStore>>>>,\n\t) => Ref<\n\t\tChimeraCollectionQuery<\n\t\t\tChimeraEntityStoreName<TStore>,\n\t\t\tChimeraEntityStoreEntity<TStore>,\n\t\t\tChimeraEntityStoreOperatorsMap<TStore>\n\t\t>\n\t>;\n} & {\n\t[K in TEntityName as `useChimera${Capitalize<K>}Item`]: <TMeta = any>(\n\t\tid: MaybeRefOrGetter<ChimeraEntityId>,\n\t\tmeta?: MaybeRefOrGetter<TMeta>,\n\t) => Ref<ChimeraItemQuery<ChimeraEntityStoreName<TStore>, ChimeraEntityStoreEntity<TStore>>>;\n};\n\nconst isFunction = (value: any): value is () => any => typeof value === \"function\";\nconst toValue = <T>(value: MaybeRefOrGetter<T>): T =>\n\tisFunction(value) ? value() : isRef(value) ? value.value : value;\nconst capitalize = <T extends string>(s: T): Capitalize<T> =>\n\ts !== \"\" ? (((s[0] as string).toUpperCase() + s.slice(1)) as Capitalize<T>) : (\"\" as Capitalize<T>);\n\nconst createEmitterRef = <TEventEmitter extends AnyChimeraEventEmitter>(\n\tvalue: MaybeRefOrGetter<TEventEmitter>,\n\tevents: ChimeraEventEmitterEventNames<TEventEmitter>[],\n\tname: string,\n) =>\n\tcustomRef((track, trigger) => {\n\t\twatch(\n\t\t\tvalue,\n\t\t\t(value, _, onCleanup) => {\n\t\t\t\tconst actualValue = toValue(value);\n\n\t\t\t\tconst handler = () => trigger();\n\t\t\t\tevents.forEach((event) => {\n\t\t\t\t\tactualValue.on(event, handler);\n\t\t\t\t});\n\t\t\t\tonCleanup(() =>\n\t\t\t\t\tevents.forEach((event) => {\n\t\t\t\t\t\tactualValue.off(event, handler);\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t},\n\t\t\t{ immediate: true },\n\t\t);\n\n\t\treturn {\n\t\t\tget() {\n\t\t\t\ttrack();\n\t\t\t\treturn toValue(value);\n\t\t\t},\n\t\t\tset() {\n\t\t\t\tconsole.warn(`${name} ref is readonly`);\n\t\t\t},\n\t\t};\n\t});\n\nexport function createChimeraStoreComposables<TStore extends AnyChimeraEntityStore>(\n\tstore: TStore,\n): ChimeraComposables<TStore, DefaultChimeraQueryBuilder<TStore>>;\nexport function createChimeraStoreComposables<\n\tTStore extends AnyChimeraEntityStore,\n\tTQueryBuilder extends ChimeraQueryBuilder<TStore>,\n>(store: TStore, createQueryBuilder: () => TQueryBuilder): ChimeraComposables<TStore, TQueryBuilder>;\nexport function createChimeraStoreComposables<\n\tTStore extends AnyChimeraEntityStore,\n\tTQueryBuilder extends ChimeraQueryBuilder<TStore>,\n>(store: TStore, createQueryBuilder?: () => TQueryBuilder): ChimeraComposables<TStore, TQueryBuilder> {\n\tcreateQueryBuilder ||= () => new DefaultChimeraQueryBuilder() as unknown as TQueryBuilder;\n\n\treturn {\n\t\t[`useChimera${capitalize(store.name)}Store`]: () =>\n\t\t\tcreateEmitterRef(store, CHIMERA_ENTITY_STORE_UPDATE_EVENTS, \"ChimeraEntityStore\"),\n\t\t[`useChimera${capitalize(store.name)}Collection`]: <TMeta = any>(\n\t\t\tparams: MaybeRefOrGetter<AnyChimeraParams<TStore, TMeta, Extract<TQueryBuilder, ChimeraQueryBuilder<TStore>>>>,\n\t\t): Ref<\n\t\t\tChimeraCollectionQuery<\n\t\t\t\tChimeraEntityStoreName<TStore>,\n\t\t\t\tChimeraEntityStoreEntity<TStore>,\n\t\t\t\tChimeraEntityStoreOperatorsMap<TStore>\n\t\t\t>\n\t\t> => {\n\t\t\tconst normalizedParams = computed(() => normalizeParams(createQueryBuilder, toValue(params)));\n\t\t\treturn createEmitterRef(\n\t\t\t\tcomputed(() => store.getCollection(normalizedParams.value)),\n\t\t\t\tCHIMERA_COLLECTION_UPDATE_EVENTS,\n\t\t\t\t\"ChimeraCollectionQuery\",\n\t\t\t);\n\t\t},\n\t\t[`useChimera${capitalize(store.name)}Item`]: <TMeta = any>(\n\t\t\tid: MaybeRefOrGetter<ChimeraEntityId>,\n\t\t\tmeta?: MaybeRefOrGetter<TMeta>,\n\t\t): Ref<ChimeraItemQuery<ChimeraEntityStoreName<TStore>, ChimeraEntityStoreEntity<TStore>>> =>\n\t\t\tcreateEmitterRef(\n\t\t\t\tcomputed(() => store.getItem(toValue(id), toValue(meta))),\n\t\t\t\tCHIMERA_ITEM_UPDATE_EVENTS,\n\t\t\t\t\"ChimeraItemQuery\",\n\t\t\t),\n\t} as ChimeraComposables<TStore, TQueryBuilder>;\n}\n"],"mappings":";;;;;AAgDA,MAAM,cAAc,UAAmC,OAAO,UAAU;AACxE,MAAM,WAAc,UACnB,WAAW,MAAM,GAAG,OAAO,GAAG,MAAM,MAAM,GAAG,MAAM,QAAQ;AAC5D,MAAM,cAAgC,MACrC,MAAM,KAAQ,EAAE,GAAc,aAAa,GAAG,EAAE,MAAM,EAAE,GAAuB;AAEhF,MAAM,oBACL,OACA,QACA,SAEA,WAAW,OAAO,YAAY;AAC7B,OACC,QACC,SAAO,GAAG,cAAc;EACxB,MAAM,cAAc,QAAQA,QAAM;EAElC,MAAM,gBAAgB,SAAS;AAC/B,SAAO,SAAS,UAAU;AACzB,eAAY,GAAG,OAAO,QAAQ;IAC7B;AACF,kBACC,OAAO,SAAS,UAAU;AACzB,eAAY,IAAI,OAAO,QAAQ;IAC9B,CACF;IAEF,EAAE,WAAW,MAAM,CACnB;AAED,QAAO;EACN,MAAM;AACL,UAAO;AACP,UAAO,QAAQ,MAAM;;EAEtB,MAAM;AACL,WAAQ,KAAK,GAAG,KAAK,kBAAkB;;EAExC;EACA;AASH,SAAgB,8BAGd,OAAe,oBAAqF;AACrG,8BAA6B,IAAI,4BAA4B;AAE7D,QAAO;GACL,aAAa,WAAW,MAAM,KAAK,CAAC,eACpC,iBAAiB,OAAO,oCAAoC,qBAAqB;GACjF,aAAa,WAAW,MAAM,KAAK,CAAC,eACpC,WAOI;GACJ,MAAM,mBAAmB,eAAe,gBAAgB,oBAAoB,QAAQ,OAAO,CAAC,CAAC;AAC7F,UAAO,iBACN,eAAe,MAAM,cAAc,iBAAiB,MAAM,CAAC,EAC3D,kCACA,yBACA;;GAED,aAAa,WAAW,MAAM,KAAK,CAAC,SACpC,IACA,SAEA,iBACC,eAAe,MAAM,QAAQ,QAAQ,GAAG,EAAE,QAAQ,KAAK,CAAC,CAAC,EACzD,4BACA,mBACA;EACF"}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@hf-chimera/vue",
3
+ "version": "0.2.0",
4
+ "description": "Cross-end reactivity API - Vue adapter",
5
+ "license": "MIT",
6
+ "author": "hewston",
7
+ "keywords": [
8
+ "reactivity",
9
+ "reactive",
10
+ "vue",
11
+ "composables",
12
+ "typescript",
13
+ "state-management"
14
+ ],
15
+ "type": "module",
16
+ "types": "./dist/index.d.ts",
17
+ "main": "./dist/index.cjs",
18
+ "module": "./dist/index.js",
19
+ "exports": {
20
+ ".": {
21
+ "types": "./dist/index.d.ts",
22
+ "require": "./dist/index.cjs",
23
+ "import": "./dist/index.js"
24
+ }
25
+ },
26
+ "files": [
27
+ "dist"
28
+ ],
29
+ "bugs": {
30
+ "url": "https://github.com/hf-chimera/store/issues"
31
+ },
32
+ "repository": {
33
+ "url": "https://github.com/hf-chimera/store"
34
+ },
35
+ "peerDependencies": {
36
+ "@hf-chimera/store": "workspace:^",
37
+ "@hf-chimera/adapters-shared": "workspace:^",
38
+ "vue": ">=3.0.0"
39
+ },
40
+ "scripts": {
41
+ "build": "tsdown",
42
+ "changeset:patch": "node ../../../scripts/changeset-patch.mjs @hf-chimera/vue"
43
+ },
44
+ "publishConfig": {
45
+ "access": "public",
46
+ "provenance": true
47
+ }
48
+ }