@lyeve-labs/client-vue 0.1.2
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/LICENSE +21 -0
- package/README.md +177 -0
- package/dist/index.cjs +95 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +33 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +68 -0
- package/dist/index.js.map +1 -0
- package/package.json +54 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 LyEve Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# @lyeve/cms-client-vue
|
|
2
|
+
|
|
3
|
+
Vue 3 composables for the LyEve Core. `useQuery`, `useMutation`, and the
|
|
4
|
+
`CmsPlugin` provider. Thin wrapper around `@lyeve/cms-client` using the
|
|
5
|
+
Composition API.
|
|
6
|
+
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
[](https://vuejs.org)
|
|
9
|
+
[](https://www.typescriptlang.org)
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pnpm add @lyeve/cms-client @lyeve/cms-client-vue
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { createApp } from "vue";
|
|
17
|
+
import { CmsPlugin } from "@lyeve/cms-client-vue";
|
|
18
|
+
|
|
19
|
+
const app = createApp(App);
|
|
20
|
+
app.use(CmsPlugin, {
|
|
21
|
+
baseUrl: "https://cms.example.com",
|
|
22
|
+
getHeaders: () => ({ Authorization: `Bearer ${token}` }),
|
|
23
|
+
});
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
One plugin at the root, reactive refs everywhere else. No ceremony.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## What's in the box
|
|
31
|
+
|
|
32
|
+
- **CmsPlugin:** Vue plugin that provides the CMS HTTP client to the entire
|
|
33
|
+
component tree via `inject`/`provide`.
|
|
34
|
+
- **useQuery:** reactive data fetching composable. Returns `data`, `error`,
|
|
35
|
+
`loading` as Vue `Ref`s, plus a `refetch` function.
|
|
36
|
+
- **useMutation:** mutation composable returning `[trigger, loading]`. The
|
|
37
|
+
trigger returns a Promise of the result; `loading` is a `Ref<boolean>`.
|
|
38
|
+
|
|
39
|
+
## Requirements
|
|
40
|
+
|
|
41
|
+
- **Node 20** or newer
|
|
42
|
+
- **Vue 3.0** or newer
|
|
43
|
+
- **[@lyeve/cms-client](https://www.npmjs.com/package/@lyeve/cms-client)** `>=0.1.0`
|
|
44
|
+
|
|
45
|
+
## Install
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pnpm add @lyeve/cms-client @lyeve/cms-client-vue
|
|
49
|
+
# or npm install @lyeve/cms-client @lyeve/cms-client-vue
|
|
50
|
+
# or yarn add @lyeve/cms-client @lyeve/cms-client-vue
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Use
|
|
54
|
+
|
|
55
|
+
### Setup
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import { createApp } from "vue";
|
|
59
|
+
import { CmsPlugin } from "@lyeve/cms-client-vue";
|
|
60
|
+
|
|
61
|
+
const app = createApp(App);
|
|
62
|
+
app.use(CmsPlugin, {
|
|
63
|
+
baseUrl: "https://cms.example.com",
|
|
64
|
+
getHeaders: () => ({
|
|
65
|
+
Authorization: `Bearer ${localStorage.getItem("token")}`,
|
|
66
|
+
}),
|
|
67
|
+
});
|
|
68
|
+
app.mount("#app");
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### useQuery
|
|
72
|
+
|
|
73
|
+
```vue
|
|
74
|
+
<script setup lang="ts">
|
|
75
|
+
import { useQuery } from "@lyeve/cms-client-vue";
|
|
76
|
+
import { getSchemas } from "@lyeve/cms-client-rest";
|
|
77
|
+
|
|
78
|
+
const { data, error, loading, refetch } = useQuery((client) =>
|
|
79
|
+
getSchemas(client),
|
|
80
|
+
);
|
|
81
|
+
</script>
|
|
82
|
+
|
|
83
|
+
<template>
|
|
84
|
+
<div v-if="loading">Loading...</div>
|
|
85
|
+
<div v-else-if="error">{{ error.message }}</div>
|
|
86
|
+
<ul v-else>
|
|
87
|
+
<li v-for="schema in data" :key="schema.id">{{ schema.name }}</li>
|
|
88
|
+
</ul>
|
|
89
|
+
</template>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### useMutation
|
|
93
|
+
|
|
94
|
+
```vue
|
|
95
|
+
<script setup lang="ts">
|
|
96
|
+
import { useMutation } from "@lyeve/cms-client-vue";
|
|
97
|
+
import { deleteContent } from "@lyeve/cms-client-rest";
|
|
98
|
+
|
|
99
|
+
const [remove, removing] = useMutation((client, id: string) =>
|
|
100
|
+
deleteContent(id, client),
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
async function handleDelete(id: string) {
|
|
104
|
+
await remove(id);
|
|
105
|
+
}
|
|
106
|
+
</script>
|
|
107
|
+
|
|
108
|
+
<template>
|
|
109
|
+
<button :disabled="removing" @click="handleDelete('abc-123')">
|
|
110
|
+
{{ removing ? "Deleting..." : "Delete" }}
|
|
111
|
+
</button>
|
|
112
|
+
</template>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## API
|
|
116
|
+
|
|
117
|
+
### CmsPlugin
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
interface VueCmsConfig {
|
|
121
|
+
baseUrl?: string;
|
|
122
|
+
getHeaders?: () => Record<string, string>;
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### useQuery
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
function useQuery<T>(fetcher: (client: HttpClient) => Promise<T>): {
|
|
130
|
+
data: Ref<T | null>;
|
|
131
|
+
error: Ref<Error | null>;
|
|
132
|
+
loading: Ref<boolean>;
|
|
133
|
+
refetch: () => void;
|
|
134
|
+
};
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### useMutation
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
function useMutation<T, V>(
|
|
141
|
+
mutator: (client: HttpClient, vars: V) => Promise<T>,
|
|
142
|
+
): [(vars: V) => Promise<T>, Ref<boolean>];
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Returns a tuple: `[trigger, loading]`.
|
|
146
|
+
|
|
147
|
+
## Local development
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
pnpm install # install dependencies
|
|
151
|
+
pnpm test # run unit tests
|
|
152
|
+
pnpm check # type-check
|
|
153
|
+
pnpm build # tsup + publint -> dist/
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Project layout
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
src/
|
|
160
|
+
index.ts # CmsPlugin, useQuery, useMutation
|
|
161
|
+
tests/ # vitest test suite
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Versioning
|
|
165
|
+
|
|
166
|
+
`@lyeve/cms-client-vue` follows [SemVer](https://semver.org). While under `1.0`,
|
|
167
|
+
breaking changes bump the **minor** version; additive changes bump the **patch**.
|
|
168
|
+
Every release is logged in [`CHANGELOG.md`](CHANGELOG.md).
|
|
169
|
+
|
|
170
|
+
## Contributing
|
|
171
|
+
|
|
172
|
+
Bug reports and feature requests are welcome. See
|
|
173
|
+
[`CONTRIBUTING.md`](CONTRIBUTING.md) for the development setup and conventions.
|
|
174
|
+
|
|
175
|
+
## License
|
|
176
|
+
|
|
177
|
+
MIT. See [`LICENSE`](LICENSE).
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
CmsPlugin: () => CmsPlugin,
|
|
24
|
+
useMutation: () => useMutation,
|
|
25
|
+
useQuery: () => useQuery
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(src_exports);
|
|
28
|
+
var import_cms_client = require("@lyeve/cms-client");
|
|
29
|
+
var import_vue = require("vue");
|
|
30
|
+
var CMS_KEY = /* @__PURE__ */ Symbol("cms-client");
|
|
31
|
+
var CmsPlugin = {
|
|
32
|
+
install(app, config) {
|
|
33
|
+
const base = config.baseUrl ?? "";
|
|
34
|
+
const client = (0, import_cms_client.createClient)((url, init) => {
|
|
35
|
+
const fullUrl = typeof url === "string" ? `${base}${url}` : url;
|
|
36
|
+
return fetch(fullUrl, {
|
|
37
|
+
...init,
|
|
38
|
+
headers: { ...init?.headers, ...config.getHeaders?.() }
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
app.provide(CMS_KEY, client);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
function useClient() {
|
|
45
|
+
const client = (0, import_vue.inject)(CMS_KEY);
|
|
46
|
+
if (!client) throw new Error("CmsPlugin must be installed via app.use(CmsPlugin, config)");
|
|
47
|
+
return client;
|
|
48
|
+
}
|
|
49
|
+
function useQuery(fetcher) {
|
|
50
|
+
const client = useClient();
|
|
51
|
+
const data = (0, import_vue.ref)(null);
|
|
52
|
+
const error = (0, import_vue.ref)(null);
|
|
53
|
+
const loading = (0, import_vue.ref)(true);
|
|
54
|
+
async function run() {
|
|
55
|
+
loading.value = true;
|
|
56
|
+
try {
|
|
57
|
+
data.value = await fetcher(client);
|
|
58
|
+
error.value = null;
|
|
59
|
+
} catch (e) {
|
|
60
|
+
error.value = e;
|
|
61
|
+
} finally {
|
|
62
|
+
loading.value = false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
run();
|
|
66
|
+
return { data, error, loading, refetch: run };
|
|
67
|
+
}
|
|
68
|
+
function useMutation(mutator) {
|
|
69
|
+
const client = useClient();
|
|
70
|
+
const data = (0, import_vue.ref)(null);
|
|
71
|
+
const error = (0, import_vue.ref)(null);
|
|
72
|
+
const loading = (0, import_vue.ref)(false);
|
|
73
|
+
async function run(vars) {
|
|
74
|
+
loading.value = true;
|
|
75
|
+
error.value = null;
|
|
76
|
+
try {
|
|
77
|
+
const result = await mutator(client, vars);
|
|
78
|
+
data.value = result;
|
|
79
|
+
return result;
|
|
80
|
+
} catch (e) {
|
|
81
|
+
error.value = e;
|
|
82
|
+
throw e;
|
|
83
|
+
} finally {
|
|
84
|
+
loading.value = false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return [run, { data, error, loading }];
|
|
88
|
+
}
|
|
89
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
90
|
+
0 && (module.exports = {
|
|
91
|
+
CmsPlugin,
|
|
92
|
+
useMutation,
|
|
93
|
+
useQuery
|
|
94
|
+
});
|
|
95
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { createClient, type HttpClient } from '@lyeve/cms-client';\nimport { ref, inject, type InjectionKey, type Ref, type App } from 'vue';\n\n// Plugin\n\nexport interface VueCmsConfig {\n baseUrl?: string;\n getHeaders?: () => Record<string, string>;\n}\n\nconst CMS_KEY: InjectionKey<HttpClient> = Symbol('cms-client');\n\n/** Vue plugin that provides an HttpClient via app-level dependency injection. */\nexport const CmsPlugin = {\n install(app: App, config: VueCmsConfig) {\n const base = config.baseUrl ?? '';\n const client = createClient((url, init) => {\n const fullUrl = typeof url === 'string' ? `${base}${url}` : url;\n return fetch(fullUrl, {\n ...init,\n headers: { ...init?.headers, ...config.getHeaders?.() },\n });\n });\n app.provide(CMS_KEY, client);\n },\n};\n\nfunction useClient(): HttpClient {\n const client = inject(CMS_KEY);\n if (!client) throw new Error('CmsPlugin must be installed via app.use(CmsPlugin, config)');\n return client;\n}\n\n// Composables\n\nexport interface AsyncState<T> {\n data: Ref<T | null>;\n error: Ref<Error | null>;\n loading: Ref<boolean>;\n refetch: () => void;\n}\n\n/**\n * Reactive query that fires immediately on mount and exposes loading/data/error state.\n * Re-fetch by calling the returned `refetch` function.\n */\nexport function useQuery<T>(fetcher: (client: HttpClient) => Promise<T>): AsyncState<T> {\n const client = useClient();\n const data = ref<T | null>(null) as Ref<T | null>;\n const error = ref<Error | null>(null);\n const loading = ref(true);\n\n async function run() {\n loading.value = true;\n try {\n data.value = await fetcher(client);\n error.value = null;\n } catch (e) {\n error.value = e as Error;\n } finally {\n loading.value = false;\n }\n }\n\n run();\n\n return { data, error, loading, refetch: run };\n}\n\n/**\n * Returns a mutate function and a reactive state object tracking the latest invocation.\n * The mutate function throws on failure so callers can catch and handle errors inline.\n */\nexport function useMutation<T, V>(\n mutator: (client: HttpClient, vars: V) => Promise<T>,\n): [(vars: V) => Promise<T>, { data: Ref<T | null>; error: Ref<Error | null>; loading: Ref<boolean> }] {\n const client = useClient();\n const data = ref<T | null>(null) as Ref<T | null>;\n const error = ref<Error | null>(null);\n const loading = ref(false);\n\n async function run(vars: V): Promise<T> {\n loading.value = true;\n error.value = null;\n try {\n const result = await mutator(client, vars);\n data.value = result;\n return result;\n } catch (e) {\n error.value = e as Error;\n throw e;\n } finally {\n loading.value = false;\n }\n }\n\n return [run, { data, error, loading }];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAA8C;AAC9C,iBAAmE;AASnE,IAAM,UAAoC,uBAAO,YAAY;AAGtD,IAAM,YAAY;AAAA,EACvB,QAAQ,KAAU,QAAsB;AACtC,UAAM,OAAO,OAAO,WAAW;AAC/B,UAAM,aAAS,gCAAa,CAAC,KAAK,SAAS;AACzC,YAAM,UAAU,OAAO,QAAQ,WAAW,GAAG,IAAI,GAAG,GAAG,KAAK;AAC5D,aAAO,MAAM,SAAS;AAAA,QACpB,GAAG;AAAA,QACH,SAAS,EAAE,GAAG,MAAM,SAAS,GAAG,OAAO,aAAa,EAAE;AAAA,MACxD,CAAC;AAAA,IACH,CAAC;AACD,QAAI,QAAQ,SAAS,MAAM;AAAA,EAC7B;AACF;AAEA,SAAS,YAAwB;AAC/B,QAAM,aAAS,mBAAO,OAAO;AAC7B,MAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,4DAA4D;AACzF,SAAO;AACT;AAeO,SAAS,SAAY,SAA4D;AACtF,QAAM,SAAS,UAAU;AACzB,QAAM,WAAO,gBAAc,IAAI;AAC/B,QAAM,YAAQ,gBAAkB,IAAI;AACpC,QAAM,cAAU,gBAAI,IAAI;AAExB,iBAAe,MAAM;AACnB,YAAQ,QAAQ;AAChB,QAAI;AACF,WAAK,QAAQ,MAAM,QAAQ,MAAM;AACjC,YAAM,QAAQ;AAAA,IAChB,SAAS,GAAG;AACV,YAAM,QAAQ;AAAA,IAChB,UAAE;AACA,cAAQ,QAAQ;AAAA,IAClB;AAAA,EACF;AAEA,MAAI;AAEJ,SAAO,EAAE,MAAM,OAAO,SAAS,SAAS,IAAI;AAC9C;AAMO,SAAS,YACd,SACqG;AACrG,QAAM,SAAS,UAAU;AACzB,QAAM,WAAO,gBAAc,IAAI;AAC/B,QAAM,YAAQ,gBAAkB,IAAI;AACpC,QAAM,cAAU,gBAAI,KAAK;AAEzB,iBAAe,IAAI,MAAqB;AACtC,YAAQ,QAAQ;AAChB,UAAM,QAAQ;AACd,QAAI;AACF,YAAM,SAAS,MAAM,QAAQ,QAAQ,IAAI;AACzC,WAAK,QAAQ;AACb,aAAO;AAAA,IACT,SAAS,GAAG;AACV,YAAM,QAAQ;AACd,YAAM;AAAA,IACR,UAAE;AACA,cAAQ,QAAQ;AAAA,IAClB;AAAA,EACF;AAEA,SAAO,CAAC,KAAK,EAAE,MAAM,OAAO,QAAQ,CAAC;AACvC;","names":[]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { HttpClient } from '@lyeve/cms-client';
|
|
2
|
+
import { Ref, App } from 'vue';
|
|
3
|
+
|
|
4
|
+
interface VueCmsConfig {
|
|
5
|
+
baseUrl?: string;
|
|
6
|
+
getHeaders?: () => Record<string, string>;
|
|
7
|
+
}
|
|
8
|
+
/** Vue plugin that provides an HttpClient via app-level dependency injection. */
|
|
9
|
+
declare const CmsPlugin: {
|
|
10
|
+
install(app: App, config: VueCmsConfig): void;
|
|
11
|
+
};
|
|
12
|
+
interface AsyncState<T> {
|
|
13
|
+
data: Ref<T | null>;
|
|
14
|
+
error: Ref<Error | null>;
|
|
15
|
+
loading: Ref<boolean>;
|
|
16
|
+
refetch: () => void;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Reactive query that fires immediately on mount and exposes loading/data/error state.
|
|
20
|
+
* Re-fetch by calling the returned `refetch` function.
|
|
21
|
+
*/
|
|
22
|
+
declare function useQuery<T>(fetcher: (client: HttpClient) => Promise<T>): AsyncState<T>;
|
|
23
|
+
/**
|
|
24
|
+
* Returns a mutate function and a reactive state object tracking the latest invocation.
|
|
25
|
+
* The mutate function throws on failure so callers can catch and handle errors inline.
|
|
26
|
+
*/
|
|
27
|
+
declare function useMutation<T, V>(mutator: (client: HttpClient, vars: V) => Promise<T>): [(vars: V) => Promise<T>, {
|
|
28
|
+
data: Ref<T | null>;
|
|
29
|
+
error: Ref<Error | null>;
|
|
30
|
+
loading: Ref<boolean>;
|
|
31
|
+
}];
|
|
32
|
+
|
|
33
|
+
export { type AsyncState, CmsPlugin, type VueCmsConfig, useMutation, useQuery };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { HttpClient } from '@lyeve/cms-client';
|
|
2
|
+
import { Ref, App } from 'vue';
|
|
3
|
+
|
|
4
|
+
interface VueCmsConfig {
|
|
5
|
+
baseUrl?: string;
|
|
6
|
+
getHeaders?: () => Record<string, string>;
|
|
7
|
+
}
|
|
8
|
+
/** Vue plugin that provides an HttpClient via app-level dependency injection. */
|
|
9
|
+
declare const CmsPlugin: {
|
|
10
|
+
install(app: App, config: VueCmsConfig): void;
|
|
11
|
+
};
|
|
12
|
+
interface AsyncState<T> {
|
|
13
|
+
data: Ref<T | null>;
|
|
14
|
+
error: Ref<Error | null>;
|
|
15
|
+
loading: Ref<boolean>;
|
|
16
|
+
refetch: () => void;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Reactive query that fires immediately on mount and exposes loading/data/error state.
|
|
20
|
+
* Re-fetch by calling the returned `refetch` function.
|
|
21
|
+
*/
|
|
22
|
+
declare function useQuery<T>(fetcher: (client: HttpClient) => Promise<T>): AsyncState<T>;
|
|
23
|
+
/**
|
|
24
|
+
* Returns a mutate function and a reactive state object tracking the latest invocation.
|
|
25
|
+
* The mutate function throws on failure so callers can catch and handle errors inline.
|
|
26
|
+
*/
|
|
27
|
+
declare function useMutation<T, V>(mutator: (client: HttpClient, vars: V) => Promise<T>): [(vars: V) => Promise<T>, {
|
|
28
|
+
data: Ref<T | null>;
|
|
29
|
+
error: Ref<Error | null>;
|
|
30
|
+
loading: Ref<boolean>;
|
|
31
|
+
}];
|
|
32
|
+
|
|
33
|
+
export { type AsyncState, CmsPlugin, type VueCmsConfig, useMutation, useQuery };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { createClient } from "@lyeve/cms-client";
|
|
3
|
+
import { ref, inject } from "vue";
|
|
4
|
+
var CMS_KEY = /* @__PURE__ */ Symbol("cms-client");
|
|
5
|
+
var CmsPlugin = {
|
|
6
|
+
install(app, config) {
|
|
7
|
+
const base = config.baseUrl ?? "";
|
|
8
|
+
const client = createClient((url, init) => {
|
|
9
|
+
const fullUrl = typeof url === "string" ? `${base}${url}` : url;
|
|
10
|
+
return fetch(fullUrl, {
|
|
11
|
+
...init,
|
|
12
|
+
headers: { ...init?.headers, ...config.getHeaders?.() }
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
app.provide(CMS_KEY, client);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
function useClient() {
|
|
19
|
+
const client = inject(CMS_KEY);
|
|
20
|
+
if (!client) throw new Error("CmsPlugin must be installed via app.use(CmsPlugin, config)");
|
|
21
|
+
return client;
|
|
22
|
+
}
|
|
23
|
+
function useQuery(fetcher) {
|
|
24
|
+
const client = useClient();
|
|
25
|
+
const data = ref(null);
|
|
26
|
+
const error = ref(null);
|
|
27
|
+
const loading = ref(true);
|
|
28
|
+
async function run() {
|
|
29
|
+
loading.value = true;
|
|
30
|
+
try {
|
|
31
|
+
data.value = await fetcher(client);
|
|
32
|
+
error.value = null;
|
|
33
|
+
} catch (e) {
|
|
34
|
+
error.value = e;
|
|
35
|
+
} finally {
|
|
36
|
+
loading.value = false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
run();
|
|
40
|
+
return { data, error, loading, refetch: run };
|
|
41
|
+
}
|
|
42
|
+
function useMutation(mutator) {
|
|
43
|
+
const client = useClient();
|
|
44
|
+
const data = ref(null);
|
|
45
|
+
const error = ref(null);
|
|
46
|
+
const loading = ref(false);
|
|
47
|
+
async function run(vars) {
|
|
48
|
+
loading.value = true;
|
|
49
|
+
error.value = null;
|
|
50
|
+
try {
|
|
51
|
+
const result = await mutator(client, vars);
|
|
52
|
+
data.value = result;
|
|
53
|
+
return result;
|
|
54
|
+
} catch (e) {
|
|
55
|
+
error.value = e;
|
|
56
|
+
throw e;
|
|
57
|
+
} finally {
|
|
58
|
+
loading.value = false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return [run, { data, error, loading }];
|
|
62
|
+
}
|
|
63
|
+
export {
|
|
64
|
+
CmsPlugin,
|
|
65
|
+
useMutation,
|
|
66
|
+
useQuery
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { createClient, type HttpClient } from '@lyeve/cms-client';\nimport { ref, inject, type InjectionKey, type Ref, type App } from 'vue';\n\n// Plugin\n\nexport interface VueCmsConfig {\n baseUrl?: string;\n getHeaders?: () => Record<string, string>;\n}\n\nconst CMS_KEY: InjectionKey<HttpClient> = Symbol('cms-client');\n\n/** Vue plugin that provides an HttpClient via app-level dependency injection. */\nexport const CmsPlugin = {\n install(app: App, config: VueCmsConfig) {\n const base = config.baseUrl ?? '';\n const client = createClient((url, init) => {\n const fullUrl = typeof url === 'string' ? `${base}${url}` : url;\n return fetch(fullUrl, {\n ...init,\n headers: { ...init?.headers, ...config.getHeaders?.() },\n });\n });\n app.provide(CMS_KEY, client);\n },\n};\n\nfunction useClient(): HttpClient {\n const client = inject(CMS_KEY);\n if (!client) throw new Error('CmsPlugin must be installed via app.use(CmsPlugin, config)');\n return client;\n}\n\n// Composables\n\nexport interface AsyncState<T> {\n data: Ref<T | null>;\n error: Ref<Error | null>;\n loading: Ref<boolean>;\n refetch: () => void;\n}\n\n/**\n * Reactive query that fires immediately on mount and exposes loading/data/error state.\n * Re-fetch by calling the returned `refetch` function.\n */\nexport function useQuery<T>(fetcher: (client: HttpClient) => Promise<T>): AsyncState<T> {\n const client = useClient();\n const data = ref<T | null>(null) as Ref<T | null>;\n const error = ref<Error | null>(null);\n const loading = ref(true);\n\n async function run() {\n loading.value = true;\n try {\n data.value = await fetcher(client);\n error.value = null;\n } catch (e) {\n error.value = e as Error;\n } finally {\n loading.value = false;\n }\n }\n\n run();\n\n return { data, error, loading, refetch: run };\n}\n\n/**\n * Returns a mutate function and a reactive state object tracking the latest invocation.\n * The mutate function throws on failure so callers can catch and handle errors inline.\n */\nexport function useMutation<T, V>(\n mutator: (client: HttpClient, vars: V) => Promise<T>,\n): [(vars: V) => Promise<T>, { data: Ref<T | null>; error: Ref<Error | null>; loading: Ref<boolean> }] {\n const client = useClient();\n const data = ref<T | null>(null) as Ref<T | null>;\n const error = ref<Error | null>(null);\n const loading = ref(false);\n\n async function run(vars: V): Promise<T> {\n loading.value = true;\n error.value = null;\n try {\n const result = await mutator(client, vars);\n data.value = result;\n return result;\n } catch (e) {\n error.value = e as Error;\n throw e;\n } finally {\n loading.value = false;\n }\n }\n\n return [run, { data, error, loading }];\n}\n"],"mappings":";AAAA,SAAS,oBAAqC;AAC9C,SAAS,KAAK,cAAqD;AASnE,IAAM,UAAoC,uBAAO,YAAY;AAGtD,IAAM,YAAY;AAAA,EACvB,QAAQ,KAAU,QAAsB;AACtC,UAAM,OAAO,OAAO,WAAW;AAC/B,UAAM,SAAS,aAAa,CAAC,KAAK,SAAS;AACzC,YAAM,UAAU,OAAO,QAAQ,WAAW,GAAG,IAAI,GAAG,GAAG,KAAK;AAC5D,aAAO,MAAM,SAAS;AAAA,QACpB,GAAG;AAAA,QACH,SAAS,EAAE,GAAG,MAAM,SAAS,GAAG,OAAO,aAAa,EAAE;AAAA,MACxD,CAAC;AAAA,IACH,CAAC;AACD,QAAI,QAAQ,SAAS,MAAM;AAAA,EAC7B;AACF;AAEA,SAAS,YAAwB;AAC/B,QAAM,SAAS,OAAO,OAAO;AAC7B,MAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,4DAA4D;AACzF,SAAO;AACT;AAeO,SAAS,SAAY,SAA4D;AACtF,QAAM,SAAS,UAAU;AACzB,QAAM,OAAO,IAAc,IAAI;AAC/B,QAAM,QAAQ,IAAkB,IAAI;AACpC,QAAM,UAAU,IAAI,IAAI;AAExB,iBAAe,MAAM;AACnB,YAAQ,QAAQ;AAChB,QAAI;AACF,WAAK,QAAQ,MAAM,QAAQ,MAAM;AACjC,YAAM,QAAQ;AAAA,IAChB,SAAS,GAAG;AACV,YAAM,QAAQ;AAAA,IAChB,UAAE;AACA,cAAQ,QAAQ;AAAA,IAClB;AAAA,EACF;AAEA,MAAI;AAEJ,SAAO,EAAE,MAAM,OAAO,SAAS,SAAS,IAAI;AAC9C;AAMO,SAAS,YACd,SACqG;AACrG,QAAM,SAAS,UAAU;AACzB,QAAM,OAAO,IAAc,IAAI;AAC/B,QAAM,QAAQ,IAAkB,IAAI;AACpC,QAAM,UAAU,IAAI,KAAK;AAEzB,iBAAe,IAAI,MAAqB;AACtC,YAAQ,QAAQ;AAChB,UAAM,QAAQ;AACd,QAAI;AACF,YAAM,SAAS,MAAM,QAAQ,QAAQ,IAAI;AACzC,WAAK,QAAQ;AACb,aAAO;AAAA,IACT,SAAS,GAAG;AACV,YAAM,QAAQ;AACd,YAAM;AAAA,IACR,UAAE;AACA,cAAQ,QAAQ;AAAA,IAClB;AAAA,EACF;AAEA,SAAO,CAAC,KAAK,EAAE,MAAM,OAAO,QAAQ,CAAC;AACvC;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lyeve-labs/client-vue",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "Vue 3 composables for the LyEve Core client - useQuery, useMutation, and the CmsPlugin provider",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "LyEve Labs <hello@lyeve.com>",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"engines": {
|
|
9
|
+
"node": ">=20"
|
|
10
|
+
},
|
|
11
|
+
"main": "./dist/index.cjs",
|
|
12
|
+
"module": "./dist/index.js",
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"sideEffects": false,
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"import": "./dist/index.js",
|
|
19
|
+
"require": "./dist/index.cjs"
|
|
20
|
+
},
|
|
21
|
+
"./package.json": "./package.json"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"!dist/**/*.test.*",
|
|
26
|
+
"!dist/**/*.spec.*"
|
|
27
|
+
],
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"@lyeve-labs/client-vue": ">=0.1.0",
|
|
33
|
+
"vue": ">=3.0.0"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@lyeve-labs/client-vue": "^0.1.0",
|
|
37
|
+
"jsdom": "^29.1.1",
|
|
38
|
+
"prettier": "^3.4.0",
|
|
39
|
+
"publint": "^0.3.0",
|
|
40
|
+
"tsup": "^8.4.0",
|
|
41
|
+
"typescript": "^5.7.0",
|
|
42
|
+
"vitest": "^2.1.0",
|
|
43
|
+
"vue": "^3.5.0"
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"dev": "tsup --watch",
|
|
47
|
+
"build": "tsup && publint",
|
|
48
|
+
"check": "tsc --noEmit",
|
|
49
|
+
"test": "vitest run",
|
|
50
|
+
"test:watch": "vitest",
|
|
51
|
+
"format": "prettier --write .",
|
|
52
|
+
"format:check": "prettier --check ."
|
|
53
|
+
}
|
|
54
|
+
}
|