@htlkg/astro 0.0.1 → 0.0.3
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 +24 -8
- package/dist/chunk-2GML443T.js +273 -0
- package/dist/chunk-2GML443T.js.map +1 -0
- package/dist/{chunk-Z2ZAL7KX.js → chunk-UBF5F2RG.js} +1 -1
- package/dist/{chunk-Z2ZAL7KX.js.map → chunk-UBF5F2RG.js.map} +1 -1
- package/dist/chunk-XOY5BM3N.js +151 -0
- package/dist/chunk-XOY5BM3N.js.map +1 -0
- package/dist/htlkg/config.js +1 -1
- package/dist/htlkg/index.js +1 -1
- package/dist/index.js +126 -14
- package/dist/index.js.map +1 -1
- package/dist/middleware/index.js +27 -28
- package/dist/middleware/index.js.map +1 -1
- package/dist/utils/index.js +31 -12
- package/dist/vue-app-setup.js +47 -0
- package/dist/vue-app-setup.js.map +1 -0
- package/package.json +60 -26
- package/src/auth/auth.md +77 -0
- package/src/components/Island.astro +56 -0
- package/src/components/components.md +79 -0
- package/src/factories/createListPage.ts +290 -0
- package/src/factories/index.ts +16 -0
- package/src/htlkg/config.ts +10 -0
- package/src/htlkg/htlkg.md +63 -0
- package/src/htlkg/index.ts +49 -157
- package/src/index.ts +3 -0
- package/src/layouts/AdminLayout.astro +103 -92
- package/src/layouts/layouts.md +87 -0
- package/src/middleware/auth.ts +42 -0
- package/src/middleware/middleware.md +82 -0
- package/src/middleware/route-guards.ts +4 -28
- package/src/patterns/patterns.md +104 -0
- package/src/utils/filters.ts +320 -0
- package/src/utils/index.ts +8 -2
- package/src/utils/params.ts +260 -0
- package/src/utils/utils.md +86 -0
- package/src/vue-app-setup.ts +21 -28
- package/dist/chunk-WLOFOVCL.js +0 -210
- package/dist/chunk-WLOFOVCL.js.map +0 -1
- package/dist/chunk-ZQ4XMJH7.js +0 -1
- package/dist/chunk-ZQ4XMJH7.js.map +0 -1
package/src/auth/auth.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Auth Module
|
|
2
|
+
|
|
3
|
+
Authentication pages and components.
|
|
4
|
+
|
|
5
|
+
## Components
|
|
6
|
+
|
|
7
|
+
### LoginPage
|
|
8
|
+
|
|
9
|
+
Full login page with form and error handling.
|
|
10
|
+
|
|
11
|
+
```astro
|
|
12
|
+
---
|
|
13
|
+
import { LoginPage } from '@htlkg/astro/auth';
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<LoginPage
|
|
17
|
+
redirectTo="/admin"
|
|
18
|
+
logoUrl="/logo.svg"
|
|
19
|
+
/>
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### LoginForm
|
|
23
|
+
|
|
24
|
+
Vue component for login form (used within LoginPage).
|
|
25
|
+
|
|
26
|
+
```vue
|
|
27
|
+
<script setup>
|
|
28
|
+
import { LoginForm } from '@htlkg/astro/auth';
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<template>
|
|
32
|
+
<LoginForm
|
|
33
|
+
@success="handleSuccess"
|
|
34
|
+
@error="handleError"
|
|
35
|
+
/>
|
|
36
|
+
</template>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Usage
|
|
40
|
+
|
|
41
|
+
The auth module is typically used with the htlkg integration which automatically injects the login page:
|
|
42
|
+
|
|
43
|
+
```javascript
|
|
44
|
+
// astro.config.mjs
|
|
45
|
+
import { htlkg } from '@htlkg/astro';
|
|
46
|
+
|
|
47
|
+
export default defineConfig({
|
|
48
|
+
integrations: [
|
|
49
|
+
htlkg({
|
|
50
|
+
auth: {
|
|
51
|
+
enabled: true,
|
|
52
|
+
loginPage: '/login',
|
|
53
|
+
},
|
|
54
|
+
}),
|
|
55
|
+
],
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Customization
|
|
60
|
+
|
|
61
|
+
Create a custom login page:
|
|
62
|
+
|
|
63
|
+
```astro
|
|
64
|
+
---
|
|
65
|
+
// src/pages/login.astro
|
|
66
|
+
import { AuthLayout } from '@htlkg/astro/layouts';
|
|
67
|
+
import { LoginForm } from '@htlkg/astro/auth';
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
<AuthLayout title="Sign In">
|
|
71
|
+
<div class="custom-login">
|
|
72
|
+
<img src="/logo.svg" alt="Logo" />
|
|
73
|
+
<h1>Welcome Back</h1>
|
|
74
|
+
<LoginForm client:load />
|
|
75
|
+
</div>
|
|
76
|
+
</AuthLayout>
|
|
77
|
+
```
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* Island Component
|
|
4
|
+
*
|
|
5
|
+
* A wrapper component for Vue islands that handles:
|
|
6
|
+
* - Automatic nanostore synchronization from server to client
|
|
7
|
+
* - Hydration strategy selection
|
|
8
|
+
* - Props forwarding
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```astro
|
|
12
|
+
* <Island
|
|
13
|
+
* component={AccountsPage}
|
|
14
|
+
* data={{ accounts }}
|
|
15
|
+
* stores={{ accounts: $accounts }}
|
|
16
|
+
* hydration="load"
|
|
17
|
+
* />
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import type { Component } from "vue";
|
|
22
|
+
import type { WritableAtom } from "nanostores";
|
|
23
|
+
|
|
24
|
+
interface Props {
|
|
25
|
+
/** Vue component to render */
|
|
26
|
+
component: Component;
|
|
27
|
+
/** Data to sync to stores */
|
|
28
|
+
data?: Record<string, any>;
|
|
29
|
+
/** Store mapping { dataKey: storeAtom } */
|
|
30
|
+
stores?: Record<string, WritableAtom<any>>;
|
|
31
|
+
/** Hydration strategy */
|
|
32
|
+
hydration?: "load" | "idle" | "visible" | "only";
|
|
33
|
+
/** Additional props to pass to the component */
|
|
34
|
+
props?: Record<string, any>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const {
|
|
38
|
+
component: Component,
|
|
39
|
+
data = {},
|
|
40
|
+
stores = {},
|
|
41
|
+
hydration = "load",
|
|
42
|
+
props = {},
|
|
43
|
+
} = Astro.props;
|
|
44
|
+
|
|
45
|
+
// Auto-sync data to stores on server-side
|
|
46
|
+
for (const [key, store] of Object.entries(stores)) {
|
|
47
|
+
if (data[key] !== undefined) {
|
|
48
|
+
store.set(data[key]);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
{hydration === "load" && <Component client:load {...props} />}
|
|
54
|
+
{hydration === "idle" && <Component client:idle {...props} />}
|
|
55
|
+
{hydration === "visible" && <Component client:visible {...props} />}
|
|
56
|
+
{hydration === "only" && <Component client:only="vue" {...props} />}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Components Module
|
|
2
|
+
|
|
3
|
+
Astro components for page structure and navigation.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { Sidebar } from '@htlkg/astro/components';
|
|
9
|
+
import { Topbar } from '@htlkg/astro/components';
|
|
10
|
+
import { PageHeader } from '@htlkg/astro/components';
|
|
11
|
+
import { Island } from '@htlkg/astro/components';
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Sidebar
|
|
15
|
+
|
|
16
|
+
Navigation sidebar for admin layouts.
|
|
17
|
+
|
|
18
|
+
```astro
|
|
19
|
+
---
|
|
20
|
+
import { Sidebar } from '@htlkg/astro/components';
|
|
21
|
+
|
|
22
|
+
const navItems = [
|
|
23
|
+
{ label: 'Dashboard', href: '/admin', icon: 'home' },
|
|
24
|
+
{ label: 'Brands', href: '/admin/brands', icon: 'building' },
|
|
25
|
+
{ label: 'Users', href: '/admin/users', icon: 'users' },
|
|
26
|
+
];
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
<Sidebar items={navItems} currentPath={Astro.url.pathname} />
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Topbar
|
|
33
|
+
|
|
34
|
+
Top navigation bar with user menu.
|
|
35
|
+
|
|
36
|
+
```astro
|
|
37
|
+
---
|
|
38
|
+
import { Topbar } from '@htlkg/astro/components';
|
|
39
|
+
|
|
40
|
+
const user = Astro.locals.user;
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
<Topbar user={user} title="Admin Portal" />
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## PageHeader
|
|
47
|
+
|
|
48
|
+
Page header with title, breadcrumbs, and actions.
|
|
49
|
+
|
|
50
|
+
```astro
|
|
51
|
+
---
|
|
52
|
+
import { PageHeader } from '@htlkg/astro/components';
|
|
53
|
+
|
|
54
|
+
const breadcrumbs = [
|
|
55
|
+
{ label: 'Admin', href: '/admin' },
|
|
56
|
+
{ label: 'Brands', href: '/admin/brands' },
|
|
57
|
+
];
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
<PageHeader
|
|
61
|
+
title="Brands"
|
|
62
|
+
breadcrumbs={breadcrumbs}
|
|
63
|
+
>
|
|
64
|
+
<button slot="actions">Add Brand</button>
|
|
65
|
+
</PageHeader>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Island
|
|
69
|
+
|
|
70
|
+
Wrapper for client-side Vue components with hydration control.
|
|
71
|
+
|
|
72
|
+
```astro
|
|
73
|
+
---
|
|
74
|
+
import { Island } from '@htlkg/astro/components';
|
|
75
|
+
import BrandList from '@/components/BrandList.vue';
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
<Island component={BrandList} client:load props={{ brands }} />
|
|
79
|
+
```
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* List Page Factory
|
|
3
|
+
*
|
|
4
|
+
* Factory function for creating standardized list pages with automatic
|
|
5
|
+
* data fetching, filtering, sorting, and pagination.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { AstroGlobal } from "astro";
|
|
9
|
+
import type { WritableAtom } from "nanostores";
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
parseListParams,
|
|
13
|
+
type ListParams,
|
|
14
|
+
type ListParamConfig,
|
|
15
|
+
type FilterFieldConfig,
|
|
16
|
+
} from "../utils/params";
|
|
17
|
+
import {
|
|
18
|
+
buildGraphQLFilter,
|
|
19
|
+
applyClientFilters,
|
|
20
|
+
sortItems,
|
|
21
|
+
paginateItems,
|
|
22
|
+
} from "../utils/filters";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Breadcrumb item
|
|
26
|
+
*/
|
|
27
|
+
export interface BreadcrumbItem {
|
|
28
|
+
label: string;
|
|
29
|
+
href?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Layout props returned by the factory
|
|
34
|
+
*/
|
|
35
|
+
export interface LayoutProps {
|
|
36
|
+
title: string;
|
|
37
|
+
description?: string;
|
|
38
|
+
currentPage: string;
|
|
39
|
+
breadcrumbs: BreadcrumbItem[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Table initial state
|
|
44
|
+
*/
|
|
45
|
+
export interface TableInitialState {
|
|
46
|
+
currentPage: number;
|
|
47
|
+
pageSize: number;
|
|
48
|
+
sortKey: string;
|
|
49
|
+
sortOrder: "asc" | "desc";
|
|
50
|
+
totalItems: number;
|
|
51
|
+
totalPages: number;
|
|
52
|
+
filters: Record<string, any>;
|
|
53
|
+
search?: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Related store configuration
|
|
58
|
+
*/
|
|
59
|
+
export interface RelatedStoreConfig<T = any> {
|
|
60
|
+
store: WritableAtom<T[]>;
|
|
61
|
+
fetch: () => Promise<T[]>;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Configuration for createListPage
|
|
66
|
+
*/
|
|
67
|
+
export interface ListPageConfig<T> {
|
|
68
|
+
// Page metadata
|
|
69
|
+
/** Page title */
|
|
70
|
+
title: string;
|
|
71
|
+
/** Page description */
|
|
72
|
+
description?: string;
|
|
73
|
+
/** Page identifier (for sidebar active state) */
|
|
74
|
+
pageId: string;
|
|
75
|
+
/** Custom breadcrumbs (auto-generated if not provided) */
|
|
76
|
+
breadcrumbs?: BreadcrumbItem[];
|
|
77
|
+
|
|
78
|
+
// Data fetching
|
|
79
|
+
/** Fetch function that retrieves data */
|
|
80
|
+
fetchFn: (params: {
|
|
81
|
+
filter: any;
|
|
82
|
+
limit?: number;
|
|
83
|
+
nextToken?: string;
|
|
84
|
+
}) => Promise<{ data: T[]; nextToken?: string | null }>;
|
|
85
|
+
|
|
86
|
+
// Data handling
|
|
87
|
+
/** Transform function to apply to fetched data */
|
|
88
|
+
transform?: (item: any) => T;
|
|
89
|
+
/** Main store to set with data */
|
|
90
|
+
store: WritableAtom<T[]>;
|
|
91
|
+
/** Related stores to populate */
|
|
92
|
+
relatedStores?: Record<string, RelatedStoreConfig>;
|
|
93
|
+
|
|
94
|
+
// Filtering/sorting config
|
|
95
|
+
/** Searchable field keys */
|
|
96
|
+
searchableFields?: string[];
|
|
97
|
+
/** Filterable field configurations */
|
|
98
|
+
filterableFields?: FilterFieldConfig[];
|
|
99
|
+
/** Sortable field keys (all by default) */
|
|
100
|
+
sortableFields?: string[];
|
|
101
|
+
/** Default sort configuration */
|
|
102
|
+
defaultSort?: { key: string; order: "asc" | "desc" };
|
|
103
|
+
/** Default page size */
|
|
104
|
+
defaultPageSize?: number;
|
|
105
|
+
/** Maximum items to fetch from API */
|
|
106
|
+
fetchLimit?: number;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Result from createListPage
|
|
111
|
+
*/
|
|
112
|
+
export interface ListPageResult<T> {
|
|
113
|
+
/** Props to spread to Layout component */
|
|
114
|
+
layoutProps: LayoutProps;
|
|
115
|
+
/** Initial state for table component */
|
|
116
|
+
initialState: TableInitialState;
|
|
117
|
+
/** Processed items (paginated) */
|
|
118
|
+
items: T[];
|
|
119
|
+
/** All items (pre-pagination, for client-side operations) */
|
|
120
|
+
allItems: T[];
|
|
121
|
+
/** Parsed URL parameters */
|
|
122
|
+
params: ListParams;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Default breadcrumb generator
|
|
127
|
+
*/
|
|
128
|
+
function generateBreadcrumbs(pageId: string, title: string): BreadcrumbItem[] {
|
|
129
|
+
return [
|
|
130
|
+
{ label: "Admin", href: "/admin" },
|
|
131
|
+
{ label: title },
|
|
132
|
+
];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Create a list page with automatic data handling
|
|
137
|
+
*
|
|
138
|
+
* This factory handles:
|
|
139
|
+
* - URL parameter parsing (page, pageSize, sortKey, sortOrder, filters)
|
|
140
|
+
* - Data fetching with GraphQL filter building
|
|
141
|
+
* - Data transformation
|
|
142
|
+
* - Client-side filtering (for computed fields)
|
|
143
|
+
* - Sorting
|
|
144
|
+
* - Pagination
|
|
145
|
+
* - Store population
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```astro
|
|
149
|
+
* ---
|
|
150
|
+
* import { createListPage } from '@htlkg/astro/factories';
|
|
151
|
+
* import { $accounts } from '@/stores/accounts';
|
|
152
|
+
*
|
|
153
|
+
* const { layoutProps, initialState, items } = await createListPage(Astro, {
|
|
154
|
+
* title: 'Accounts',
|
|
155
|
+
* pageId: 'accounts',
|
|
156
|
+
* store: $accounts,
|
|
157
|
+
*
|
|
158
|
+
* fetchFn: async ({ filter }) => {
|
|
159
|
+
* const client = getServerClient(Astro);
|
|
160
|
+
* return await client.models.Account.list({ filter });
|
|
161
|
+
* },
|
|
162
|
+
*
|
|
163
|
+
* transform: (account) => ({
|
|
164
|
+
* id: account.id,
|
|
165
|
+
* name: account.name,
|
|
166
|
+
* brandCount: account.brands?.length ?? 0,
|
|
167
|
+
* }),
|
|
168
|
+
*
|
|
169
|
+
* filterableFields: [
|
|
170
|
+
* { key: 'name', type: 'text', graphql: true },
|
|
171
|
+
* { key: 'status', type: 'select', graphql: true, options: ['active', 'inactive'] },
|
|
172
|
+
* ],
|
|
173
|
+
*
|
|
174
|
+
* defaultSort: { key: 'name', order: 'asc' },
|
|
175
|
+
* });
|
|
176
|
+
* ---
|
|
177
|
+
*
|
|
178
|
+
* <Layout {...layoutProps}>
|
|
179
|
+
* <AccountsTable client:load initialState={initialState} />
|
|
180
|
+
* </Layout>
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
export async function createListPage<T extends Record<string, any>>(
|
|
184
|
+
astro: AstroGlobal,
|
|
185
|
+
config: ListPageConfig<T>
|
|
186
|
+
): Promise<ListPageResult<T>> {
|
|
187
|
+
const {
|
|
188
|
+
title,
|
|
189
|
+
description,
|
|
190
|
+
pageId,
|
|
191
|
+
breadcrumbs,
|
|
192
|
+
fetchFn,
|
|
193
|
+
transform,
|
|
194
|
+
store,
|
|
195
|
+
relatedStores,
|
|
196
|
+
searchableFields,
|
|
197
|
+
filterableFields = [],
|
|
198
|
+
defaultSort,
|
|
199
|
+
defaultPageSize = 25,
|
|
200
|
+
fetchLimit = 1000,
|
|
201
|
+
} = config;
|
|
202
|
+
|
|
203
|
+
// 1. Parse URL parameters
|
|
204
|
+
const paramConfig: ListParamConfig = {
|
|
205
|
+
defaultPageSize,
|
|
206
|
+
defaultSort,
|
|
207
|
+
searchableFields,
|
|
208
|
+
filterableFields,
|
|
209
|
+
};
|
|
210
|
+
const params = parseListParams(astro.url, paramConfig);
|
|
211
|
+
|
|
212
|
+
// 2. Build GraphQL filter from URL params
|
|
213
|
+
const graphqlFilter = buildGraphQLFilter(params.filters, filterableFields, {
|
|
214
|
+
search: params.search,
|
|
215
|
+
searchFields: searchableFields,
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
// 3. Fetch data with pagination
|
|
219
|
+
let allItems: T[] = [];
|
|
220
|
+
let nextToken: string | null | undefined = undefined;
|
|
221
|
+
|
|
222
|
+
do {
|
|
223
|
+
const result = await fetchFn({
|
|
224
|
+
filter: graphqlFilter,
|
|
225
|
+
limit: fetchLimit,
|
|
226
|
+
nextToken: nextToken ?? undefined,
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
const data = result.data ?? [];
|
|
230
|
+
allItems = allItems.concat(data);
|
|
231
|
+
nextToken = result.nextToken;
|
|
232
|
+
} while (nextToken);
|
|
233
|
+
|
|
234
|
+
// 4. Transform data if needed
|
|
235
|
+
if (transform) {
|
|
236
|
+
allItems = allItems.map(transform);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// 5. Apply client-side filtering (for computed fields not in GraphQL)
|
|
240
|
+
allItems = applyClientFilters(allItems, params.filters, filterableFields, {
|
|
241
|
+
search: params.search,
|
|
242
|
+
searchFields: searchableFields,
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// 6. Sort
|
|
246
|
+
allItems = sortItems(allItems, params.sortKey, params.sortOrder);
|
|
247
|
+
|
|
248
|
+
// 7. Paginate
|
|
249
|
+
const { paginatedItems, totalItems, totalPages, currentPage, pageSize } = paginateItems(
|
|
250
|
+
allItems,
|
|
251
|
+
params.page,
|
|
252
|
+
params.pageSize
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
// 8. Set main store
|
|
256
|
+
store.set(paginatedItems);
|
|
257
|
+
|
|
258
|
+
// 9. Fetch and set related stores
|
|
259
|
+
if (relatedStores) {
|
|
260
|
+
await Promise.all(
|
|
261
|
+
Object.entries(relatedStores).map(async ([, config]) => {
|
|
262
|
+
const data = await config.fetch();
|
|
263
|
+
config.store.set(data);
|
|
264
|
+
})
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// 10. Build result
|
|
269
|
+
return {
|
|
270
|
+
layoutProps: {
|
|
271
|
+
title,
|
|
272
|
+
description,
|
|
273
|
+
currentPage: pageId,
|
|
274
|
+
breadcrumbs: breadcrumbs ?? generateBreadcrumbs(pageId, title),
|
|
275
|
+
},
|
|
276
|
+
initialState: {
|
|
277
|
+
currentPage,
|
|
278
|
+
pageSize,
|
|
279
|
+
sortKey: params.sortKey,
|
|
280
|
+
sortOrder: params.sortOrder,
|
|
281
|
+
totalItems,
|
|
282
|
+
totalPages,
|
|
283
|
+
filters: params.filters,
|
|
284
|
+
search: params.search,
|
|
285
|
+
},
|
|
286
|
+
items: paginatedItems,
|
|
287
|
+
allItems,
|
|
288
|
+
params,
|
|
289
|
+
};
|
|
290
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Page Factories for @htlkg/astro
|
|
3
|
+
*
|
|
4
|
+
* Factory functions for creating standardized Astro pages with automatic
|
|
5
|
+
* data handling, filtering, sorting, and pagination.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
createListPage,
|
|
10
|
+
type ListPageConfig,
|
|
11
|
+
type ListPageResult,
|
|
12
|
+
type LayoutProps,
|
|
13
|
+
type TableInitialState,
|
|
14
|
+
type BreadcrumbItem,
|
|
15
|
+
type RelatedStoreConfig,
|
|
16
|
+
} from "./createListPage";
|
package/src/htlkg/config.ts
CHANGED
|
@@ -209,6 +209,16 @@ export interface HtlkgIntegrationOptions {
|
|
|
209
209
|
* @default undefined (Tailwind enabled with default config)
|
|
210
210
|
*/
|
|
211
211
|
tailwind?: Record<string, unknown> | false;
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Vue app setup mode.
|
|
215
|
+
* - 'full': Use the Amplify-configured Vue app setup (requires SSR)
|
|
216
|
+
* - 'basic': Use basic Vue integration without Amplify app setup (works with static)
|
|
217
|
+
* - 'auto': Automatically detect based on output mode (default)
|
|
218
|
+
*
|
|
219
|
+
* @default 'auto'
|
|
220
|
+
*/
|
|
221
|
+
vueAppSetup?: 'full' | 'basic' | 'auto';
|
|
212
222
|
}
|
|
213
223
|
|
|
214
224
|
/**
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# htlkg Integration
|
|
2
|
+
|
|
3
|
+
Zero-config Astro integration for Hotelinking applications.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
// astro.config.mjs
|
|
9
|
+
import { defineConfig } from 'astro/config';
|
|
10
|
+
import { htlkg } from '@htlkg/astro';
|
|
11
|
+
|
|
12
|
+
export default defineConfig({
|
|
13
|
+
integrations: [
|
|
14
|
+
htlkg({
|
|
15
|
+
auth: {
|
|
16
|
+
enabled: true,
|
|
17
|
+
loginPage: '/login',
|
|
18
|
+
publicRoutes: ['/login', '/public'],
|
|
19
|
+
},
|
|
20
|
+
brandRoutes: {
|
|
21
|
+
enabled: true,
|
|
22
|
+
pattern: '/[brandId]',
|
|
23
|
+
},
|
|
24
|
+
}),
|
|
25
|
+
],
|
|
26
|
+
});
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Features
|
|
30
|
+
|
|
31
|
+
- Automatic middleware setup
|
|
32
|
+
- Route guard configuration
|
|
33
|
+
- Login page injection
|
|
34
|
+
- Brand route handling
|
|
35
|
+
- Virtual module configuration
|
|
36
|
+
|
|
37
|
+
## Options
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
interface HtlkgIntegrationOptions {
|
|
41
|
+
auth?: {
|
|
42
|
+
enabled: boolean;
|
|
43
|
+
loginPage?: string;
|
|
44
|
+
publicRoutes?: RoutePattern[];
|
|
45
|
+
protectedRoutes?: RoutePattern[];
|
|
46
|
+
};
|
|
47
|
+
brandRoutes?: {
|
|
48
|
+
enabled: boolean;
|
|
49
|
+
pattern?: string;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Virtual Modules
|
|
55
|
+
|
|
56
|
+
The integration provides virtual modules for configuration:
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
// Access config in your code
|
|
60
|
+
import config from 'virtual:htlkg-config';
|
|
61
|
+
|
|
62
|
+
console.log(config.auth.loginPage);
|
|
63
|
+
```
|