storyloco 2.5.0 → 2.6.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
CHANGED
|
@@ -114,6 +114,19 @@ at your call site rather than move into the client.
|
|
|
114
114
|
`client.handle_error` is on the instance, so `.catch(client.handle_error)` works without
|
|
115
115
|
wrapping anything.
|
|
116
116
|
|
|
117
|
+
Errors carry only a `message` by default. If your `App.Error` needs more, pass `error` to shape
|
|
118
|
+
the body of every 404 and 500 storyloco raises — it's typed against your own `App.Error`:
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
export const client = new StoryblokClient({
|
|
122
|
+
token: PUBLIC_STORYBLOK_ACCESS_TOKEN,
|
|
123
|
+
error: (status) => ({
|
|
124
|
+
message: status === 404 ? 'Story not found' : 'Storyblok request failed',
|
|
125
|
+
code: status === 404 ? 'NOT_FOUND' : 'STORYBLOK'
|
|
126
|
+
})
|
|
127
|
+
})
|
|
128
|
+
```
|
|
129
|
+
|
|
117
130
|
#### 2. Use in your Svelte components
|
|
118
131
|
|
|
119
132
|
**`+page.svelte`:**
|
|
@@ -252,7 +265,7 @@ const { client, version } = storyblok()
|
|
|
252
265
|
await client.get('cdn/datasource_entries', { version })
|
|
253
266
|
```
|
|
254
267
|
|
|
255
|
-
Errors go through `handle_error`, so a missing story is a 404 and anything else a 500.
|
|
268
|
+
Errors go through `client.handle_error`, so a missing story is a 404 and anything else a 500, shaped by the client's `error` option.
|
|
256
269
|
|
|
257
270
|
### Use Shared Components
|
|
258
271
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getRequestEvent } from "$app/server";
|
|
2
2
|
import { error } from "@sveltejs/kit";
|
|
3
|
-
import {
|
|
3
|
+
import {} from "./storyblok.svelte.js";
|
|
4
4
|
function is_not_found(err) {
|
|
5
5
|
return typeof err === "object" && err !== null && "status" in err && err.status === 404;
|
|
6
6
|
}
|
|
@@ -52,7 +52,7 @@ export function setup(client) {
|
|
|
52
52
|
.catch((err) => {
|
|
53
53
|
if (is_not_found(err))
|
|
54
54
|
return null;
|
|
55
|
-
return handle_error(err);
|
|
55
|
+
return client.handle_error(err);
|
|
56
56
|
});
|
|
57
57
|
return (response?.data.story ?? null);
|
|
58
58
|
}
|
|
@@ -60,7 +60,7 @@ export function setup(client) {
|
|
|
60
60
|
async function story(slug, params = {}) {
|
|
61
61
|
const found = await find(slug, params);
|
|
62
62
|
if (!found)
|
|
63
|
-
error(404,
|
|
63
|
+
error(404, client.error(404));
|
|
64
64
|
return found;
|
|
65
65
|
}
|
|
66
66
|
async function stories(params = {}) {
|
|
@@ -71,7 +71,7 @@ export function setup(client) {
|
|
|
71
71
|
resolve_assets: 1,
|
|
72
72
|
...params,
|
|
73
73
|
})
|
|
74
|
-
.catch(handle_error);
|
|
74
|
+
.catch(client.handle_error);
|
|
75
75
|
return { stories: response.data.stories, total: response.total ?? 0 };
|
|
76
76
|
}
|
|
77
77
|
async function all(params = {}) {
|
|
@@ -83,7 +83,7 @@ export function setup(client) {
|
|
|
83
83
|
per_page: 100,
|
|
84
84
|
...params,
|
|
85
85
|
})
|
|
86
|
-
.catch(handle_error);
|
|
86
|
+
.catch(client.handle_error);
|
|
87
87
|
}
|
|
88
88
|
return Object.assign(context, {
|
|
89
89
|
story,
|
|
@@ -97,7 +97,7 @@ export function setup(client) {
|
|
|
97
97
|
async links(params = {}) {
|
|
98
98
|
const response = await client
|
|
99
99
|
.get("cdn/links", { version: version(), per_page: 1000, ...params })
|
|
100
|
-
.catch(handle_error);
|
|
100
|
+
.catch(client.handle_error);
|
|
101
101
|
return Object.values(response.data.links ?? {});
|
|
102
102
|
},
|
|
103
103
|
});
|
|
@@ -43,7 +43,15 @@ export interface ClientOptions {
|
|
|
43
43
|
* news posts reuse the blog template. Applied by `template`.
|
|
44
44
|
*/
|
|
45
45
|
aliases?: Record<string, string>;
|
|
46
|
+
/**
|
|
47
|
+
* The body of the errors storyloco raises, for projects whose `App.Error` needs more
|
|
48
|
+
* than a message — e.g. `(status) => ({ message: "Not found", code: "NOT_FOUND" })`.
|
|
49
|
+
* `cause` is the Storyblok error, when there was one.
|
|
50
|
+
*/
|
|
51
|
+
error?: ErrorBody;
|
|
46
52
|
}
|
|
53
|
+
/** Shapes the body of a 404 (missing story) or 500 (anything else Storyblok threw) */
|
|
54
|
+
export type ErrorBody = (status: 404 | 500, cause?: unknown) => App.Error;
|
|
47
55
|
/** Type alias for the storyblok api instance */
|
|
48
56
|
type API = ReturnType<typeof useStoryblokApi>;
|
|
49
57
|
/**
|
|
@@ -83,8 +91,10 @@ export declare class StoryblokClient {
|
|
|
83
91
|
put: API["put"];
|
|
84
92
|
/** Make a DELETE request to the Storyblok API */
|
|
85
93
|
delete: API["delete"];
|
|
86
|
-
/**
|
|
87
|
-
|
|
94
|
+
/** Shapes the body of every error storyloco raises; see `ClientOptions.error` */
|
|
95
|
+
error: ErrorBody;
|
|
96
|
+
/** `handle_error` with this client's `error` shape, bound so `.catch(client.handle_error)` works */
|
|
97
|
+
handle_error: (err: unknown) => never;
|
|
88
98
|
/**
|
|
89
99
|
* Configured here rather than by subclassing, so setup is one expression.
|
|
90
100
|
*
|
|
@@ -97,7 +107,7 @@ export declare class StoryblokClient {
|
|
|
97
107
|
* })
|
|
98
108
|
* ```
|
|
99
109
|
*/
|
|
100
|
-
constructor({ token, components, relations, aliases }: ClientOptions);
|
|
110
|
+
constructor({ token, components, relations, aliases, error, }: ClientOptions);
|
|
101
111
|
/**
|
|
102
112
|
* Load the components and set up the SDK.
|
|
103
113
|
*
|
|
@@ -215,9 +225,10 @@ export declare function href(link?: Link): string | undefined;
|
|
|
215
225
|
* Turn a Storyblok error into a SvelteKit one, for `.catch(handle_error)`.
|
|
216
226
|
*
|
|
217
227
|
* A missing story is a 404; anything else is a 500, since the CMS being unreachable isn't
|
|
218
|
-
* something to show a visitor a Storyblok status code for.
|
|
228
|
+
* something to show a visitor a Storyblok status code for. `body` shapes the error; prefer
|
|
229
|
+
* `client.handle_error`, which passes the client's own.
|
|
219
230
|
*/
|
|
220
|
-
export declare function handle_error(err: unknown): never;
|
|
231
|
+
export declare function handle_error(err: unknown, body?: ErrorBody): never;
|
|
221
232
|
/** Declaring these keeps `SbBlokData`'s index signature from widening every access. */
|
|
222
233
|
interface BlokFields {
|
|
223
234
|
anchor?: string;
|
|
@@ -2,6 +2,9 @@ import { storyblokInit, apiPlugin, renderRichText as richtext, useStoryblokBridg
|
|
|
2
2
|
import { SvelteMap } from "svelte/reactivity";
|
|
3
3
|
import { createAttachmentKey as attach } from "svelte/attachments";
|
|
4
4
|
import { error } from "@sveltejs/kit";
|
|
5
|
+
const default_error = (status) => ({
|
|
6
|
+
message: status === 404 ? "Story not found" : "Internal server error",
|
|
7
|
+
});
|
|
5
8
|
/**
|
|
6
9
|
* Main Storyblok client class that handles component registration, API calls, and story bridging
|
|
7
10
|
* Provides a unified interface for working with Storyblok in Svelte applications
|
|
@@ -56,8 +59,10 @@ export class StoryblokClient {
|
|
|
56
59
|
put = async (...args) => (await this.#api()).put(...args);
|
|
57
60
|
/** Make a DELETE request to the Storyblok API */
|
|
58
61
|
delete = async (...args) => (await this.#api()).delete(...args);
|
|
59
|
-
/**
|
|
60
|
-
|
|
62
|
+
/** Shapes the body of every error storyloco raises; see `ClientOptions.error` */
|
|
63
|
+
error = default_error;
|
|
64
|
+
/** `handle_error` with this client's `error` shape, bound so `.catch(client.handle_error)` works */
|
|
65
|
+
handle_error = (err) => handle_error(err, this.error);
|
|
61
66
|
/**
|
|
62
67
|
* Configured here rather than by subclassing, so setup is one expression.
|
|
63
68
|
*
|
|
@@ -70,11 +75,12 @@ export class StoryblokClient {
|
|
|
70
75
|
* })
|
|
71
76
|
* ```
|
|
72
77
|
*/
|
|
73
|
-
constructor({ token, components = {}, relations = [], aliases = {} }) {
|
|
78
|
+
constructor({ token, components = {}, relations = [], aliases = {}, error = default_error, }) {
|
|
74
79
|
this.#access_token = token;
|
|
75
80
|
this.#component_imports = components;
|
|
76
81
|
this.relations = relations;
|
|
77
82
|
this.aliases = aliases;
|
|
83
|
+
this.error = error;
|
|
78
84
|
// Eager, but handled so a failure surfaces to whoever awaits `init` rather than
|
|
79
85
|
// as an unhandled rejection
|
|
80
86
|
this.init().catch(() => { });
|
|
@@ -166,14 +172,15 @@ export function href(link) {
|
|
|
166
172
|
* Turn a Storyblok error into a SvelteKit one, for `.catch(handle_error)`.
|
|
167
173
|
*
|
|
168
174
|
* A missing story is a 404; anything else is a 500, since the CMS being unreachable isn't
|
|
169
|
-
* something to show a visitor a Storyblok status code for.
|
|
175
|
+
* something to show a visitor a Storyblok status code for. `body` shapes the error; prefer
|
|
176
|
+
* `client.handle_error`, which passes the client's own.
|
|
170
177
|
*/
|
|
171
|
-
export function handle_error(err) {
|
|
178
|
+
export function handle_error(err, body = default_error) {
|
|
172
179
|
console.error(err);
|
|
173
180
|
const status = typeof err === "object" && err !== null && "status" in err ? err.status : undefined;
|
|
174
181
|
if (status === 404)
|
|
175
|
-
error(404,
|
|
176
|
-
error(500,
|
|
182
|
+
error(404, body(404, err));
|
|
183
|
+
error(500, body(500, err));
|
|
177
184
|
}
|
|
178
185
|
/**
|
|
179
186
|
* Spread onto a block's root element to wire it up for the visual editor.
|