@lyeve-labs/client-svelte 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 +207 -0
- package/dist/index.cjs +136 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +97 -0
- package/dist/index.d.ts +97 -0
- package/dist/index.js +106 -0
- package/dist/index.js.map +1 -0
- package/package.json +55 -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,207 @@
|
|
|
1
|
+
# @lyeve/cms-client-svelte
|
|
2
|
+
|
|
3
|
+
Svelte 5 reactive stores for the LyEve Core API. Thin wrapper around
|
|
4
|
+
`@lyeve/cms-client` using Svelte 5 runes (`$state`).
|
|
5
|
+
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[](https://svelte.dev)
|
|
8
|
+
[](https://www.typescriptlang.org)
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pnpm add @lyeve/cms-client @lyeve/cms-client-svelte
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
```svelte
|
|
15
|
+
<script lang="ts">
|
|
16
|
+
import { createCmsClient, createAsyncStore } from '@lyeve/cms-client-svelte';
|
|
17
|
+
import { getSchemas } from '@lyeve/cms-client-rest';
|
|
18
|
+
|
|
19
|
+
const client = createCmsClient({
|
|
20
|
+
baseUrl: 'https://cms.example.com',
|
|
21
|
+
getHeaders: () => ({ Authorization: `Bearer ${token}` }),
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const schemas = createAsyncStore((client) => getSchemas(client), client);
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
{#if schemas.loading}
|
|
28
|
+
<p>Loading...</p>
|
|
29
|
+
{:else if schemas.error}
|
|
30
|
+
<p>Error: {schemas.error.message}</p>
|
|
31
|
+
{:else}
|
|
32
|
+
<ul>
|
|
33
|
+
{#each schemas.data ?? [] as schema}
|
|
34
|
+
<li>{schema.name}</li>
|
|
35
|
+
{/each}
|
|
36
|
+
</ul>
|
|
37
|
+
{/if}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
No Provider needed. Create a client, pass it in, done.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## What's in the box
|
|
45
|
+
|
|
46
|
+
- **createCmsClient:** factory that returns a configured `HttpClient` with
|
|
47
|
+
base URL and dynamic headers.
|
|
48
|
+
- **createAsyncStore:** reactive async data store built on `$state`. Returns
|
|
49
|
+
`{ data, error, loading, refetch }`. All reactive, no boilerplate.
|
|
50
|
+
- **createAuthStore:** auth state store with reactive `user`, `token`, and
|
|
51
|
+
`isAuthenticated`. Methods to `setUser`, `clear`, and `load` from storage.
|
|
52
|
+
- **Svelte 5 native:** built on runes. No legacy stores, no `writable`.
|
|
53
|
+
|
|
54
|
+
## Requirements
|
|
55
|
+
|
|
56
|
+
- **Node 20** or newer
|
|
57
|
+
- **Svelte 5.0** or newer
|
|
58
|
+
- **[@lyeve/cms-client](https://www.npmjs.com/package/@lyeve/cms-client)** `>=0.1.0`
|
|
59
|
+
|
|
60
|
+
## Install
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pnpm add @lyeve/cms-client @lyeve/cms-client-svelte
|
|
64
|
+
# or npm install @lyeve/cms-client @lyeve/cms-client-svelte
|
|
65
|
+
# or yarn add @lyeve/cms-client @lyeve/cms-client-svelte
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Use
|
|
69
|
+
|
|
70
|
+
### Data fetching
|
|
71
|
+
|
|
72
|
+
```svelte
|
|
73
|
+
<script lang="ts">
|
|
74
|
+
import { createCmsClient, createAsyncStore } from '@lyeve/cms-client-svelte';
|
|
75
|
+
import { getSchemas } from '@lyeve/cms-client-rest';
|
|
76
|
+
|
|
77
|
+
const client = createCmsClient({
|
|
78
|
+
baseUrl: 'https://cms.example.com',
|
|
79
|
+
getHeaders: () => ({ Authorization: `Bearer ${token}` }),
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const schemas = createAsyncStore((c) => getSchemas(c), client);
|
|
83
|
+
</script>
|
|
84
|
+
|
|
85
|
+
{#if schemas.loading}
|
|
86
|
+
<p>Loading...</p>
|
|
87
|
+
{:else if schemas.error}
|
|
88
|
+
<p>Error: {schemas.error.message}</p>
|
|
89
|
+
{:else}
|
|
90
|
+
<ul>
|
|
91
|
+
{#each schemas.data ?? [] as schema}
|
|
92
|
+
<li>{schema.name}</li>
|
|
93
|
+
{/each}
|
|
94
|
+
</ul>
|
|
95
|
+
{/if}
|
|
96
|
+
|
|
97
|
+
<button onclick={() => schemas.refetch()}>Reload</button>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Authentication
|
|
101
|
+
|
|
102
|
+
```svelte
|
|
103
|
+
<script lang="ts">
|
|
104
|
+
import { createCmsClient, createAuthStore } from '@lyeve/cms-client-svelte';
|
|
105
|
+
|
|
106
|
+
const client = createCmsClient({ baseUrl: 'https://cms.example.com' });
|
|
107
|
+
const auth = createAuthStore(client);
|
|
108
|
+
|
|
109
|
+
function handleLogin(e: SubmitEvent) {
|
|
110
|
+
e.preventDefault();
|
|
111
|
+
const data = new FormData(e.target as HTMLFormElement);
|
|
112
|
+
const credentials = {
|
|
113
|
+
email: data.get('email') as string,
|
|
114
|
+
password: data.get('password') as string,
|
|
115
|
+
};
|
|
116
|
+
// Call your auth endpoint, then store the result:
|
|
117
|
+
const user = { id: '1', email: credentials.email, roles: ['admin'] };
|
|
118
|
+
auth.setUser(user, 'jwt-token');
|
|
119
|
+
}
|
|
120
|
+
</script>
|
|
121
|
+
|
|
122
|
+
{#if !auth.isAuthenticated}
|
|
123
|
+
<form onsubmit={handleLogin}>
|
|
124
|
+
<input type="email" name="email" required />
|
|
125
|
+
<input type="password" name="password" required />
|
|
126
|
+
<button type="submit">Log in</button>
|
|
127
|
+
</form>
|
|
128
|
+
{:else}
|
|
129
|
+
<p>Welcome, {auth.user?.email}</p>
|
|
130
|
+
<button onclick={() => auth.clear()}>Log out</button>
|
|
131
|
+
{/if}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## API
|
|
135
|
+
|
|
136
|
+
### createCmsClient(config)
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
function createCmsClient(config: {
|
|
140
|
+
baseUrl?: string;
|
|
141
|
+
getHeaders?: () => Record<string, string>;
|
|
142
|
+
}): HttpClient;
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### createAsyncStore(fetcher, client)
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
function createAsyncStore<T>(
|
|
149
|
+
fetcher: (client: HttpClient) => Promise<T>,
|
|
150
|
+
client: HttpClient,
|
|
151
|
+
): {
|
|
152
|
+
data: T | null;
|
|
153
|
+
error: Error | null;
|
|
154
|
+
loading: boolean;
|
|
155
|
+
refetch: () => void;
|
|
156
|
+
};
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
All fields are reactive (`$state` rune).
|
|
160
|
+
|
|
161
|
+
### createAuthStore(client)
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
function createAuthStore(client: HttpClient): {
|
|
165
|
+
user: { id: string; email: string; roles: string[] } | null;
|
|
166
|
+
token: string | null;
|
|
167
|
+
isAuthenticated: boolean;
|
|
168
|
+
setUser: (user: User, token: string) => void;
|
|
169
|
+
clear: () => void;
|
|
170
|
+
load: () => Promise<void>;
|
|
171
|
+
};
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Local development
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
pnpm install # install dependencies
|
|
178
|
+
pnpm test # run unit tests
|
|
179
|
+
pnpm check # type-check
|
|
180
|
+
pnpm build # tsup + publint -> dist/
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Project layout
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
src/
|
|
187
|
+
index.ts # public API (re-exports)
|
|
188
|
+
index.svelte.ts # Svelte 5 entry point
|
|
189
|
+
runes.ts # createAsyncStore, createAuthStore
|
|
190
|
+
ambient.d.ts # type declarations
|
|
191
|
+
tests/ # vitest test suite
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Versioning
|
|
195
|
+
|
|
196
|
+
`@lyeve/cms-client-svelte` follows [SemVer](https://semver.org). While under `1.0`,
|
|
197
|
+
breaking changes bump the **minor** version; additive changes bump the **patch**.
|
|
198
|
+
Every release is logged in [`CHANGELOG.md`](CHANGELOG.md).
|
|
199
|
+
|
|
200
|
+
## Contributing
|
|
201
|
+
|
|
202
|
+
Bug reports and feature requests are welcome. See
|
|
203
|
+
[`CONTRIBUTING.md`](CONTRIBUTING.md) for the development setup and conventions.
|
|
204
|
+
|
|
205
|
+
## License
|
|
206
|
+
|
|
207
|
+
MIT. See [`LICENSE`](LICENSE).
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
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
|
+
createAsyncStore: () => createAsyncStore,
|
|
24
|
+
createAuthStore: () => createAuthStore,
|
|
25
|
+
createCmsClient: () => createCmsClient,
|
|
26
|
+
createMutation: () => createMutation
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(src_exports);
|
|
29
|
+
|
|
30
|
+
// src/runes.ts
|
|
31
|
+
var import_cms_client = require("@lyeve/cms-client");
|
|
32
|
+
function createCmsClient(config) {
|
|
33
|
+
const base = config.baseUrl ?? "";
|
|
34
|
+
return (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
|
+
}
|
|
42
|
+
function createAsyncStore(fetcher, client) {
|
|
43
|
+
let data = $state(null);
|
|
44
|
+
let error = $state(null);
|
|
45
|
+
let loading = $state(true);
|
|
46
|
+
async function fetch2() {
|
|
47
|
+
loading = true;
|
|
48
|
+
try {
|
|
49
|
+
data = await fetcher(client);
|
|
50
|
+
error = null;
|
|
51
|
+
} catch (e) {
|
|
52
|
+
error = e;
|
|
53
|
+
} finally {
|
|
54
|
+
loading = false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
fetch2();
|
|
58
|
+
return {
|
|
59
|
+
get data() {
|
|
60
|
+
return data;
|
|
61
|
+
},
|
|
62
|
+
get error() {
|
|
63
|
+
return error;
|
|
64
|
+
},
|
|
65
|
+
get loading() {
|
|
66
|
+
return loading;
|
|
67
|
+
},
|
|
68
|
+
refetch: fetch2
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function createMutation(mutator, client) {
|
|
72
|
+
let data = $state(null);
|
|
73
|
+
let error = $state(null);
|
|
74
|
+
let loading = $state(false);
|
|
75
|
+
async function run(vars) {
|
|
76
|
+
loading = true;
|
|
77
|
+
error = null;
|
|
78
|
+
try {
|
|
79
|
+
const result = await mutator(client, vars);
|
|
80
|
+
data = result;
|
|
81
|
+
return result;
|
|
82
|
+
} catch (e) {
|
|
83
|
+
error = e;
|
|
84
|
+
throw e;
|
|
85
|
+
} finally {
|
|
86
|
+
loading = false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
get data() {
|
|
91
|
+
return data;
|
|
92
|
+
},
|
|
93
|
+
get error() {
|
|
94
|
+
return error;
|
|
95
|
+
},
|
|
96
|
+
get loading() {
|
|
97
|
+
return loading;
|
|
98
|
+
},
|
|
99
|
+
run
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function createAuthStore(client) {
|
|
103
|
+
let state = $state({ user: null, token: null });
|
|
104
|
+
return {
|
|
105
|
+
get user() {
|
|
106
|
+
return state.user;
|
|
107
|
+
},
|
|
108
|
+
get token() {
|
|
109
|
+
return state.token;
|
|
110
|
+
},
|
|
111
|
+
get isAuthenticated() {
|
|
112
|
+
return state.token !== null;
|
|
113
|
+
},
|
|
114
|
+
setUser(user, token) {
|
|
115
|
+
state = { user, token };
|
|
116
|
+
},
|
|
117
|
+
clear() {
|
|
118
|
+
state = { user: null, token: null };
|
|
119
|
+
},
|
|
120
|
+
async load() {
|
|
121
|
+
try {
|
|
122
|
+
const user = await client.get("/api/admin/auth/me");
|
|
123
|
+
state = { ...state, user };
|
|
124
|
+
} catch {
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
130
|
+
0 && (module.exports = {
|
|
131
|
+
createAsyncStore,
|
|
132
|
+
createAuthStore,
|
|
133
|
+
createCmsClient,
|
|
134
|
+
createMutation
|
|
135
|
+
});
|
|
136
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/runes.ts"],"sourcesContent":["// Re-exports for non-Svelte consumers (bundled by tsup).\n// Implementation lives in runes.svelte.ts so Svelte's compiler handles\n// $state runes natively via the \"svelte\" export condition.\nexport {\n\tcreateCmsClient,\n\tcreateAsyncStore,\n\tcreateMutation,\n\tcreateAuthStore,\n\ttype SvelteCmsConfig,\n\ttype AsyncStore,\n\ttype AuthState,\n\ttype AuthStore,\n} from './runes.js';\n","import { createClient, type HttpClient } from '@lyeve/cms-client';\n\n// Client factory\n\nexport interface SvelteCmsConfig {\n\t/** Base URL prepended to every request path. */\n\tbaseUrl?: string;\n\t/**\n\t * Callback returning headers added to every request.\n\t * Called on every request so auth tokens can be refreshed without\n\t * recreating the client.\n\t */\n\tgetHeaders?: () => Record<string, string>;\n}\n\n/**\n * Creates an HttpClient pre-configured with base URL and dynamic request\n * headers. No Provider needed - Svelte callers just pass the client around.\n *\n * @example\n * ```ts\n * const client = createCmsClient({\n * baseUrl: 'https://cms.example.com',\n * getHeaders: () => ({ Authorization: `Bearer ${token}` }),\n * });\n * ```\n */\nexport function createCmsClient(config: SvelteCmsConfig): HttpClient {\n\tconst base = config.baseUrl ?? '';\n\treturn createClient((url, init) => {\n\t\tconst fullUrl = typeof url === 'string' ? `${base}${url}` : url;\n\t\treturn fetch(fullUrl, {\n\t\t\t...init,\n\t\t\theaders: { ...init?.headers, ...config.getHeaders?.() },\n\t\t});\n\t});\n}\n\n// Generic async store\n\nexport interface AsyncStore<T> {\n\treadonly data: T | null;\n\treadonly error: Error | null;\n\treadonly loading: boolean;\n\trefetch: () => void;\n}\n\n/**\n * Reactive async data store using the $state rune.\n * Fires the fetcher immediately and exposes reactive loading/data/error\n * getters that Svelte components can read directly in markup.\n *\n * @example\n * ```svelte\n * <script lang=\"ts\">\n * const schemas = createAsyncStore((c) => getSchemas(c), client);\n * </script>\n * {#if schemas.loading}...{/if}\n * ```\n */\nexport function createAsyncStore<T>(\n\tfetcher: (client: HttpClient) => Promise<T>,\n\tclient: HttpClient,\n): AsyncStore<T> {\n\tlet data = $state<T | null>(null);\n\tlet error = $state<Error | null>(null);\n\tlet loading = $state(true);\n\n\tasync function fetch() {\n\t\tloading = true;\n\t\ttry {\n\t\t\tdata = await fetcher(client);\n\t\t\terror = null;\n\t\t} catch (e) {\n\t\t\terror = e as Error;\n\t\t} finally {\n\t\t\tloading = false;\n\t\t}\n\t}\n\n\tfetch();\n\n\treturn {\n\t\tget data() { return data; },\n\t\tget error() { return error; },\n\t\tget loading() { return loading; },\n\t\trefetch: fetch,\n\t};\n}\n\n/**\n * Reactive mutation primitive using the $state rune.\n * Returns data/error/loading state and a run function that triggers the\n * mutation. Unlike createAsyncStore, the mutation does not fire immediately.\n *\n * @example\n * ```svelte\n * <script lang=\"ts\">\n * const createArticle = createMutation(\n * (c, vars: { title: string }) => createArticle(c, vars),\n * client,\n * );\n * </script>\n * <button onclick={() => createArticle.run({ title: 'Hello' })}>\n * {createArticle.loading ? 'Saving...' : 'Create'}\n * </button>\n * ```\n */\nexport function createMutation<T, V>(\n\tmutator: (client: HttpClient, vars: V) => Promise<T>,\n\tclient: HttpClient,\n) {\n\tlet data = $state<T | null>(null);\n\tlet error = $state<Error | null>(null);\n\tlet loading = $state(false);\n\n\tasync function run(vars: V): Promise<T> {\n\t\tloading = true;\n\t\terror = null;\n\t\ttry {\n\t\t\tconst result = await mutator(client, vars);\n\t\t\tdata = result;\n\t\t\treturn result;\n\t\t} catch (e) {\n\t\t\terror = e as Error;\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\tloading = false;\n\t\t}\n\t}\n\n\treturn {\n\t\tget data() { return data; },\n\t\tget error() { return error; },\n\t\tget loading() { return loading; },\n\t\trun,\n\t};\n}\n\n// Auth store\n\nexport interface AuthState {\n\tuser: { id: string; email: string; roles: string[] } | null;\n\ttoken: string | null;\n}\n\nexport interface AuthStore {\n\treadonly user: AuthState['user'];\n\treadonly token: string | null;\n\treadonly isAuthenticated: boolean;\n\t/** Set the current user and token after a successful login. */\n\tsetUser: (user: AuthState['user'], token: string | null) => void;\n\t/** Clear auth state (e.g. after logout). */\n\tclear: () => void;\n\t/** Try to load the current user from the server using the stored token. */\n\tload: () => Promise<void>;\n}\n\n/**\n * Simple reactive auth store. The caller is responsible for calling\n * {@link AuthStore.setUser} after login and {@link AuthStore.clear} after\n * logout. Use {@link AuthStore.load} on app start to restore a session\n * from an existing cookie.\n */\nexport function createAuthStore(client: HttpClient): AuthStore {\n\tlet state = $state<AuthState>({ user: null, token: null });\n\n\treturn {\n\t\tget user() { return state.user; },\n\t\tget token() { return state.token; },\n\t\tget isAuthenticated() { return state.token !== null; },\n\t\tsetUser(user: AuthState['user'], token: string | null) {\n\t\t\tstate = { user, token };\n\t\t},\n\t\tclear() {\n\t\t\tstate = { user: null, token: null };\n\t\t},\n\t\tasync load() {\n\t\t\ttry {\n\t\t\t\tconst user = await client.get<{ id: string; email: string; roles: string[] }>('/api/admin/auth/me');\n\t\t\t\tstate = { ...state, user };\n\t\t\t} catch { /* not logged in */ }\n\t\t},\n\t};\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,wBAA8C;AA2BvC,SAAS,gBAAgB,QAAqC;AACpE,QAAM,OAAO,OAAO,WAAW;AAC/B,aAAO,gCAAa,CAAC,KAAK,SAAS;AAClC,UAAM,UAAU,OAAO,QAAQ,WAAW,GAAG,IAAI,GAAG,GAAG,KAAK;AAC5D,WAAO,MAAM,SAAS;AAAA,MACrB,GAAG;AAAA,MACH,SAAS,EAAE,GAAG,MAAM,SAAS,GAAG,OAAO,aAAa,EAAE;AAAA,IACvD,CAAC;AAAA,EACF,CAAC;AACF;AAwBO,SAAS,iBACf,SACA,QACgB;AAChB,MAAI,OAAO,OAAiB,IAAI;AAChC,MAAI,QAAQ,OAAqB,IAAI;AACrC,MAAI,UAAU,OAAO,IAAI;AAEzB,iBAAeA,SAAQ;AACtB,cAAU;AACV,QAAI;AACH,aAAO,MAAM,QAAQ,MAAM;AAC3B,cAAQ;AAAA,IACT,SAAS,GAAG;AACX,cAAQ;AAAA,IACT,UAAE;AACD,gBAAU;AAAA,IACX;AAAA,EACD;AAEA,EAAAA,OAAM;AAEN,SAAO;AAAA,IACN,IAAI,OAAO;AAAE,aAAO;AAAA,IAAM;AAAA,IAC1B,IAAI,QAAQ;AAAE,aAAO;AAAA,IAAO;AAAA,IAC5B,IAAI,UAAU;AAAE,aAAO;AAAA,IAAS;AAAA,IAChC,SAASA;AAAA,EACV;AACD;AAoBO,SAAS,eACf,SACA,QACC;AACD,MAAI,OAAO,OAAiB,IAAI;AAChC,MAAI,QAAQ,OAAqB,IAAI;AACrC,MAAI,UAAU,OAAO,KAAK;AAE1B,iBAAe,IAAI,MAAqB;AACvC,cAAU;AACV,YAAQ;AACR,QAAI;AACH,YAAM,SAAS,MAAM,QAAQ,QAAQ,IAAI;AACzC,aAAO;AACP,aAAO;AAAA,IACR,SAAS,GAAG;AACX,cAAQ;AACR,YAAM;AAAA,IACP,UAAE;AACD,gBAAU;AAAA,IACX;AAAA,EACD;AAEA,SAAO;AAAA,IACN,IAAI,OAAO;AAAE,aAAO;AAAA,IAAM;AAAA,IAC1B,IAAI,QAAQ;AAAE,aAAO;AAAA,IAAO;AAAA,IAC5B,IAAI,UAAU;AAAE,aAAO;AAAA,IAAS;AAAA,IAChC;AAAA,EACD;AACD;AA2BO,SAAS,gBAAgB,QAA+B;AAC9D,MAAI,QAAQ,OAAkB,EAAE,MAAM,MAAM,OAAO,KAAK,CAAC;AAEzD,SAAO;AAAA,IACN,IAAI,OAAO;AAAE,aAAO,MAAM;AAAA,IAAM;AAAA,IAChC,IAAI,QAAQ;AAAE,aAAO,MAAM;AAAA,IAAO;AAAA,IAClC,IAAI,kBAAkB;AAAE,aAAO,MAAM,UAAU;AAAA,IAAM;AAAA,IACrD,QAAQ,MAAyB,OAAsB;AACtD,cAAQ,EAAE,MAAM,MAAM;AAAA,IACvB;AAAA,IACA,QAAQ;AACP,cAAQ,EAAE,MAAM,MAAM,OAAO,KAAK;AAAA,IACnC;AAAA,IACA,MAAM,OAAO;AACZ,UAAI;AACH,cAAM,OAAO,MAAM,OAAO,IAAoD,oBAAoB;AAClG,gBAAQ,EAAE,GAAG,OAAO,KAAK;AAAA,MAC1B,QAAQ;AAAA,MAAsB;AAAA,IAC/B;AAAA,EACD;AACD;","names":["fetch"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { HttpClient } from '@lyeve/cms-client';
|
|
2
|
+
|
|
3
|
+
interface SvelteCmsConfig {
|
|
4
|
+
/** Base URL prepended to every request path. */
|
|
5
|
+
baseUrl?: string;
|
|
6
|
+
/**
|
|
7
|
+
* Callback returning headers added to every request.
|
|
8
|
+
* Called on every request so auth tokens can be refreshed without
|
|
9
|
+
* recreating the client.
|
|
10
|
+
*/
|
|
11
|
+
getHeaders?: () => Record<string, string>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Creates an HttpClient pre-configured with base URL and dynamic request
|
|
15
|
+
* headers. No Provider needed - Svelte callers just pass the client around.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* const client = createCmsClient({
|
|
20
|
+
* baseUrl: 'https://cms.example.com',
|
|
21
|
+
* getHeaders: () => ({ Authorization: `Bearer ${token}` }),
|
|
22
|
+
* });
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
declare function createCmsClient(config: SvelteCmsConfig): HttpClient;
|
|
26
|
+
interface AsyncStore<T> {
|
|
27
|
+
readonly data: T | null;
|
|
28
|
+
readonly error: Error | null;
|
|
29
|
+
readonly loading: boolean;
|
|
30
|
+
refetch: () => void;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Reactive async data store using the $state rune.
|
|
34
|
+
* Fires the fetcher immediately and exposes reactive loading/data/error
|
|
35
|
+
* getters that Svelte components can read directly in markup.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```svelte
|
|
39
|
+
* <script lang="ts">
|
|
40
|
+
* const schemas = createAsyncStore((c) => getSchemas(c), client);
|
|
41
|
+
* </script>
|
|
42
|
+
* {#if schemas.loading}...{/if}
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
declare function createAsyncStore<T>(fetcher: (client: HttpClient) => Promise<T>, client: HttpClient): AsyncStore<T>;
|
|
46
|
+
/**
|
|
47
|
+
* Reactive mutation primitive using the $state rune.
|
|
48
|
+
* Returns data/error/loading state and a run function that triggers the
|
|
49
|
+
* mutation. Unlike createAsyncStore, the mutation does not fire immediately.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```svelte
|
|
53
|
+
* <script lang="ts">
|
|
54
|
+
* const createArticle = createMutation(
|
|
55
|
+
* (c, vars: { title: string }) => createArticle(c, vars),
|
|
56
|
+
* client,
|
|
57
|
+
* );
|
|
58
|
+
* </script>
|
|
59
|
+
* <button onclick={() => createArticle.run({ title: 'Hello' })}>
|
|
60
|
+
* {createArticle.loading ? 'Saving...' : 'Create'}
|
|
61
|
+
* </button>
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
declare function createMutation<T, V>(mutator: (client: HttpClient, vars: V) => Promise<T>, client: HttpClient): {
|
|
65
|
+
readonly data: T | null;
|
|
66
|
+
readonly error: Error | null;
|
|
67
|
+
readonly loading: boolean;
|
|
68
|
+
run: (vars: V) => Promise<T>;
|
|
69
|
+
};
|
|
70
|
+
interface AuthState {
|
|
71
|
+
user: {
|
|
72
|
+
id: string;
|
|
73
|
+
email: string;
|
|
74
|
+
roles: string[];
|
|
75
|
+
} | null;
|
|
76
|
+
token: string | null;
|
|
77
|
+
}
|
|
78
|
+
interface AuthStore {
|
|
79
|
+
readonly user: AuthState['user'];
|
|
80
|
+
readonly token: string | null;
|
|
81
|
+
readonly isAuthenticated: boolean;
|
|
82
|
+
/** Set the current user and token after a successful login. */
|
|
83
|
+
setUser: (user: AuthState['user'], token: string | null) => void;
|
|
84
|
+
/** Clear auth state (e.g. after logout). */
|
|
85
|
+
clear: () => void;
|
|
86
|
+
/** Try to load the current user from the server using the stored token. */
|
|
87
|
+
load: () => Promise<void>;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Simple reactive auth store. The caller is responsible for calling
|
|
91
|
+
* {@link AuthStore.setUser} after login and {@link AuthStore.clear} after
|
|
92
|
+
* logout. Use {@link AuthStore.load} on app start to restore a session
|
|
93
|
+
* from an existing cookie.
|
|
94
|
+
*/
|
|
95
|
+
declare function createAuthStore(client: HttpClient): AuthStore;
|
|
96
|
+
|
|
97
|
+
export { type AsyncStore, type AuthState, type AuthStore, type SvelteCmsConfig, createAsyncStore, createAuthStore, createCmsClient, createMutation };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { HttpClient } from '@lyeve/cms-client';
|
|
2
|
+
|
|
3
|
+
interface SvelteCmsConfig {
|
|
4
|
+
/** Base URL prepended to every request path. */
|
|
5
|
+
baseUrl?: string;
|
|
6
|
+
/**
|
|
7
|
+
* Callback returning headers added to every request.
|
|
8
|
+
* Called on every request so auth tokens can be refreshed without
|
|
9
|
+
* recreating the client.
|
|
10
|
+
*/
|
|
11
|
+
getHeaders?: () => Record<string, string>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Creates an HttpClient pre-configured with base URL and dynamic request
|
|
15
|
+
* headers. No Provider needed - Svelte callers just pass the client around.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* const client = createCmsClient({
|
|
20
|
+
* baseUrl: 'https://cms.example.com',
|
|
21
|
+
* getHeaders: () => ({ Authorization: `Bearer ${token}` }),
|
|
22
|
+
* });
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
declare function createCmsClient(config: SvelteCmsConfig): HttpClient;
|
|
26
|
+
interface AsyncStore<T> {
|
|
27
|
+
readonly data: T | null;
|
|
28
|
+
readonly error: Error | null;
|
|
29
|
+
readonly loading: boolean;
|
|
30
|
+
refetch: () => void;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Reactive async data store using the $state rune.
|
|
34
|
+
* Fires the fetcher immediately and exposes reactive loading/data/error
|
|
35
|
+
* getters that Svelte components can read directly in markup.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```svelte
|
|
39
|
+
* <script lang="ts">
|
|
40
|
+
* const schemas = createAsyncStore((c) => getSchemas(c), client);
|
|
41
|
+
* </script>
|
|
42
|
+
* {#if schemas.loading}...{/if}
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
declare function createAsyncStore<T>(fetcher: (client: HttpClient) => Promise<T>, client: HttpClient): AsyncStore<T>;
|
|
46
|
+
/**
|
|
47
|
+
* Reactive mutation primitive using the $state rune.
|
|
48
|
+
* Returns data/error/loading state and a run function that triggers the
|
|
49
|
+
* mutation. Unlike createAsyncStore, the mutation does not fire immediately.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```svelte
|
|
53
|
+
* <script lang="ts">
|
|
54
|
+
* const createArticle = createMutation(
|
|
55
|
+
* (c, vars: { title: string }) => createArticle(c, vars),
|
|
56
|
+
* client,
|
|
57
|
+
* );
|
|
58
|
+
* </script>
|
|
59
|
+
* <button onclick={() => createArticle.run({ title: 'Hello' })}>
|
|
60
|
+
* {createArticle.loading ? 'Saving...' : 'Create'}
|
|
61
|
+
* </button>
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
declare function createMutation<T, V>(mutator: (client: HttpClient, vars: V) => Promise<T>, client: HttpClient): {
|
|
65
|
+
readonly data: T | null;
|
|
66
|
+
readonly error: Error | null;
|
|
67
|
+
readonly loading: boolean;
|
|
68
|
+
run: (vars: V) => Promise<T>;
|
|
69
|
+
};
|
|
70
|
+
interface AuthState {
|
|
71
|
+
user: {
|
|
72
|
+
id: string;
|
|
73
|
+
email: string;
|
|
74
|
+
roles: string[];
|
|
75
|
+
} | null;
|
|
76
|
+
token: string | null;
|
|
77
|
+
}
|
|
78
|
+
interface AuthStore {
|
|
79
|
+
readonly user: AuthState['user'];
|
|
80
|
+
readonly token: string | null;
|
|
81
|
+
readonly isAuthenticated: boolean;
|
|
82
|
+
/** Set the current user and token after a successful login. */
|
|
83
|
+
setUser: (user: AuthState['user'], token: string | null) => void;
|
|
84
|
+
/** Clear auth state (e.g. after logout). */
|
|
85
|
+
clear: () => void;
|
|
86
|
+
/** Try to load the current user from the server using the stored token. */
|
|
87
|
+
load: () => Promise<void>;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Simple reactive auth store. The caller is responsible for calling
|
|
91
|
+
* {@link AuthStore.setUser} after login and {@link AuthStore.clear} after
|
|
92
|
+
* logout. Use {@link AuthStore.load} on app start to restore a session
|
|
93
|
+
* from an existing cookie.
|
|
94
|
+
*/
|
|
95
|
+
declare function createAuthStore(client: HttpClient): AuthStore;
|
|
96
|
+
|
|
97
|
+
export { type AsyncStore, type AuthState, type AuthStore, type SvelteCmsConfig, createAsyncStore, createAuthStore, createCmsClient, createMutation };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// src/runes.ts
|
|
2
|
+
import { createClient } from "@lyeve/cms-client";
|
|
3
|
+
function createCmsClient(config) {
|
|
4
|
+
const base = config.baseUrl ?? "";
|
|
5
|
+
return createClient((url, init) => {
|
|
6
|
+
const fullUrl = typeof url === "string" ? `${base}${url}` : url;
|
|
7
|
+
return fetch(fullUrl, {
|
|
8
|
+
...init,
|
|
9
|
+
headers: { ...init?.headers, ...config.getHeaders?.() }
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
function createAsyncStore(fetcher, client) {
|
|
14
|
+
let data = $state(null);
|
|
15
|
+
let error = $state(null);
|
|
16
|
+
let loading = $state(true);
|
|
17
|
+
async function fetch2() {
|
|
18
|
+
loading = true;
|
|
19
|
+
try {
|
|
20
|
+
data = await fetcher(client);
|
|
21
|
+
error = null;
|
|
22
|
+
} catch (e) {
|
|
23
|
+
error = e;
|
|
24
|
+
} finally {
|
|
25
|
+
loading = false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
fetch2();
|
|
29
|
+
return {
|
|
30
|
+
get data() {
|
|
31
|
+
return data;
|
|
32
|
+
},
|
|
33
|
+
get error() {
|
|
34
|
+
return error;
|
|
35
|
+
},
|
|
36
|
+
get loading() {
|
|
37
|
+
return loading;
|
|
38
|
+
},
|
|
39
|
+
refetch: fetch2
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function createMutation(mutator, client) {
|
|
43
|
+
let data = $state(null);
|
|
44
|
+
let error = $state(null);
|
|
45
|
+
let loading = $state(false);
|
|
46
|
+
async function run(vars) {
|
|
47
|
+
loading = true;
|
|
48
|
+
error = null;
|
|
49
|
+
try {
|
|
50
|
+
const result = await mutator(client, vars);
|
|
51
|
+
data = result;
|
|
52
|
+
return result;
|
|
53
|
+
} catch (e) {
|
|
54
|
+
error = e;
|
|
55
|
+
throw e;
|
|
56
|
+
} finally {
|
|
57
|
+
loading = false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
get data() {
|
|
62
|
+
return data;
|
|
63
|
+
},
|
|
64
|
+
get error() {
|
|
65
|
+
return error;
|
|
66
|
+
},
|
|
67
|
+
get loading() {
|
|
68
|
+
return loading;
|
|
69
|
+
},
|
|
70
|
+
run
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function createAuthStore(client) {
|
|
74
|
+
let state = $state({ user: null, token: null });
|
|
75
|
+
return {
|
|
76
|
+
get user() {
|
|
77
|
+
return state.user;
|
|
78
|
+
},
|
|
79
|
+
get token() {
|
|
80
|
+
return state.token;
|
|
81
|
+
},
|
|
82
|
+
get isAuthenticated() {
|
|
83
|
+
return state.token !== null;
|
|
84
|
+
},
|
|
85
|
+
setUser(user, token) {
|
|
86
|
+
state = { user, token };
|
|
87
|
+
},
|
|
88
|
+
clear() {
|
|
89
|
+
state = { user: null, token: null };
|
|
90
|
+
},
|
|
91
|
+
async load() {
|
|
92
|
+
try {
|
|
93
|
+
const user = await client.get("/api/admin/auth/me");
|
|
94
|
+
state = { ...state, user };
|
|
95
|
+
} catch {
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
export {
|
|
101
|
+
createAsyncStore,
|
|
102
|
+
createAuthStore,
|
|
103
|
+
createCmsClient,
|
|
104
|
+
createMutation
|
|
105
|
+
};
|
|
106
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/runes.ts"],"sourcesContent":["import { createClient, type HttpClient } from '@lyeve/cms-client';\n\n// Client factory\n\nexport interface SvelteCmsConfig {\n\t/** Base URL prepended to every request path. */\n\tbaseUrl?: string;\n\t/**\n\t * Callback returning headers added to every request.\n\t * Called on every request so auth tokens can be refreshed without\n\t * recreating the client.\n\t */\n\tgetHeaders?: () => Record<string, string>;\n}\n\n/**\n * Creates an HttpClient pre-configured with base URL and dynamic request\n * headers. No Provider needed - Svelte callers just pass the client around.\n *\n * @example\n * ```ts\n * const client = createCmsClient({\n * baseUrl: 'https://cms.example.com',\n * getHeaders: () => ({ Authorization: `Bearer ${token}` }),\n * });\n * ```\n */\nexport function createCmsClient(config: SvelteCmsConfig): HttpClient {\n\tconst base = config.baseUrl ?? '';\n\treturn createClient((url, init) => {\n\t\tconst fullUrl = typeof url === 'string' ? `${base}${url}` : url;\n\t\treturn fetch(fullUrl, {\n\t\t\t...init,\n\t\t\theaders: { ...init?.headers, ...config.getHeaders?.() },\n\t\t});\n\t});\n}\n\n// Generic async store\n\nexport interface AsyncStore<T> {\n\treadonly data: T | null;\n\treadonly error: Error | null;\n\treadonly loading: boolean;\n\trefetch: () => void;\n}\n\n/**\n * Reactive async data store using the $state rune.\n * Fires the fetcher immediately and exposes reactive loading/data/error\n * getters that Svelte components can read directly in markup.\n *\n * @example\n * ```svelte\n * <script lang=\"ts\">\n * const schemas = createAsyncStore((c) => getSchemas(c), client);\n * </script>\n * {#if schemas.loading}...{/if}\n * ```\n */\nexport function createAsyncStore<T>(\n\tfetcher: (client: HttpClient) => Promise<T>,\n\tclient: HttpClient,\n): AsyncStore<T> {\n\tlet data = $state<T | null>(null);\n\tlet error = $state<Error | null>(null);\n\tlet loading = $state(true);\n\n\tasync function fetch() {\n\t\tloading = true;\n\t\ttry {\n\t\t\tdata = await fetcher(client);\n\t\t\terror = null;\n\t\t} catch (e) {\n\t\t\terror = e as Error;\n\t\t} finally {\n\t\t\tloading = false;\n\t\t}\n\t}\n\n\tfetch();\n\n\treturn {\n\t\tget data() { return data; },\n\t\tget error() { return error; },\n\t\tget loading() { return loading; },\n\t\trefetch: fetch,\n\t};\n}\n\n/**\n * Reactive mutation primitive using the $state rune.\n * Returns data/error/loading state and a run function that triggers the\n * mutation. Unlike createAsyncStore, the mutation does not fire immediately.\n *\n * @example\n * ```svelte\n * <script lang=\"ts\">\n * const createArticle = createMutation(\n * (c, vars: { title: string }) => createArticle(c, vars),\n * client,\n * );\n * </script>\n * <button onclick={() => createArticle.run({ title: 'Hello' })}>\n * {createArticle.loading ? 'Saving...' : 'Create'}\n * </button>\n * ```\n */\nexport function createMutation<T, V>(\n\tmutator: (client: HttpClient, vars: V) => Promise<T>,\n\tclient: HttpClient,\n) {\n\tlet data = $state<T | null>(null);\n\tlet error = $state<Error | null>(null);\n\tlet loading = $state(false);\n\n\tasync function run(vars: V): Promise<T> {\n\t\tloading = true;\n\t\terror = null;\n\t\ttry {\n\t\t\tconst result = await mutator(client, vars);\n\t\t\tdata = result;\n\t\t\treturn result;\n\t\t} catch (e) {\n\t\t\terror = e as Error;\n\t\t\tthrow e;\n\t\t} finally {\n\t\t\tloading = false;\n\t\t}\n\t}\n\n\treturn {\n\t\tget data() { return data; },\n\t\tget error() { return error; },\n\t\tget loading() { return loading; },\n\t\trun,\n\t};\n}\n\n// Auth store\n\nexport interface AuthState {\n\tuser: { id: string; email: string; roles: string[] } | null;\n\ttoken: string | null;\n}\n\nexport interface AuthStore {\n\treadonly user: AuthState['user'];\n\treadonly token: string | null;\n\treadonly isAuthenticated: boolean;\n\t/** Set the current user and token after a successful login. */\n\tsetUser: (user: AuthState['user'], token: string | null) => void;\n\t/** Clear auth state (e.g. after logout). */\n\tclear: () => void;\n\t/** Try to load the current user from the server using the stored token. */\n\tload: () => Promise<void>;\n}\n\n/**\n * Simple reactive auth store. The caller is responsible for calling\n * {@link AuthStore.setUser} after login and {@link AuthStore.clear} after\n * logout. Use {@link AuthStore.load} on app start to restore a session\n * from an existing cookie.\n */\nexport function createAuthStore(client: HttpClient): AuthStore {\n\tlet state = $state<AuthState>({ user: null, token: null });\n\n\treturn {\n\t\tget user() { return state.user; },\n\t\tget token() { return state.token; },\n\t\tget isAuthenticated() { return state.token !== null; },\n\t\tsetUser(user: AuthState['user'], token: string | null) {\n\t\t\tstate = { user, token };\n\t\t},\n\t\tclear() {\n\t\t\tstate = { user: null, token: null };\n\t\t},\n\t\tasync load() {\n\t\t\ttry {\n\t\t\t\tconst user = await client.get<{ id: string; email: string; roles: string[] }>('/api/admin/auth/me');\n\t\t\t\tstate = { ...state, user };\n\t\t\t} catch { /* not logged in */ }\n\t\t},\n\t};\n}\n"],"mappings":";AAAA,SAAS,oBAAqC;AA2BvC,SAAS,gBAAgB,QAAqC;AACpE,QAAM,OAAO,OAAO,WAAW;AAC/B,SAAO,aAAa,CAAC,KAAK,SAAS;AAClC,UAAM,UAAU,OAAO,QAAQ,WAAW,GAAG,IAAI,GAAG,GAAG,KAAK;AAC5D,WAAO,MAAM,SAAS;AAAA,MACrB,GAAG;AAAA,MACH,SAAS,EAAE,GAAG,MAAM,SAAS,GAAG,OAAO,aAAa,EAAE;AAAA,IACvD,CAAC;AAAA,EACF,CAAC;AACF;AAwBO,SAAS,iBACf,SACA,QACgB;AAChB,MAAI,OAAO,OAAiB,IAAI;AAChC,MAAI,QAAQ,OAAqB,IAAI;AACrC,MAAI,UAAU,OAAO,IAAI;AAEzB,iBAAeA,SAAQ;AACtB,cAAU;AACV,QAAI;AACH,aAAO,MAAM,QAAQ,MAAM;AAC3B,cAAQ;AAAA,IACT,SAAS,GAAG;AACX,cAAQ;AAAA,IACT,UAAE;AACD,gBAAU;AAAA,IACX;AAAA,EACD;AAEA,EAAAA,OAAM;AAEN,SAAO;AAAA,IACN,IAAI,OAAO;AAAE,aAAO;AAAA,IAAM;AAAA,IAC1B,IAAI,QAAQ;AAAE,aAAO;AAAA,IAAO;AAAA,IAC5B,IAAI,UAAU;AAAE,aAAO;AAAA,IAAS;AAAA,IAChC,SAASA;AAAA,EACV;AACD;AAoBO,SAAS,eACf,SACA,QACC;AACD,MAAI,OAAO,OAAiB,IAAI;AAChC,MAAI,QAAQ,OAAqB,IAAI;AACrC,MAAI,UAAU,OAAO,KAAK;AAE1B,iBAAe,IAAI,MAAqB;AACvC,cAAU;AACV,YAAQ;AACR,QAAI;AACH,YAAM,SAAS,MAAM,QAAQ,QAAQ,IAAI;AACzC,aAAO;AACP,aAAO;AAAA,IACR,SAAS,GAAG;AACX,cAAQ;AACR,YAAM;AAAA,IACP,UAAE;AACD,gBAAU;AAAA,IACX;AAAA,EACD;AAEA,SAAO;AAAA,IACN,IAAI,OAAO;AAAE,aAAO;AAAA,IAAM;AAAA,IAC1B,IAAI,QAAQ;AAAE,aAAO;AAAA,IAAO;AAAA,IAC5B,IAAI,UAAU;AAAE,aAAO;AAAA,IAAS;AAAA,IAChC;AAAA,EACD;AACD;AA2BO,SAAS,gBAAgB,QAA+B;AAC9D,MAAI,QAAQ,OAAkB,EAAE,MAAM,MAAM,OAAO,KAAK,CAAC;AAEzD,SAAO;AAAA,IACN,IAAI,OAAO;AAAE,aAAO,MAAM;AAAA,IAAM;AAAA,IAChC,IAAI,QAAQ;AAAE,aAAO,MAAM;AAAA,IAAO;AAAA,IAClC,IAAI,kBAAkB;AAAE,aAAO,MAAM,UAAU;AAAA,IAAM;AAAA,IACrD,QAAQ,MAAyB,OAAsB;AACtD,cAAQ,EAAE,MAAM,MAAM;AAAA,IACvB;AAAA,IACA,QAAQ;AACP,cAAQ,EAAE,MAAM,MAAM,OAAO,KAAK;AAAA,IACnC;AAAA,IACA,MAAM,OAAO;AACZ,UAAI;AACH,cAAM,OAAO,MAAM,OAAO,IAAoD,oBAAoB;AAClG,gBAAQ,EAAE,GAAG,OAAO,KAAK;AAAA,MAC1B,QAAQ;AAAA,MAAsB;AAAA,IAC/B;AAAA,EACD;AACD;","names":["fetch"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lyeve-labs/client-svelte",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "Svelte 5 reactive stores for the LyEve Core API - thin wrapper around @lyeve/cms-client using $state runes",
|
|
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
|
+
"svelte": "./src/index.svelte.ts",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"svelte": "./src/index.svelte.ts",
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"import": "./dist/index.js",
|
|
20
|
+
"require": "./dist/index.cjs"
|
|
21
|
+
},
|
|
22
|
+
"./package.json": "./package.json"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"!dist/**/*.test.*",
|
|
27
|
+
"!dist/**/*.spec.*"
|
|
28
|
+
],
|
|
29
|
+
"sideEffects": false,
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"@lyeve-labs/client-svelte": ">=0.1.0",
|
|
35
|
+
"svelte": ">=5.0.0"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@lyeve-labs/client-svelte": "^0.1.0",
|
|
39
|
+
"svelte": "^5.0.0",
|
|
40
|
+
"tsup": "^8.4.0",
|
|
41
|
+
"typescript": "^5.7.0",
|
|
42
|
+
"vitest": "^2.1.0",
|
|
43
|
+
"publint": "^0.3.0",
|
|
44
|
+
"prettier": "^3.4.0"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"dev": "tsup --watch",
|
|
48
|
+
"build": "tsup && publint",
|
|
49
|
+
"check": "tsc --noEmit",
|
|
50
|
+
"test": "vitest run",
|
|
51
|
+
"test:watch": "vitest",
|
|
52
|
+
"format": "prettier --write .",
|
|
53
|
+
"format:check": "prettier --check ."
|
|
54
|
+
}
|
|
55
|
+
}
|