@btst/stack 1.1.10 → 1.1.11
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 +3 -168
- package/dist/client/components/index.d.cts +22 -0
- package/dist/client/components/index.d.mts +22 -0
- package/dist/client/components/index.d.ts +22 -0
- package/dist/context/index.d.cts +21 -1
- package/dist/context/index.d.mts +21 -1
- package/dist/context/index.d.ts +21 -1
- package/dist/packages/better-stack/src/plugins/blog/client/components/shared/on-this-page.cjs +7 -2
- package/dist/packages/better-stack/src/plugins/blog/client/components/shared/on-this-page.mjs +7 -2
- package/dist/plugins/blog/api/index.d.cts +1 -1
- package/dist/plugins/blog/api/index.d.mts +1 -1
- package/dist/plugins/blog/api/index.d.ts +1 -1
- package/dist/plugins/blog/client/hooks/index.d.cts +74 -2
- package/dist/plugins/blog/client/hooks/index.d.mts +74 -2
- package/dist/plugins/blog/client/hooks/index.d.ts +74 -2
- package/dist/plugins/blog/client/index.d.cts +70 -1
- package/dist/plugins/blog/client/index.d.mts +70 -1
- package/dist/plugins/blog/client/index.d.ts +70 -1
- package/dist/plugins/blog/query-keys.d.cts +64 -2
- package/dist/plugins/blog/query-keys.d.mts +64 -2
- package/dist/plugins/blog/query-keys.d.ts +64 -2
- package/package.json +1 -1
- package/src/client/components/compose.tsx +13 -0
- package/src/client/components/error-boundary.tsx +9 -0
- package/src/context/provider.tsx +21 -1
- package/src/plugins/blog/api/plugin.ts +62 -3
- package/src/plugins/blog/client/components/shared/on-this-page.tsx +4 -2
- package/src/plugins/blog/client/hooks/blog-hooks.tsx +72 -0
- package/src/plugins/blog/client/overrides.ts +10 -0
- package/src/plugins/blog/client/plugin.tsx +59 -5
- package/dist/shared/{stack.Cr2JoQdo.d.cts → stack.CoPoHVfV.d.cts} +1 -1
- package/dist/shared/{stack.Cr2JoQdo.d.mts → stack.CoPoHVfV.d.mts} +1 -1
- package/dist/shared/{stack.Cr2JoQdo.d.ts → stack.CoPoHVfV.d.ts} +1 -1
|
@@ -3,7 +3,7 @@ import * as react from 'react';
|
|
|
3
3
|
import { ComponentType } from 'react';
|
|
4
4
|
import * as _btst_yar from '@btst/yar';
|
|
5
5
|
import { QueryClient } from '@tanstack/react-query';
|
|
6
|
-
import { P as Post, S as SerializedPost } from '../../../shared/stack.
|
|
6
|
+
import { P as Post, S as SerializedPost } from '../../../shared/stack.CoPoHVfV.js';
|
|
7
7
|
export { UsePostsOptions, UsePostsResult } from './hooks/index.js';
|
|
8
8
|
import 'zod';
|
|
9
9
|
|
|
@@ -11,21 +11,32 @@ import 'zod';
|
|
|
11
11
|
* Context passed to route hooks
|
|
12
12
|
*/
|
|
13
13
|
interface RouteContext$1 {
|
|
14
|
+
/** Current route path */
|
|
14
15
|
path: string;
|
|
16
|
+
/** Route parameters (e.g., { slug: "my-post" }) */
|
|
15
17
|
params?: Record<string, string>;
|
|
18
|
+
/** Whether rendering on server (true) or client (false) */
|
|
16
19
|
isSSR: boolean;
|
|
20
|
+
/** Additional context properties */
|
|
17
21
|
[key: string]: any;
|
|
18
22
|
}
|
|
19
23
|
/**
|
|
20
24
|
* Context passed to loader hooks
|
|
21
25
|
*/
|
|
22
26
|
interface LoaderContext {
|
|
27
|
+
/** Current route path */
|
|
23
28
|
path: string;
|
|
29
|
+
/** Route parameters (e.g., { slug: "my-post" }) */
|
|
24
30
|
params?: Record<string, string>;
|
|
31
|
+
/** Whether rendering on server (true) or client (false) */
|
|
25
32
|
isSSR: boolean;
|
|
33
|
+
/** Base URL for API calls */
|
|
26
34
|
apiBaseURL: string;
|
|
35
|
+
/** Path where the API is mounted */
|
|
27
36
|
apiBasePath: string;
|
|
37
|
+
/** Optional headers for the request */
|
|
28
38
|
headers?: Headers;
|
|
39
|
+
/** Additional context properties */
|
|
29
40
|
[key: string]: any;
|
|
30
41
|
}
|
|
31
42
|
/**
|
|
@@ -33,19 +44,32 @@ interface LoaderContext {
|
|
|
33
44
|
* Note: queryClient is passed at runtime to both loader and meta (for SSR isolation)
|
|
34
45
|
*/
|
|
35
46
|
interface BlogClientConfig {
|
|
47
|
+
/** Base URL for API calls (e.g., "http://localhost:3000") */
|
|
36
48
|
apiBaseURL: string;
|
|
49
|
+
/** Path where the API is mounted (e.g., "/api/data") */
|
|
37
50
|
apiBasePath: string;
|
|
51
|
+
/** Base URL of your site for SEO meta tags */
|
|
38
52
|
siteBaseURL: string;
|
|
53
|
+
/** Path where pages are mounted (e.g., "/pages") */
|
|
39
54
|
siteBasePath: string;
|
|
55
|
+
/** React Query client instance for caching */
|
|
40
56
|
queryClient: QueryClient;
|
|
57
|
+
/** Optional SEO configuration for meta tags */
|
|
41
58
|
seo?: {
|
|
59
|
+
/** Site name for Open Graph tags */
|
|
42
60
|
siteName?: string;
|
|
61
|
+
/** Default author name */
|
|
43
62
|
author?: string;
|
|
63
|
+
/** Twitter handle (e.g., "@yourhandle") */
|
|
44
64
|
twitterHandle?: string;
|
|
65
|
+
/** Locale for Open Graph (e.g., "en_US") */
|
|
45
66
|
locale?: string;
|
|
67
|
+
/** Default image URL for social sharing */
|
|
46
68
|
defaultImage?: string;
|
|
47
69
|
};
|
|
70
|
+
/** Optional hooks for customizing behavior */
|
|
48
71
|
hooks?: BlogClientHooks;
|
|
72
|
+
/** Optional headers for SSR (e.g., forwarding cookies) */
|
|
49
73
|
headers?: Headers;
|
|
50
74
|
}
|
|
51
75
|
/**
|
|
@@ -53,16 +77,51 @@ interface BlogClientConfig {
|
|
|
53
77
|
* All hooks are optional and allow consumers to customize behavior
|
|
54
78
|
*/
|
|
55
79
|
interface BlogClientHooks {
|
|
80
|
+
/**
|
|
81
|
+
* Called before loading posts list. Return false to cancel loading.
|
|
82
|
+
* @param filter - Filter parameters including published status
|
|
83
|
+
* @param context - Loader context with path, params, etc.
|
|
84
|
+
*/
|
|
56
85
|
beforeLoadPosts?: (filter: {
|
|
57
86
|
published: boolean;
|
|
58
87
|
}, context: LoaderContext) => Promise<boolean> | boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Called after posts are loaded. Return false to cancel further processing.
|
|
90
|
+
* @param posts - Array of loaded posts or null
|
|
91
|
+
* @param filter - Filter parameters used
|
|
92
|
+
* @param context - Loader context
|
|
93
|
+
*/
|
|
59
94
|
afterLoadPosts?: (posts: Post[] | null, filter: {
|
|
60
95
|
published: boolean;
|
|
61
96
|
}, context: LoaderContext) => Promise<boolean> | boolean;
|
|
97
|
+
/**
|
|
98
|
+
* Called before loading a single post. Return false to cancel loading.
|
|
99
|
+
* @param slug - Post slug being loaded
|
|
100
|
+
* @param context - Loader context
|
|
101
|
+
*/
|
|
62
102
|
beforeLoadPost?: (slug: string, context: LoaderContext) => Promise<boolean> | boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Called after a post is loaded. Return false to cancel further processing.
|
|
105
|
+
* @param post - Loaded post or null if not found
|
|
106
|
+
* @param slug - Post slug that was requested
|
|
107
|
+
* @param context - Loader context
|
|
108
|
+
*/
|
|
63
109
|
afterLoadPost?: (post: Post | null, slug: string, context: LoaderContext) => Promise<boolean> | boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Called before loading the new post page. Return false to cancel.
|
|
112
|
+
* @param context - Loader context
|
|
113
|
+
*/
|
|
64
114
|
beforeLoadNewPost?: (context: LoaderContext) => Promise<boolean> | boolean;
|
|
115
|
+
/**
|
|
116
|
+
* Called after the new post page is loaded. Return false to cancel.
|
|
117
|
+
* @param context - Loader context
|
|
118
|
+
*/
|
|
65
119
|
afterLoadNewPost?: (context: LoaderContext) => Promise<boolean> | boolean;
|
|
120
|
+
/**
|
|
121
|
+
* Called when a loading error occurs
|
|
122
|
+
* @param error - The error that occurred
|
|
123
|
+
* @param context - Loader context
|
|
124
|
+
*/
|
|
66
125
|
onLoadError?: (error: Error, context: LoaderContext) => Promise<void> | void;
|
|
67
126
|
}
|
|
68
127
|
/**
|
|
@@ -313,9 +372,13 @@ type BlogLocalization = typeof BLOG_LOCALIZATION;
|
|
|
313
372
|
* Context passed to lifecycle hooks
|
|
314
373
|
*/
|
|
315
374
|
interface RouteContext {
|
|
375
|
+
/** Current route path */
|
|
316
376
|
path: string;
|
|
377
|
+
/** Route parameters (e.g., { slug: "my-post" }) */
|
|
317
378
|
params?: Record<string, string>;
|
|
379
|
+
/** Whether rendering on server (true) or client (false) */
|
|
318
380
|
isSSR: boolean;
|
|
381
|
+
/** Additional context properties */
|
|
319
382
|
[key: string]: any;
|
|
320
383
|
}
|
|
321
384
|
/**
|
|
@@ -325,7 +388,13 @@ interface RouteContext {
|
|
|
325
388
|
* to customize the behavior for their framework (Next.js, React Router, etc.)
|
|
326
389
|
*/
|
|
327
390
|
interface BlogPluginOverrides {
|
|
391
|
+
/**
|
|
392
|
+
* Link component for navigation
|
|
393
|
+
*/
|
|
328
394
|
Link?: ComponentType<React.ComponentProps<"a"> & Record<string, any>>;
|
|
395
|
+
/**
|
|
396
|
+
* Post card component for displaying a post
|
|
397
|
+
*/
|
|
329
398
|
PostCard?: ComponentType<{
|
|
330
399
|
post: SerializedPost;
|
|
331
400
|
}>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as _btst_stack_plugins_api from '@btst/stack/plugins/api';
|
|
2
2
|
import * as better_call from 'better-call';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
import { c as createPostSchema, u as updatePostSchema, P as Post, T as Tag, S as SerializedPost, a as SerializedTag } from '../../shared/stack.
|
|
4
|
+
import { c as createPostSchema, u as updatePostSchema, P as Post, T as Tag, S as SerializedPost, a as SerializedTag } from '../../shared/stack.CoPoHVfV.cjs';
|
|
5
5
|
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
6
6
|
import { createApiClient } from '@btst/stack/plugins/client';
|
|
7
7
|
|
|
@@ -32,17 +32,79 @@ interface BlogApiContext<TBody = any, TParams = any, TQuery = any> {
|
|
|
32
32
|
* All hooks are optional and allow consumers to customize behavior
|
|
33
33
|
*/
|
|
34
34
|
interface BlogBackendHooks {
|
|
35
|
+
/**
|
|
36
|
+
* Called before listing posts. Return false to deny access.
|
|
37
|
+
* @param filter - Query parameters for filtering posts
|
|
38
|
+
* @param context - Request context with headers, etc.
|
|
39
|
+
*/
|
|
35
40
|
onBeforeListPosts?: (filter: z.infer<typeof PostListQuerySchema>, context: BlogApiContext) => Promise<boolean> | boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Called before creating a post. Return false to deny access.
|
|
43
|
+
* @param data - Post data being created
|
|
44
|
+
* @param context - Request context with headers, etc.
|
|
45
|
+
*/
|
|
36
46
|
onBeforeCreatePost?: (data: z.infer<typeof createPostSchema>, context: BlogApiContext) => Promise<boolean> | boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Called before updating a post. Return false to deny access.
|
|
49
|
+
* @param postId - ID of the post being updated
|
|
50
|
+
* @param data - Updated post data
|
|
51
|
+
* @param context - Request context with headers, etc.
|
|
52
|
+
*/
|
|
37
53
|
onBeforeUpdatePost?: (postId: string, data: z.infer<typeof updatePostSchema>, context: BlogApiContext) => Promise<boolean> | boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Called before deleting a post. Return false to deny access.
|
|
56
|
+
* @param postId - ID of the post being deleted
|
|
57
|
+
* @param context - Request context with headers, etc.
|
|
58
|
+
*/
|
|
38
59
|
onBeforeDeletePost?: (postId: string, context: BlogApiContext) => Promise<boolean> | boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Called after posts are read successfully
|
|
62
|
+
* @param posts - Array of posts that were read
|
|
63
|
+
* @param filter - Query parameters used for filtering
|
|
64
|
+
* @param context - Request context
|
|
65
|
+
*/
|
|
39
66
|
onPostsRead?: (posts: Post[], filter: z.infer<typeof PostListQuerySchema>, context: BlogApiContext) => Promise<void> | void;
|
|
67
|
+
/**
|
|
68
|
+
* Called after a post is created successfully
|
|
69
|
+
* @param post - The created post
|
|
70
|
+
* @param context - Request context
|
|
71
|
+
*/
|
|
40
72
|
onPostCreated?: (post: Post, context: BlogApiContext) => Promise<void> | void;
|
|
73
|
+
/**
|
|
74
|
+
* Called after a post is updated successfully
|
|
75
|
+
* @param post - The updated post
|
|
76
|
+
* @param context - Request context
|
|
77
|
+
*/
|
|
41
78
|
onPostUpdated?: (post: Post, context: BlogApiContext) => Promise<void> | void;
|
|
79
|
+
/**
|
|
80
|
+
* Called after a post is deleted successfully
|
|
81
|
+
* @param postId - ID of the deleted post
|
|
82
|
+
* @param context - Request context
|
|
83
|
+
*/
|
|
42
84
|
onPostDeleted?: (postId: string, context: BlogApiContext) => Promise<void> | void;
|
|
85
|
+
/**
|
|
86
|
+
* Called when listing posts fails
|
|
87
|
+
* @param error - The error that occurred
|
|
88
|
+
* @param context - Request context
|
|
89
|
+
*/
|
|
43
90
|
onListPostsError?: (error: Error, context: BlogApiContext) => Promise<void> | void;
|
|
91
|
+
/**
|
|
92
|
+
* Called when creating a post fails
|
|
93
|
+
* @param error - The error that occurred
|
|
94
|
+
* @param context - Request context
|
|
95
|
+
*/
|
|
44
96
|
onCreatePostError?: (error: Error, context: BlogApiContext) => Promise<void> | void;
|
|
97
|
+
/**
|
|
98
|
+
* Called when updating a post fails
|
|
99
|
+
* @param error - The error that occurred
|
|
100
|
+
* @param context - Request context
|
|
101
|
+
*/
|
|
45
102
|
onUpdatePostError?: (error: Error, context: BlogApiContext) => Promise<void> | void;
|
|
103
|
+
/**
|
|
104
|
+
* Called when deleting a post fails
|
|
105
|
+
* @param error - The error that occurred
|
|
106
|
+
* @param context - Request context
|
|
107
|
+
*/
|
|
46
108
|
onDeletePostError?: (error: Error, context: BlogApiContext) => Promise<void> | void;
|
|
47
109
|
}
|
|
48
110
|
/**
|
|
@@ -173,12 +235,12 @@ declare const blogBackendPlugin: (hooks?: BlogBackendHooks) => _btst_stack_plugi
|
|
|
173
235
|
options: {
|
|
174
236
|
method: "POST";
|
|
175
237
|
body: z.ZodObject<{
|
|
176
|
-
title: z.ZodString;
|
|
177
238
|
slug: z.ZodOptional<z.ZodString>;
|
|
178
239
|
published: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
179
240
|
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
180
241
|
publishedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
181
242
|
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
243
|
+
title: z.ZodString;
|
|
182
244
|
content: z.ZodString;
|
|
183
245
|
excerpt: z.ZodString;
|
|
184
246
|
image: z.ZodOptional<z.ZodString>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as _btst_stack_plugins_api from '@btst/stack/plugins/api';
|
|
2
2
|
import * as better_call from 'better-call';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
import { c as createPostSchema, u as updatePostSchema, P as Post, T as Tag, S as SerializedPost, a as SerializedTag } from '../../shared/stack.
|
|
4
|
+
import { c as createPostSchema, u as updatePostSchema, P as Post, T as Tag, S as SerializedPost, a as SerializedTag } from '../../shared/stack.CoPoHVfV.mjs';
|
|
5
5
|
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
6
6
|
import { createApiClient } from '@btst/stack/plugins/client';
|
|
7
7
|
|
|
@@ -32,17 +32,79 @@ interface BlogApiContext<TBody = any, TParams = any, TQuery = any> {
|
|
|
32
32
|
* All hooks are optional and allow consumers to customize behavior
|
|
33
33
|
*/
|
|
34
34
|
interface BlogBackendHooks {
|
|
35
|
+
/**
|
|
36
|
+
* Called before listing posts. Return false to deny access.
|
|
37
|
+
* @param filter - Query parameters for filtering posts
|
|
38
|
+
* @param context - Request context with headers, etc.
|
|
39
|
+
*/
|
|
35
40
|
onBeforeListPosts?: (filter: z.infer<typeof PostListQuerySchema>, context: BlogApiContext) => Promise<boolean> | boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Called before creating a post. Return false to deny access.
|
|
43
|
+
* @param data - Post data being created
|
|
44
|
+
* @param context - Request context with headers, etc.
|
|
45
|
+
*/
|
|
36
46
|
onBeforeCreatePost?: (data: z.infer<typeof createPostSchema>, context: BlogApiContext) => Promise<boolean> | boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Called before updating a post. Return false to deny access.
|
|
49
|
+
* @param postId - ID of the post being updated
|
|
50
|
+
* @param data - Updated post data
|
|
51
|
+
* @param context - Request context with headers, etc.
|
|
52
|
+
*/
|
|
37
53
|
onBeforeUpdatePost?: (postId: string, data: z.infer<typeof updatePostSchema>, context: BlogApiContext) => Promise<boolean> | boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Called before deleting a post. Return false to deny access.
|
|
56
|
+
* @param postId - ID of the post being deleted
|
|
57
|
+
* @param context - Request context with headers, etc.
|
|
58
|
+
*/
|
|
38
59
|
onBeforeDeletePost?: (postId: string, context: BlogApiContext) => Promise<boolean> | boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Called after posts are read successfully
|
|
62
|
+
* @param posts - Array of posts that were read
|
|
63
|
+
* @param filter - Query parameters used for filtering
|
|
64
|
+
* @param context - Request context
|
|
65
|
+
*/
|
|
39
66
|
onPostsRead?: (posts: Post[], filter: z.infer<typeof PostListQuerySchema>, context: BlogApiContext) => Promise<void> | void;
|
|
67
|
+
/**
|
|
68
|
+
* Called after a post is created successfully
|
|
69
|
+
* @param post - The created post
|
|
70
|
+
* @param context - Request context
|
|
71
|
+
*/
|
|
40
72
|
onPostCreated?: (post: Post, context: BlogApiContext) => Promise<void> | void;
|
|
73
|
+
/**
|
|
74
|
+
* Called after a post is updated successfully
|
|
75
|
+
* @param post - The updated post
|
|
76
|
+
* @param context - Request context
|
|
77
|
+
*/
|
|
41
78
|
onPostUpdated?: (post: Post, context: BlogApiContext) => Promise<void> | void;
|
|
79
|
+
/**
|
|
80
|
+
* Called after a post is deleted successfully
|
|
81
|
+
* @param postId - ID of the deleted post
|
|
82
|
+
* @param context - Request context
|
|
83
|
+
*/
|
|
42
84
|
onPostDeleted?: (postId: string, context: BlogApiContext) => Promise<void> | void;
|
|
85
|
+
/**
|
|
86
|
+
* Called when listing posts fails
|
|
87
|
+
* @param error - The error that occurred
|
|
88
|
+
* @param context - Request context
|
|
89
|
+
*/
|
|
43
90
|
onListPostsError?: (error: Error, context: BlogApiContext) => Promise<void> | void;
|
|
91
|
+
/**
|
|
92
|
+
* Called when creating a post fails
|
|
93
|
+
* @param error - The error that occurred
|
|
94
|
+
* @param context - Request context
|
|
95
|
+
*/
|
|
44
96
|
onCreatePostError?: (error: Error, context: BlogApiContext) => Promise<void> | void;
|
|
97
|
+
/**
|
|
98
|
+
* Called when updating a post fails
|
|
99
|
+
* @param error - The error that occurred
|
|
100
|
+
* @param context - Request context
|
|
101
|
+
*/
|
|
45
102
|
onUpdatePostError?: (error: Error, context: BlogApiContext) => Promise<void> | void;
|
|
103
|
+
/**
|
|
104
|
+
* Called when deleting a post fails
|
|
105
|
+
* @param error - The error that occurred
|
|
106
|
+
* @param context - Request context
|
|
107
|
+
*/
|
|
46
108
|
onDeletePostError?: (error: Error, context: BlogApiContext) => Promise<void> | void;
|
|
47
109
|
}
|
|
48
110
|
/**
|
|
@@ -173,12 +235,12 @@ declare const blogBackendPlugin: (hooks?: BlogBackendHooks) => _btst_stack_plugi
|
|
|
173
235
|
options: {
|
|
174
236
|
method: "POST";
|
|
175
237
|
body: z.ZodObject<{
|
|
176
|
-
title: z.ZodString;
|
|
177
238
|
slug: z.ZodOptional<z.ZodString>;
|
|
178
239
|
published: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
179
240
|
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
180
241
|
publishedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
181
242
|
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
243
|
+
title: z.ZodString;
|
|
182
244
|
content: z.ZodString;
|
|
183
245
|
excerpt: z.ZodString;
|
|
184
246
|
image: z.ZodOptional<z.ZodString>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as _btst_stack_plugins_api from '@btst/stack/plugins/api';
|
|
2
2
|
import * as better_call from 'better-call';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
import { c as createPostSchema, u as updatePostSchema, P as Post, T as Tag, S as SerializedPost, a as SerializedTag } from '../../shared/stack.
|
|
4
|
+
import { c as createPostSchema, u as updatePostSchema, P as Post, T as Tag, S as SerializedPost, a as SerializedTag } from '../../shared/stack.CoPoHVfV.js';
|
|
5
5
|
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
6
6
|
import { createApiClient } from '@btst/stack/plugins/client';
|
|
7
7
|
|
|
@@ -32,17 +32,79 @@ interface BlogApiContext<TBody = any, TParams = any, TQuery = any> {
|
|
|
32
32
|
* All hooks are optional and allow consumers to customize behavior
|
|
33
33
|
*/
|
|
34
34
|
interface BlogBackendHooks {
|
|
35
|
+
/**
|
|
36
|
+
* Called before listing posts. Return false to deny access.
|
|
37
|
+
* @param filter - Query parameters for filtering posts
|
|
38
|
+
* @param context - Request context with headers, etc.
|
|
39
|
+
*/
|
|
35
40
|
onBeforeListPosts?: (filter: z.infer<typeof PostListQuerySchema>, context: BlogApiContext) => Promise<boolean> | boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Called before creating a post. Return false to deny access.
|
|
43
|
+
* @param data - Post data being created
|
|
44
|
+
* @param context - Request context with headers, etc.
|
|
45
|
+
*/
|
|
36
46
|
onBeforeCreatePost?: (data: z.infer<typeof createPostSchema>, context: BlogApiContext) => Promise<boolean> | boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Called before updating a post. Return false to deny access.
|
|
49
|
+
* @param postId - ID of the post being updated
|
|
50
|
+
* @param data - Updated post data
|
|
51
|
+
* @param context - Request context with headers, etc.
|
|
52
|
+
*/
|
|
37
53
|
onBeforeUpdatePost?: (postId: string, data: z.infer<typeof updatePostSchema>, context: BlogApiContext) => Promise<boolean> | boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Called before deleting a post. Return false to deny access.
|
|
56
|
+
* @param postId - ID of the post being deleted
|
|
57
|
+
* @param context - Request context with headers, etc.
|
|
58
|
+
*/
|
|
38
59
|
onBeforeDeletePost?: (postId: string, context: BlogApiContext) => Promise<boolean> | boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Called after posts are read successfully
|
|
62
|
+
* @param posts - Array of posts that were read
|
|
63
|
+
* @param filter - Query parameters used for filtering
|
|
64
|
+
* @param context - Request context
|
|
65
|
+
*/
|
|
39
66
|
onPostsRead?: (posts: Post[], filter: z.infer<typeof PostListQuerySchema>, context: BlogApiContext) => Promise<void> | void;
|
|
67
|
+
/**
|
|
68
|
+
* Called after a post is created successfully
|
|
69
|
+
* @param post - The created post
|
|
70
|
+
* @param context - Request context
|
|
71
|
+
*/
|
|
40
72
|
onPostCreated?: (post: Post, context: BlogApiContext) => Promise<void> | void;
|
|
73
|
+
/**
|
|
74
|
+
* Called after a post is updated successfully
|
|
75
|
+
* @param post - The updated post
|
|
76
|
+
* @param context - Request context
|
|
77
|
+
*/
|
|
41
78
|
onPostUpdated?: (post: Post, context: BlogApiContext) => Promise<void> | void;
|
|
79
|
+
/**
|
|
80
|
+
* Called after a post is deleted successfully
|
|
81
|
+
* @param postId - ID of the deleted post
|
|
82
|
+
* @param context - Request context
|
|
83
|
+
*/
|
|
42
84
|
onPostDeleted?: (postId: string, context: BlogApiContext) => Promise<void> | void;
|
|
85
|
+
/**
|
|
86
|
+
* Called when listing posts fails
|
|
87
|
+
* @param error - The error that occurred
|
|
88
|
+
* @param context - Request context
|
|
89
|
+
*/
|
|
43
90
|
onListPostsError?: (error: Error, context: BlogApiContext) => Promise<void> | void;
|
|
91
|
+
/**
|
|
92
|
+
* Called when creating a post fails
|
|
93
|
+
* @param error - The error that occurred
|
|
94
|
+
* @param context - Request context
|
|
95
|
+
*/
|
|
44
96
|
onCreatePostError?: (error: Error, context: BlogApiContext) => Promise<void> | void;
|
|
97
|
+
/**
|
|
98
|
+
* Called when updating a post fails
|
|
99
|
+
* @param error - The error that occurred
|
|
100
|
+
* @param context - Request context
|
|
101
|
+
*/
|
|
45
102
|
onUpdatePostError?: (error: Error, context: BlogApiContext) => Promise<void> | void;
|
|
103
|
+
/**
|
|
104
|
+
* Called when deleting a post fails
|
|
105
|
+
* @param error - The error that occurred
|
|
106
|
+
* @param context - Request context
|
|
107
|
+
*/
|
|
46
108
|
onDeletePostError?: (error: Error, context: BlogApiContext) => Promise<void> | void;
|
|
47
109
|
}
|
|
48
110
|
/**
|
|
@@ -173,12 +235,12 @@ declare const blogBackendPlugin: (hooks?: BlogBackendHooks) => _btst_stack_plugi
|
|
|
173
235
|
options: {
|
|
174
236
|
method: "POST";
|
|
175
237
|
body: z.ZodObject<{
|
|
176
|
-
title: z.ZodString;
|
|
177
238
|
slug: z.ZodOptional<z.ZodString>;
|
|
178
239
|
published: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
179
240
|
createdAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
180
241
|
publishedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
181
242
|
updatedAt: z.ZodOptional<z.ZodCoercedDate<unknown>>;
|
|
243
|
+
title: z.ZodString;
|
|
182
244
|
content: z.ZodString;
|
|
183
245
|
excerpt: z.ZodString;
|
|
184
246
|
image: z.ZodOptional<z.ZodString>;
|
package/package.json
CHANGED
|
@@ -55,6 +55,19 @@ export function RouteRenderer({
|
|
|
55
55
|
);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Renders a route with Suspense and ErrorBoundary wrappers.
|
|
60
|
+
* Handles loading states, error boundaries, and not-found scenarios for a single route.
|
|
61
|
+
*
|
|
62
|
+
* @param path - The current route path
|
|
63
|
+
* @param PageComponent - The page component to render
|
|
64
|
+
* @param ErrorComponent - Optional error fallback component
|
|
65
|
+
* @param LoadingComponent - Component to show during suspense
|
|
66
|
+
* @param onNotFound - Optional callback when route is not found
|
|
67
|
+
* @param NotFoundComponent - Optional component to show for 404s
|
|
68
|
+
* @param props - Additional props to pass to the page component
|
|
69
|
+
* @param onError - Error handler callback for the error boundary
|
|
70
|
+
*/
|
|
58
71
|
export function ComposedRoute({
|
|
59
72
|
path,
|
|
60
73
|
PageComponent,
|
|
@@ -7,6 +7,15 @@ import {
|
|
|
7
7
|
|
|
8
8
|
export type { FallbackProps } from "react-error-boundary";
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Error boundary wrapper component for catching and handling React errors.
|
|
12
|
+
* Wraps react-error-boundary with a simplified API.
|
|
13
|
+
*
|
|
14
|
+
* @param children - Child components to wrap with error boundary
|
|
15
|
+
* @param FallbackComponent - Component to render when an error occurs
|
|
16
|
+
* @param resetKeys - Array of values that will reset the error boundary when changed
|
|
17
|
+
* @param onError - Callback invoked when an error is caught
|
|
18
|
+
*/
|
|
10
19
|
export function ErrorBoundary({
|
|
11
20
|
children,
|
|
12
21
|
FallbackComponent,
|
package/src/context/provider.tsx
CHANGED
|
@@ -75,8 +75,16 @@ export function BetterStackProvider<
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
/**
|
|
78
|
-
* Hook to access the entire context
|
|
78
|
+
* Hook to access the entire BetterStack context
|
|
79
79
|
* Useful if you need access to multiple plugins or the full context
|
|
80
|
+
*
|
|
81
|
+
* @returns The full context value including overrides and basePath
|
|
82
|
+
* @throws Error if used outside of BetterStackProvider
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```tsx
|
|
86
|
+
* const { overrides, basePath } = useBetterStack<MyPluginOverrides>();
|
|
87
|
+
* ```
|
|
80
88
|
*/
|
|
81
89
|
export function useBetterStack<
|
|
82
90
|
TPluginOverrides extends Record<string, any> = Record<string, any>,
|
|
@@ -145,6 +153,18 @@ export function usePluginOverrides<
|
|
|
145
153
|
return overrides as OverridesResult<TOverrides, TDefaults>;
|
|
146
154
|
}
|
|
147
155
|
|
|
156
|
+
/**
|
|
157
|
+
* Hook to access the base path where the client router is mounted
|
|
158
|
+
*
|
|
159
|
+
* @returns The base path string (e.g., "/pages")
|
|
160
|
+
* @throws Error if used outside of BetterStackProvider
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* ```tsx
|
|
164
|
+
* const basePath = useBasePath();
|
|
165
|
+
* // basePath = "/pages"
|
|
166
|
+
* ```
|
|
167
|
+
*/
|
|
148
168
|
export function useBasePath() {
|
|
149
169
|
const context = useBetterStack();
|
|
150
170
|
if (!context) {
|
|
@@ -45,51 +45,110 @@ export interface BlogApiContext<TBody = any, TParams = any, TQuery = any> {
|
|
|
45
45
|
* All hooks are optional and allow consumers to customize behavior
|
|
46
46
|
*/
|
|
47
47
|
export interface BlogBackendHooks {
|
|
48
|
-
|
|
48
|
+
/**
|
|
49
|
+
* Called before listing posts. Return false to deny access.
|
|
50
|
+
* @param filter - Query parameters for filtering posts
|
|
51
|
+
* @param context - Request context with headers, etc.
|
|
52
|
+
*/
|
|
49
53
|
onBeforeListPosts?: (
|
|
50
54
|
filter: z.infer<typeof PostListQuerySchema>,
|
|
51
55
|
context: BlogApiContext,
|
|
52
56
|
) => Promise<boolean> | boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Called before creating a post. Return false to deny access.
|
|
59
|
+
* @param data - Post data being created
|
|
60
|
+
* @param context - Request context with headers, etc.
|
|
61
|
+
*/
|
|
53
62
|
onBeforeCreatePost?: (
|
|
54
63
|
data: z.infer<typeof createPostSchema>,
|
|
55
64
|
context: BlogApiContext,
|
|
56
65
|
) => Promise<boolean> | boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Called before updating a post. Return false to deny access.
|
|
68
|
+
* @param postId - ID of the post being updated
|
|
69
|
+
* @param data - Updated post data
|
|
70
|
+
* @param context - Request context with headers, etc.
|
|
71
|
+
*/
|
|
57
72
|
onBeforeUpdatePost?: (
|
|
58
73
|
postId: string,
|
|
59
74
|
data: z.infer<typeof updatePostSchema>,
|
|
60
75
|
context: BlogApiContext,
|
|
61
76
|
) => Promise<boolean> | boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Called before deleting a post. Return false to deny access.
|
|
79
|
+
* @param postId - ID of the post being deleted
|
|
80
|
+
* @param context - Request context with headers, etc.
|
|
81
|
+
*/
|
|
62
82
|
onBeforeDeletePost?: (
|
|
63
83
|
postId: string,
|
|
64
84
|
context: BlogApiContext,
|
|
65
85
|
) => Promise<boolean> | boolean;
|
|
66
86
|
|
|
67
|
-
|
|
87
|
+
/**
|
|
88
|
+
* Called after posts are read successfully
|
|
89
|
+
* @param posts - Array of posts that were read
|
|
90
|
+
* @param filter - Query parameters used for filtering
|
|
91
|
+
* @param context - Request context
|
|
92
|
+
*/
|
|
68
93
|
onPostsRead?: (
|
|
69
94
|
posts: Post[],
|
|
70
95
|
filter: z.infer<typeof PostListQuerySchema>,
|
|
71
96
|
context: BlogApiContext,
|
|
72
97
|
) => Promise<void> | void;
|
|
98
|
+
/**
|
|
99
|
+
* Called after a post is created successfully
|
|
100
|
+
* @param post - The created post
|
|
101
|
+
* @param context - Request context
|
|
102
|
+
*/
|
|
73
103
|
onPostCreated?: (post: Post, context: BlogApiContext) => Promise<void> | void;
|
|
104
|
+
/**
|
|
105
|
+
* Called after a post is updated successfully
|
|
106
|
+
* @param post - The updated post
|
|
107
|
+
* @param context - Request context
|
|
108
|
+
*/
|
|
74
109
|
onPostUpdated?: (post: Post, context: BlogApiContext) => Promise<void> | void;
|
|
110
|
+
/**
|
|
111
|
+
* Called after a post is deleted successfully
|
|
112
|
+
* @param postId - ID of the deleted post
|
|
113
|
+
* @param context - Request context
|
|
114
|
+
*/
|
|
75
115
|
onPostDeleted?: (
|
|
76
116
|
postId: string,
|
|
77
117
|
context: BlogApiContext,
|
|
78
118
|
) => Promise<void> | void;
|
|
79
119
|
|
|
80
|
-
|
|
120
|
+
/**
|
|
121
|
+
* Called when listing posts fails
|
|
122
|
+
* @param error - The error that occurred
|
|
123
|
+
* @param context - Request context
|
|
124
|
+
*/
|
|
81
125
|
onListPostsError?: (
|
|
82
126
|
error: Error,
|
|
83
127
|
context: BlogApiContext,
|
|
84
128
|
) => Promise<void> | void;
|
|
129
|
+
/**
|
|
130
|
+
* Called when creating a post fails
|
|
131
|
+
* @param error - The error that occurred
|
|
132
|
+
* @param context - Request context
|
|
133
|
+
*/
|
|
85
134
|
onCreatePostError?: (
|
|
86
135
|
error: Error,
|
|
87
136
|
context: BlogApiContext,
|
|
88
137
|
) => Promise<void> | void;
|
|
138
|
+
/**
|
|
139
|
+
* Called when updating a post fails
|
|
140
|
+
* @param error - The error that occurred
|
|
141
|
+
* @param context - Request context
|
|
142
|
+
*/
|
|
89
143
|
onUpdatePostError?: (
|
|
90
144
|
error: Error,
|
|
91
145
|
context: BlogApiContext,
|
|
92
146
|
) => Promise<void> | void;
|
|
147
|
+
/**
|
|
148
|
+
* Called when deleting a post fails
|
|
149
|
+
* @param error - The error that occurred
|
|
150
|
+
* @param context - Request context
|
|
151
|
+
*/
|
|
93
152
|
onDeletePostError?: (
|
|
94
153
|
error: Error,
|
|
95
154
|
context: BlogApiContext,
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
SelectTrigger,
|
|
13
13
|
SelectValue,
|
|
14
14
|
} from "@workspace/ui/components/select";
|
|
15
|
+
import { TextAlignStart } from "lucide-react";
|
|
15
16
|
|
|
16
17
|
interface Heading {
|
|
17
18
|
id: string;
|
|
@@ -62,8 +63,9 @@ export function OnThisPage({ markdown, className }: OnThisPageProps) {
|
|
|
62
63
|
aria-label="Table of contents"
|
|
63
64
|
>
|
|
64
65
|
<div className="overflow-y-auto px-2">
|
|
65
|
-
<div className="flex flex-col gap-
|
|
66
|
-
<p className="font-semibold text-muted-foreground sticky top-0 h-6 text-xs">
|
|
66
|
+
<div className="flex flex-col gap-1 p-4 pt-0 text-sm">
|
|
67
|
+
<p className="flex items-center gap-2 font-semibold text-muted-foreground sticky top-0 h-6 text-xs">
|
|
68
|
+
<TextAlignStart className="w-3 h-3" />{" "}
|
|
67
69
|
{localization.BLOG_POST_ON_THIS_PAGE}
|
|
68
70
|
</p>
|
|
69
71
|
{headings.map(({ id, text, level }) => {
|