@htlkg/data 0.0.19 → 0.0.20
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/dist/client/index.d.ts +257 -1
- package/dist/client/index.js +59 -1
- package/dist/client/index.js.map +1 -1
- package/dist/common-DSxswsZ3.d.ts +40 -0
- package/dist/hooks/index.d.ts +75 -9
- package/dist/hooks/index.js +131 -33
- package/dist/hooks/index.js.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.js +351 -13
- package/dist/index.js.map +1 -1
- package/dist/mutations/index.d.ts +4 -2
- package/dist/mutations/index.js +200 -0
- package/dist/mutations/index.js.map +1 -1
- package/dist/{productInstances-BA3cNsYc.d.ts → productInstances-BpQv1oLS.d.ts} +2 -40
- package/dist/queries/index.d.ts +3 -0
- package/dist/queries/index.js +82 -0
- package/dist/queries/index.js.map +1 -1
- package/dist/reservations-C0FNm__0.d.ts +154 -0
- package/dist/reservations-CdDfkcZ_.d.ts +172 -0
- package/package.json +3 -3
- package/src/client/index.ts +18 -0
- package/src/client/reservations.ts +336 -0
- package/src/hooks/createDataHook.test.ts +534 -0
- package/src/hooks/createDataHook.ts +20 -13
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useReservations.ts +145 -0
- package/src/mutations/index.ts +14 -0
- package/src/mutations/productInstances/productInstances.test.ts +3 -3
- package/src/mutations/reservations.test.ts +459 -0
- package/src/mutations/reservations.ts +452 -0
- package/src/queries/index.ts +11 -0
- package/src/queries/reservations.test.ts +374 -0
- package/src/queries/reservations.ts +247 -0
package/dist/client/index.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { generateClient as generateClient$1 } from 'aws-amplify/data';
|
|
2
2
|
import { ResourcesConfig } from 'aws-amplify';
|
|
3
3
|
import { generateServerClientUsingCookies } from '../server/index.js';
|
|
4
|
+
import { C as CreateReservationInput, b as ReservationStatus, U as UpdateReservationInput } from '../reservations-CdDfkcZ_.js';
|
|
4
5
|
import 'astro';
|
|
5
6
|
import 'aws-amplify/api/internals';
|
|
7
|
+
import '../common-DSxswsZ3.js';
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* GraphQL Proxy Client
|
|
@@ -100,6 +102,260 @@ declare function hasErrors(response: GraphQLResponse): boolean;
|
|
|
100
102
|
*/
|
|
101
103
|
declare function getErrorMessage(response: GraphQLResponse): string | null;
|
|
102
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Type-safe Client-Side Reservation Operations
|
|
107
|
+
*
|
|
108
|
+
* Provides type-safe wrappers around the GraphQL proxy for reservation operations.
|
|
109
|
+
* These functions can be used directly in Vue components while maintaining type safety.
|
|
110
|
+
* Includes client-side validation for dates and status transitions.
|
|
111
|
+
*/
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Reservation type (simplified for client-side use)
|
|
115
|
+
*/
|
|
116
|
+
interface Reservation {
|
|
117
|
+
id: string;
|
|
118
|
+
brandId: string;
|
|
119
|
+
visitId: string;
|
|
120
|
+
confirmationCode: string;
|
|
121
|
+
checkIn: string;
|
|
122
|
+
checkOut: string;
|
|
123
|
+
status: ReservationStatus;
|
|
124
|
+
source?: string;
|
|
125
|
+
channel?: string;
|
|
126
|
+
roomType?: string;
|
|
127
|
+
room?: string;
|
|
128
|
+
totalAmount?: number;
|
|
129
|
+
currency?: string;
|
|
130
|
+
nights?: number;
|
|
131
|
+
deletedAt?: string;
|
|
132
|
+
deletedBy?: string;
|
|
133
|
+
createdAt?: string;
|
|
134
|
+
createdBy?: string;
|
|
135
|
+
updatedAt?: string;
|
|
136
|
+
updatedBy?: string;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Create a new reservation (client-side)
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```typescript
|
|
144
|
+
* import { createReservation } from '@htlkg/data/client';
|
|
145
|
+
*
|
|
146
|
+
* const result = await createReservation({
|
|
147
|
+
* brandId: 'brand-123',
|
|
148
|
+
* visitId: 'visit-456',
|
|
149
|
+
* confirmationCode: 'ABC123',
|
|
150
|
+
* checkIn: '2024-01-01',
|
|
151
|
+
* checkOut: '2024-01-05',
|
|
152
|
+
* status: 'confirmed'
|
|
153
|
+
* });
|
|
154
|
+
*
|
|
155
|
+
* if (!result.errors) {
|
|
156
|
+
* console.log('Created:', result.data);
|
|
157
|
+
* }
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
160
|
+
declare function createReservation(input: CreateReservationInput): Promise<GraphQLResponse<Reservation>>;
|
|
161
|
+
/**
|
|
162
|
+
* Update an existing reservation (client-side)
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* ```typescript
|
|
166
|
+
* import { updateReservation } from '@htlkg/data/client';
|
|
167
|
+
*
|
|
168
|
+
* const result = await updateReservation({
|
|
169
|
+
* id: 'reservation-123',
|
|
170
|
+
* status: 'checked_in',
|
|
171
|
+
* room: '201'
|
|
172
|
+
* });
|
|
173
|
+
*
|
|
174
|
+
* if (!result.errors) {
|
|
175
|
+
* console.log('Updated:', result.data);
|
|
176
|
+
* }
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
declare function updateReservation(input: UpdateReservationInput): Promise<GraphQLResponse<Reservation>>;
|
|
180
|
+
/**
|
|
181
|
+
* Soft delete a reservation (sets deletedAt/deletedBy)
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* ```typescript
|
|
185
|
+
* import { softDeleteReservation } from '@htlkg/data/client';
|
|
186
|
+
*
|
|
187
|
+
* const result = await softDeleteReservation('reservation-123', 'admin@example.com');
|
|
188
|
+
*
|
|
189
|
+
* if (!result.errors) {
|
|
190
|
+
* console.log('Soft deleted');
|
|
191
|
+
* }
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
declare function softDeleteReservation(id: string, deletedBy: string): Promise<GraphQLResponse<Reservation>>;
|
|
195
|
+
/**
|
|
196
|
+
* Restore a soft-deleted reservation
|
|
197
|
+
*
|
|
198
|
+
* @example
|
|
199
|
+
* ```typescript
|
|
200
|
+
* import { restoreReservation } from '@htlkg/data/client';
|
|
201
|
+
*
|
|
202
|
+
* const result = await restoreReservation('reservation-123');
|
|
203
|
+
*
|
|
204
|
+
* if (!result.errors) {
|
|
205
|
+
* console.log('Restored');
|
|
206
|
+
* }
|
|
207
|
+
* ```
|
|
208
|
+
*/
|
|
209
|
+
declare function restoreReservation(id: string): Promise<GraphQLResponse<Reservation>>;
|
|
210
|
+
/**
|
|
211
|
+
* Permanently delete a reservation (removes from database)
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ```typescript
|
|
215
|
+
* import { deleteReservation } from '@htlkg/data/client';
|
|
216
|
+
*
|
|
217
|
+
* const result = await deleteReservation('reservation-123');
|
|
218
|
+
*
|
|
219
|
+
* if (!result.errors) {
|
|
220
|
+
* console.log('Permanently deleted');
|
|
221
|
+
* }
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
declare function deleteReservation(id: string): Promise<GraphQLResponse<Reservation>>;
|
|
225
|
+
/**
|
|
226
|
+
* Get a single reservation by ID
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* ```typescript
|
|
230
|
+
* import { getReservation } from '@htlkg/data/client';
|
|
231
|
+
*
|
|
232
|
+
* const result = await getReservation('reservation-123');
|
|
233
|
+
*
|
|
234
|
+
* if (!result.errors && result.data) {
|
|
235
|
+
* console.log('Reservation:', result.data);
|
|
236
|
+
* }
|
|
237
|
+
* ```
|
|
238
|
+
*/
|
|
239
|
+
declare function getReservation(id: string): Promise<GraphQLResponse<Reservation>>;
|
|
240
|
+
/**
|
|
241
|
+
* List reservations with optional filters
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* ```typescript
|
|
245
|
+
* import { listReservations } from '@htlkg/data/client';
|
|
246
|
+
*
|
|
247
|
+
* const result = await listReservations({
|
|
248
|
+
* filter: { brandId: { eq: 'brand-123' } },
|
|
249
|
+
* limit: 100
|
|
250
|
+
* });
|
|
251
|
+
*
|
|
252
|
+
* if (!result.errors && result.data) {
|
|
253
|
+
* console.log('Reservations:', result.data);
|
|
254
|
+
* }
|
|
255
|
+
* ```
|
|
256
|
+
*/
|
|
257
|
+
declare function listReservations(options?: {
|
|
258
|
+
filter?: Record<string, any>;
|
|
259
|
+
limit?: number;
|
|
260
|
+
nextToken?: string;
|
|
261
|
+
selectionSet?: string[];
|
|
262
|
+
}): Promise<GraphQLResponse<Reservation[]>>;
|
|
263
|
+
/**
|
|
264
|
+
* Update reservation status (with server-side validation)
|
|
265
|
+
*
|
|
266
|
+
* The server will validate status transitions:
|
|
267
|
+
* - confirmed → checked_in, cancelled, no_show
|
|
268
|
+
* - checked_in → checked_out, cancelled
|
|
269
|
+
* - checked_out, cancelled, no_show → (terminal states, no transitions)
|
|
270
|
+
*
|
|
271
|
+
* @example
|
|
272
|
+
* ```typescript
|
|
273
|
+
* import { updateReservationStatus } from '@htlkg/data/client';
|
|
274
|
+
*
|
|
275
|
+
* const result = await updateReservationStatus('reservation-123', 'checked_in');
|
|
276
|
+
*
|
|
277
|
+
* if (!result.errors) {
|
|
278
|
+
* console.log('Status updated');
|
|
279
|
+
* } else {
|
|
280
|
+
* console.error('Status transition not allowed:', result.errors[0].message);
|
|
281
|
+
* }
|
|
282
|
+
* ```
|
|
283
|
+
*/
|
|
284
|
+
declare function updateReservationStatus(id: string, status: ReservationStatus): Promise<GraphQLResponse<Reservation>>;
|
|
285
|
+
/**
|
|
286
|
+
* Bulk soft delete reservations
|
|
287
|
+
*
|
|
288
|
+
* @example
|
|
289
|
+
* ```typescript
|
|
290
|
+
* import { bulkSoftDeleteReservations } from '@htlkg/data/client';
|
|
291
|
+
*
|
|
292
|
+
* const results = await bulkSoftDeleteReservations(
|
|
293
|
+
* ['res-1', 'res-2', 'res-3'],
|
|
294
|
+
* 'admin@example.com'
|
|
295
|
+
* );
|
|
296
|
+
*
|
|
297
|
+
* results.forEach(result => {
|
|
298
|
+
* if (!result.errors) console.log('Deleted:', result.data?.id);
|
|
299
|
+
* });
|
|
300
|
+
* ```
|
|
301
|
+
*/
|
|
302
|
+
declare function bulkSoftDeleteReservations(ids: string[], deletedBy: string): Promise<GraphQLResponse<Reservation>[]>;
|
|
303
|
+
/**
|
|
304
|
+
* Bulk restore reservations
|
|
305
|
+
*
|
|
306
|
+
* @example
|
|
307
|
+
* ```typescript
|
|
308
|
+
* import { bulkRestoreReservations } from '@htlkg/data/client';
|
|
309
|
+
*
|
|
310
|
+
* const results = await bulkRestoreReservations(['res-1', 'res-2', 'res-3']);
|
|
311
|
+
*
|
|
312
|
+
* results.forEach(result => {
|
|
313
|
+
* if (!result.errors) console.log('Restored:', result.data?.id);
|
|
314
|
+
* });
|
|
315
|
+
* ```
|
|
316
|
+
*/
|
|
317
|
+
declare function bulkRestoreReservations(ids: string[]): Promise<GraphQLResponse<Reservation>[]>;
|
|
318
|
+
/**
|
|
319
|
+
* Bulk permanently delete reservations
|
|
320
|
+
*
|
|
321
|
+
* @example
|
|
322
|
+
* ```typescript
|
|
323
|
+
* import { bulkDeleteReservations } from '@htlkg/data/client';
|
|
324
|
+
*
|
|
325
|
+
* const results = await bulkDeleteReservations(['res-1', 'res-2', 'res-3']);
|
|
326
|
+
*
|
|
327
|
+
* results.forEach(result => {
|
|
328
|
+
* if (!result.errors) console.log('Permanently deleted:', result.data?.id);
|
|
329
|
+
* });
|
|
330
|
+
* ```
|
|
331
|
+
*/
|
|
332
|
+
declare function bulkDeleteReservations(ids: string[]): Promise<GraphQLResponse<Reservation>[]>;
|
|
333
|
+
/**
|
|
334
|
+
* Bulk update reservation status (with server-side validation per reservation)
|
|
335
|
+
*
|
|
336
|
+
* Note: Each reservation's status transition is validated independently.
|
|
337
|
+
* Some may succeed while others fail if their current status doesn't allow the transition.
|
|
338
|
+
*
|
|
339
|
+
* @example
|
|
340
|
+
* ```typescript
|
|
341
|
+
* import { bulkUpdateReservationStatus } from '@htlkg/data/client';
|
|
342
|
+
*
|
|
343
|
+
* const results = await bulkUpdateReservationStatus(
|
|
344
|
+
* ['res-1', 'res-2', 'res-3'],
|
|
345
|
+
* 'checked_in'
|
|
346
|
+
* );
|
|
347
|
+
*
|
|
348
|
+
* results.forEach(result => {
|
|
349
|
+
* if (!result.errors) {
|
|
350
|
+
* console.log('Updated:', result.data?.id);
|
|
351
|
+
* } else {
|
|
352
|
+
* console.error('Failed:', result.errors[0].message);
|
|
353
|
+
* }
|
|
354
|
+
* });
|
|
355
|
+
* ```
|
|
356
|
+
*/
|
|
357
|
+
declare function bulkUpdateReservationStatus(ids: string[], status: ReservationStatus): Promise<GraphQLResponse<Reservation>[]>;
|
|
358
|
+
|
|
103
359
|
/**
|
|
104
360
|
* GraphQL Client for @htlkg/data
|
|
105
361
|
*
|
|
@@ -246,4 +502,4 @@ interface ServerClientContext {
|
|
|
246
502
|
*/
|
|
247
503
|
declare function getServerClient<TSchema extends Record<string, unknown> = Record<string, unknown>>(context: ServerClientContext): ReturnType<typeof generateServerClientUsingCookies<TSchema>> | null;
|
|
248
504
|
|
|
249
|
-
export { type AmplifyServerClient, type AstroAmplifyConfig, type GenerateServerClientOptions, type GraphQLResponse, type Operation, type ProxyOptions, type ServerAuthMode, type ServerClientContext, generateClient, generateServerClient, generateServerClientUsingCookies, getErrorMessage, getServerClient, getSharedClient, hasErrors, mutate, query, resetSharedClient };
|
|
505
|
+
export { type AmplifyServerClient, type AstroAmplifyConfig, type GenerateServerClientOptions, type GraphQLResponse, type Operation, type ProxyOptions, type Reservation, ReservationStatus, type ServerAuthMode, type ServerClientContext, bulkDeleteReservations, bulkRestoreReservations, bulkSoftDeleteReservations, bulkUpdateReservationStatus, createReservation, deleteReservation, generateClient, generateServerClient, generateServerClientUsingCookies, getErrorMessage, getReservation, getServerClient, getSharedClient, hasErrors, listReservations, mutate, query, resetSharedClient, restoreReservation, softDeleteReservation, updateReservation, updateReservationStatus };
|
package/dist/client/index.js
CHANGED
|
@@ -106,6 +106,52 @@ function getErrorMessage(response) {
|
|
|
106
106
|
return response.errors[0].message;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
// src/client/reservations.ts
|
|
110
|
+
async function createReservation(input) {
|
|
111
|
+
return mutate("Reservation", "create", input);
|
|
112
|
+
}
|
|
113
|
+
async function updateReservation(input) {
|
|
114
|
+
return mutate("Reservation", "update", input);
|
|
115
|
+
}
|
|
116
|
+
async function softDeleteReservation(id, deletedBy) {
|
|
117
|
+
return mutate("Reservation", "update", {
|
|
118
|
+
id,
|
|
119
|
+
deletedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
120
|
+
deletedBy
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
async function restoreReservation(id) {
|
|
124
|
+
return mutate("Reservation", "update", {
|
|
125
|
+
id,
|
|
126
|
+
deletedAt: null,
|
|
127
|
+
deletedBy: null
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
async function deleteReservation(id) {
|
|
131
|
+
return mutate("Reservation", "delete", { id });
|
|
132
|
+
}
|
|
133
|
+
async function getReservation(id) {
|
|
134
|
+
return query("Reservation", "get", { id });
|
|
135
|
+
}
|
|
136
|
+
async function listReservations(options) {
|
|
137
|
+
return query("Reservation", "list", options);
|
|
138
|
+
}
|
|
139
|
+
async function updateReservationStatus(id, status) {
|
|
140
|
+
return mutate("Reservation", "update", { id, status });
|
|
141
|
+
}
|
|
142
|
+
async function bulkSoftDeleteReservations(ids, deletedBy) {
|
|
143
|
+
return Promise.all(ids.map((id) => softDeleteReservation(id, deletedBy)));
|
|
144
|
+
}
|
|
145
|
+
async function bulkRestoreReservations(ids) {
|
|
146
|
+
return Promise.all(ids.map((id) => restoreReservation(id)));
|
|
147
|
+
}
|
|
148
|
+
async function bulkDeleteReservations(ids) {
|
|
149
|
+
return Promise.all(ids.map((id) => deleteReservation(id)));
|
|
150
|
+
}
|
|
151
|
+
async function bulkUpdateReservationStatus(ids, status) {
|
|
152
|
+
return Promise.all(ids.map((id) => updateReservationStatus(id, status)));
|
|
153
|
+
}
|
|
154
|
+
|
|
109
155
|
// src/client/index.ts
|
|
110
156
|
var sharedClientInstance = null;
|
|
111
157
|
function getSharedClient() {
|
|
@@ -145,15 +191,27 @@ function getServerClient(context) {
|
|
|
145
191
|
return null;
|
|
146
192
|
}
|
|
147
193
|
export {
|
|
194
|
+
bulkDeleteReservations,
|
|
195
|
+
bulkRestoreReservations,
|
|
196
|
+
bulkSoftDeleteReservations,
|
|
197
|
+
bulkUpdateReservationStatus,
|
|
198
|
+
createReservation,
|
|
199
|
+
deleteReservation,
|
|
148
200
|
generateClient,
|
|
149
201
|
generateServerClient,
|
|
150
202
|
generateServerClientUsingCookies,
|
|
151
203
|
getErrorMessage,
|
|
204
|
+
getReservation,
|
|
152
205
|
getServerClient,
|
|
153
206
|
getSharedClient,
|
|
154
207
|
hasErrors,
|
|
208
|
+
listReservations,
|
|
155
209
|
mutate,
|
|
156
210
|
query,
|
|
157
|
-
resetSharedClient
|
|
211
|
+
resetSharedClient,
|
|
212
|
+
restoreReservation,
|
|
213
|
+
softDeleteReservation,
|
|
214
|
+
updateReservation,
|
|
215
|
+
updateReservationStatus
|
|
158
216
|
};
|
|
159
217
|
//# sourceMappingURL=index.js.map
|
package/dist/client/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/client/index.ts","../../src/client/server.ts","../../src/client/proxy.ts"],"sourcesContent":["/**\n * GraphQL Client for @htlkg/data\n *\n * Provides both client-side and server-side GraphQL capabilities using AWS Amplify Data.\n * The server-side functions use the Amplify Astro adapter for proper SSR support.\n *\n * For server-side usage, use `Astro.locals.amplifyClient` (zero-config, injected by middleware).\n */\n\nimport { generateClient as generateDataClient } from \"aws-amplify/data\";\nimport { Amplify } from \"aws-amplify\";\nimport type { ResourcesConfig } from \"aws-amplify\";\nimport { generateServerClientUsingCookies } from \"./server\";\n\n// Re-export server-side client generation (used internally by middleware)\nexport { generateServerClientUsingCookies } from \"./server\";\n\n// Re-export proxy functions for authenticated client-side operations\nexport {\n\tmutate,\n\tquery,\n\thasErrors,\n\tgetErrorMessage,\n\ttype Operation,\n\ttype GraphQLResponse,\n\ttype ProxyOptions,\n} from \"./proxy\";\n\n/**\n * Type for the server-side Amplify client (for use in type declarations)\n * This represents the client returned by generateServerClientUsingCookies\n */\nexport type AmplifyServerClient<TSchema extends Record<string, unknown> = Record<string, unknown>> =\n\tReturnType<typeof generateServerClientUsingCookies<TSchema>>;\n\n// Singleton client instance for client-side fetching\nlet sharedClientInstance: any = null;\n\n/**\n * Get or create the shared GraphQL client instance (singleton pattern)\n * Use this for client-side fetching to avoid creating multiple client instances.\n *\n * @example\n * ```typescript\n * const client = getSharedClient<Schema>();\n * const { data } = await client.models.Account.list();\n * ```\n */\nexport function getSharedClient<\n\tTSchema extends Record<string, unknown> = Record<string, unknown>,\n>(): ReturnType<typeof generateDataClient<TSchema>> {\n\tif (!sharedClientInstance) {\n\t\tsharedClientInstance = generateDataClient<TSchema>();\n\t}\n\treturn sharedClientInstance;\n}\n\n/**\n * Reset the shared client instance (useful for testing or auth state changes)\n */\nexport function resetSharedClient(): void {\n\tsharedClientInstance = null;\n}\n\n/**\n * Generate a client-side GraphQL client for use in Vue components and browser contexts\n * This is SSR-safe and should be called within a component's setup function or after hydration\n *\n * @example\n * ```typescript\n * import type { Schema } from '@backend/data/resource';\n * import { generateClient } from '@htlkg/data/client';\n *\n * const client = generateClient<Schema>();\n * const { data: brands } = await client.models.Brand.list();\n * ```\n */\nexport function generateClient<\n\tTSchema extends Record<string, unknown> = Record<string, unknown>,\n>(): ReturnType<typeof generateDataClient<TSchema>> {\n\treturn generateDataClient<TSchema>();\n}\n\n/**\n * Configuration for Amplify (matches amplify_outputs.json format)\n */\nexport type AstroAmplifyConfig = ResourcesConfig;\n\n/**\n * Authentication mode for server-side GraphQL client\n */\nexport type ServerAuthMode = 'userPool' | 'apiKey';\n\n/**\n * Options for generating a server-side GraphQL client\n */\nexport interface GenerateServerClientOptions {\n\t/** Authentication mode - 'userPool' (default) uses JWT from cookies, 'apiKey' uses API key */\n\tauthMode?: ServerAuthMode;\n}\n\n/**\n * Generate a server-side GraphQL client for use within runWithAmplifyServerContext\n * \n * This function creates a GraphQL client that can be used for server-side data fetching in Astro.\n * It MUST be called within runWithAmplifyServerContext to access JWT tokens from cookies.\n * \n * The client supports two authentication modes:\n * - 'userPool' (default): Uses JWT tokens from cookies (requires runWithAmplifyServerContext)\n * - 'apiKey': Uses API key for public/unauthenticated requests\n *\n * **Important**: \n * - Amplify.configure() must be called once at app startup (e.g., in amplify-server.ts)\n * - This function must be called INSIDE the operation function of runWithAmplifyServerContext\n * - The context automatically provides the token provider that reads JWT tokens from cookies\n *\n * @example\n * ```typescript\n * // In your Astro page\n * import type { Schema } from '../amplify/data/resource';\n * import { generateServerClient } from '@htlkg/data/client';\n * import { createRunWithAmplifyServerContext } from '@htlkg/core/amplify-astro-adapter';\n * import outputs from '../amplify_outputs.json';\n *\n * const runWithAmplifyServerContext = createRunWithAmplifyServerContext({ config: outputs });\n *\n * // Fetch data with authentication\n * const result = await runWithAmplifyServerContext({\n * astroServerContext: {\n * cookies: Astro.cookies,\n * request: Astro.request\n * },\n * operation: async (contextSpec) => {\n * // Generate client INSIDE the operation\n * const client = generateServerClient<Schema>({ authMode: 'userPool' });\n * return await client.models.User.list();\n * }\n * });\n * \n * const users = result.data || [];\n * ```\n * \n * @example Using API key for public data\n * ```typescript\n * const result = await runWithAmplifyServerContext({\n * astroServerContext: {\n * cookies: Astro.cookies,\n * request: Astro.request\n * },\n * operation: async (contextSpec) => {\n * const client = generateServerClient<Schema>({ authMode: 'apiKey' });\n * return await client.models.Brand.list();\n * }\n * });\n * ```\n */\nexport function generateServerClient<\n\tTSchema extends Record<string, unknown> = Record<string, unknown>,\n>(_options?: GenerateServerClientOptions): ReturnType<typeof generateDataClient<TSchema>> {\n\t// Generate the client without authMode parameter\n\t// When called within runWithAmplifyServerContext, it will automatically use the token provider\n\t// from the context (which reads JWT tokens from cookies)\n\t// The authMode should be specified per-operation, not at client creation\n\tconst client = generateDataClient<TSchema>();\n\n\treturn client;\n}\n\n/**\n * Context required for getting a server client in API routes\n */\nexport interface ServerClientContext {\n\tlocals: { amplifyClient?: any; user?: any };\n\tcookies: any;\n\trequest: Request;\n}\n\n/**\n * Get the server client from Astro context\n *\n * Uses locals.amplifyClient if available (set by middleware),\n * otherwise creates a new client using Amplify's global config.\n * No config parameter needed - uses the config set by the middleware.\n *\n * @example\n * ```typescript\n * import { getServerClient } from '@htlkg/data/client';\n *\n * export const POST: APIRoute = async (context) => {\n * const client = getServerClient(context);\n * if (!client) return new Response('Not authenticated', { status: 401 });\n *\n * const result = await client.models.User.list();\n * };\n * ```\n */\nexport function getServerClient<TSchema extends Record<string, unknown> = Record<string, unknown>>(\n\tcontext: ServerClientContext,\n): ReturnType<typeof generateServerClientUsingCookies<TSchema>> | null {\n\t// Try to use client from middleware first\n\tif (context.locals.amplifyClient) {\n\t\treturn context.locals.amplifyClient as ReturnType<typeof generateServerClientUsingCookies<TSchema>>;\n\t}\n\n\t// If no client from middleware and user is authenticated, create one using global Amplify config\n\tif (context.locals.user) {\n\t\ttry {\n\t\t\t// Get config from Amplify (set by middleware)\n\t\t\tconst amplifyConfig = Amplify.getConfig();\n\t\t\tif (amplifyConfig) {\n\t\t\t\treturn generateServerClientUsingCookies<TSchema>({\n\t\t\t\t\tconfig: amplifyConfig,\n\t\t\t\t\tcookies: context.cookies,\n\t\t\t\t\trequest: context.request,\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tconsole.error('[getServerClient] Failed to get Amplify config:', e);\n\t\t}\n\t}\n\n\t// No authentication available\n\treturn null;\n}\n","/**\n * Server-side data client for Astro\n *\n * Provides a client generator similar to Next.js's generateServerClientUsingCookies\n * using generateClientWithAmplifyInstance for proper server context integration.\n */\n\nimport type { AstroGlobal } from \"astro\";\nimport type { ResourcesConfig } from \"aws-amplify\";\nimport {\n\tCommonPublicClientOptions,\n\tDefaultCommonClientOptions,\n\tV6ClientSSRCookies,\n\tgenerateClientWithAmplifyInstance,\n} from \"aws-amplify/api/internals\";\nimport { getAmplifyServerContext } from \"aws-amplify/adapter-core/internals\";\nimport { createRunWithAmplifyServerContext, createLogger } from \"@htlkg/core/amplify-astro-adapter\";\n\nconst log = createLogger('server-client');\n\ninterface AstroCookiesClientParams {\n\tcookies: AstroGlobal[\"cookies\"];\n\trequest: AstroGlobal[\"request\"];\n\tconfig: ResourcesConfig;\n}\n\n/**\n * Generates a server-side data client for Astro (matches Next.js implementation)\n *\n * This function creates a client that automatically wraps all operations in the Amplify server context,\n * ensuring that authentication tokens from cookies are properly used.\n *\n * @example\n * ```typescript\n * import type { Schema } from '../amplify/data/resource';\n * import { generateServerClientUsingCookies } from '@htlkg/data/client';\n * import { parseAmplifyConfig } from 'aws-amplify/utils';\n * import outputs from '../amplify_outputs.json';\n *\n * const amplifyConfig = parseAmplifyConfig(outputs);\n *\n * const client = generateServerClientUsingCookies<Schema>({\n * config: amplifyConfig,\n * cookies: Astro.cookies,\n * request: Astro.request,\n * });\n *\n * // Use the client directly - operations are automatically wrapped\n * const result = await client.models.User.list({\n * selectionSet: ['id', 'email'],\n * limit: 100,\n * });\n * ```\n */\nexport function generateServerClientUsingCookies<\n\tT extends Record<any, any> = never,\n\tOptions extends CommonPublicClientOptions &\n\t\tAstroCookiesClientParams = DefaultCommonClientOptions &\n\t\tAstroCookiesClientParams,\n>(options: Options): V6ClientSSRCookies<T, Options> {\n\tconst runWithAmplifyServerContext = createRunWithAmplifyServerContext({\n\t\tconfig: options.config,\n\t});\n\n\tconst resourcesConfig = options.config;\n\n\t// This function reference gets passed down to InternalGraphQLAPI.ts.graphql\n\t// where this._graphql is passed in as the `fn` argument\n\t// causing it to always get invoked inside `runWithAmplifyServerContext`\n\tconst getAmplify = (fn: (amplify: any) => Promise<any>) => {\n\t\treturn runWithAmplifyServerContext({\n\t\t\tastroServerContext: {\n\t\t\t\tcookies: options.cookies,\n\t\t\t\trequest: options.request,\n\t\t\t},\n\t\t\toperation: async (contextSpec: any) => {\n\t\t\t\tconst amplifyInstance = getAmplifyServerContext(contextSpec).amplify;\n\t\t\t\t\n\t\t\t\t// Debug logging (only when DEBUG=true)\n\t\t\t\ttry {\n\t\t\t\t\tconst config = amplifyInstance.getConfig();\n\t\t\t\t\tlog.debug('Amplify config from instance:', {\n\t\t\t\t\t\thasAPI: !!config.API,\n\t\t\t\t\t\thasGraphQL: !!config.API?.GraphQL,\n\t\t\t\t\t\tendpoint: config.API?.GraphQL?.endpoint,\n\t\t\t\t\t\tdefaultAuthMode: config.API?.GraphQL?.defaultAuthMode,\n\t\t\t\t\t\tregion: config.API?.GraphQL?.region,\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\tconst session = await amplifyInstance.Auth.fetchAuthSession();\n\t\t\t\t\tlog.debug('Auth session:', {\n\t\t\t\t\t\thasTokens: !!session.tokens,\n\t\t\t\t\t\thasAccessToken: !!session.tokens?.accessToken,\n\t\t\t\t\t\thasIdToken: !!session.tokens?.idToken,\n\t\t\t\t\t\thasCredentials: !!session.credentials,\n\t\t\t\t\t});\n\t\t\t\t} catch (e: any) {\n\t\t\t\t\tlog.debug('Error fetching session:', e.message);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn fn(amplifyInstance);\n\t\t\t},\n\t\t});\n\t};\n\n\tconst {\n\t\tcookies: _cookies,\n\t\trequest: _request,\n\t\tconfig: _config,\n\t\t...params\n\t} = options;\n\n\treturn generateClientWithAmplifyInstance<T, V6ClientSSRCookies<T, Options>>({\n\t\tamplify: getAmplify,\n\t\tconfig: resourcesConfig,\n\t\t...params,\n\t} as any);\n}\n","/**\n * GraphQL Proxy Client\n *\n * Client-side helper for making authenticated GraphQL operations through\n * the server-side proxy. This allows Vue components to perform mutations\n * while keeping auth cookies httpOnly for security.\n *\n * @module @htlkg/data/proxy\n */\n\n/**\n * Valid GraphQL operations\n */\nexport type Operation = \"create\" | \"update\" | \"delete\" | \"get\" | \"list\";\n\n/**\n * Response type from GraphQL operations\n */\nexport interface GraphQLResponse<T = any> {\n\tdata: T | null;\n\terrors?: Array<{ message: string; [key: string]: any }>;\n}\n\n/**\n * Options for proxy requests\n */\nexport interface ProxyOptions {\n\t/** Custom API endpoint (default: /api/graphql) */\n\tendpoint?: string;\n\t/** Additional fetch options */\n\tfetchOptions?: RequestInit;\n}\n\n/**\n * Default proxy endpoint\n */\nconst DEFAULT_ENDPOINT = \"/api/graphql\";\n\n/**\n * Execute a GraphQL mutation through the server proxy\n *\n * @param model - The model name (e.g., 'User', 'Brand', 'Account')\n * @param operation - The operation type ('create', 'update', 'delete')\n * @param data - The operation data/input\n * @param options - Optional configuration\n * @returns Promise with the operation result\n *\n * @example Create\n * ```typescript\n * const result = await mutate('User', 'create', {\n * email: 'user@example.com',\n * accountId: '123',\n * });\n * ```\n *\n * @example Update\n * ```typescript\n * const result = await mutate('User', 'update', {\n * id: 'user-id',\n * status: 'deleted',\n * deletedAt: new Date().toISOString(),\n * });\n * ```\n *\n * @example Delete\n * ```typescript\n * const result = await mutate('User', 'delete', { id: 'user-id' });\n * ```\n */\nexport async function mutate<T = any>(\n\tmodel: string,\n\toperation: \"create\" | \"update\" | \"delete\",\n\tdata: Record<string, any>,\n\toptions?: ProxyOptions,\n): Promise<GraphQLResponse<T>> {\n\treturn proxyRequest<T>(model, operation, data, options);\n}\n\n/**\n * Execute a GraphQL query through the server proxy\n *\n * @param model - The model name (e.g., 'User', 'Brand', 'Account')\n * @param operation - The operation type ('get', 'list')\n * @param data - The query parameters (id for get, filter/limit for list)\n * @param options - Optional configuration\n * @returns Promise with the query result\n *\n * @example Get by ID\n * ```typescript\n * const result = await query('User', 'get', { id: 'user-id' });\n * ```\n *\n * @example List with filter\n * ```typescript\n * const result = await query('User', 'list', {\n * filter: { status: { eq: 'active' } },\n * limit: 100,\n * });\n * ```\n */\nexport async function query<T = any>(\n\tmodel: string,\n\toperation: \"get\" | \"list\",\n\tdata?: Record<string, any>,\n\toptions?: ProxyOptions,\n): Promise<GraphQLResponse<T>> {\n\treturn proxyRequest<T>(model, operation, data, options);\n}\n\n/**\n * Internal function to make proxy requests\n */\nasync function proxyRequest<T>(\n\tmodel: string,\n\toperation: Operation,\n\tdata?: Record<string, any>,\n\toptions?: ProxyOptions,\n): Promise<GraphQLResponse<T>> {\n\tconst endpoint = options?.endpoint ?? DEFAULT_ENDPOINT;\n\n\ttry {\n\t\tconst response = await fetch(endpoint, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tcredentials: \"include\", // Important: include cookies\n\t\t\t...options?.fetchOptions,\n\t\t\tbody: JSON.stringify({ model, operation, data }),\n\t\t});\n\n\t\tconst result: GraphQLResponse<T> = await response.json();\n\n\t\t// Handle auth errors\n\t\tif (response.status === 401) {\n\t\t\tconsole.error(\"[GraphQL Proxy] Unauthorized - session may have expired\");\n\t\t\t// Optionally trigger a redirect to login\n\t\t\t// window.location.href = '/login';\n\t\t}\n\n\t\treturn result;\n\t} catch (error) {\n\t\tconsole.error(\"[GraphQL Proxy] Request failed:\", error);\n\t\treturn {\n\t\t\tdata: null,\n\t\t\terrors: [\n\t\t\t\t{\n\t\t\t\t\tmessage: error instanceof Error ? error.message : \"Network error\",\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t}\n}\n\n/**\n * Helper to check if a response has errors\n */\nexport function hasErrors(response: GraphQLResponse): boolean {\n\treturn !!response.errors && response.errors.length > 0;\n}\n\n/**\n * Helper to get the first error message from a response\n */\nexport function getErrorMessage(response: GraphQLResponse): string | null {\n\tif (!response.errors || response.errors.length === 0) {\n\t\treturn null;\n\t}\n\treturn response.errors[0].message;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/client/index.ts","../../src/client/server.ts","../../src/client/proxy.ts","../../src/client/reservations.ts"],"sourcesContent":["/**\n * GraphQL Client for @htlkg/data\n *\n * Provides both client-side and server-side GraphQL capabilities using AWS Amplify Data.\n * The server-side functions use the Amplify Astro adapter for proper SSR support.\n *\n * For server-side usage, use `Astro.locals.amplifyClient` (zero-config, injected by middleware).\n */\n\nimport { generateClient as generateDataClient } from \"aws-amplify/data\";\nimport { Amplify } from \"aws-amplify\";\nimport type { ResourcesConfig } from \"aws-amplify\";\nimport { generateServerClientUsingCookies } from \"./server\";\n\n// Re-export server-side client generation (used internally by middleware)\nexport { generateServerClientUsingCookies } from \"./server\";\n\n// Re-export proxy functions for authenticated client-side operations\nexport {\n\tmutate,\n\tquery,\n\thasErrors,\n\tgetErrorMessage,\n\ttype Operation,\n\ttype GraphQLResponse,\n\ttype ProxyOptions,\n} from \"./proxy\";\n\n// Re-export type-safe client-side Reservation operations\nexport {\n\tcreateReservation,\n\tupdateReservation,\n\tsoftDeleteReservation,\n\trestoreReservation,\n\tdeleteReservation,\n\tgetReservation,\n\tlistReservations,\n\tupdateReservationStatus,\n\tbulkSoftDeleteReservations,\n\tbulkRestoreReservations,\n\tbulkDeleteReservations,\n\tbulkUpdateReservationStatus,\n\ttype Reservation,\n\ttype ReservationStatus,\n} from \"./reservations\";\n\n/**\n * Type for the server-side Amplify client (for use in type declarations)\n * This represents the client returned by generateServerClientUsingCookies\n */\nexport type AmplifyServerClient<TSchema extends Record<string, unknown> = Record<string, unknown>> =\n\tReturnType<typeof generateServerClientUsingCookies<TSchema>>;\n\n// Singleton client instance for client-side fetching\nlet sharedClientInstance: any = null;\n\n/**\n * Get or create the shared GraphQL client instance (singleton pattern)\n * Use this for client-side fetching to avoid creating multiple client instances.\n *\n * @example\n * ```typescript\n * const client = getSharedClient<Schema>();\n * const { data } = await client.models.Account.list();\n * ```\n */\nexport function getSharedClient<\n\tTSchema extends Record<string, unknown> = Record<string, unknown>,\n>(): ReturnType<typeof generateDataClient<TSchema>> {\n\tif (!sharedClientInstance) {\n\t\tsharedClientInstance = generateDataClient<TSchema>();\n\t}\n\treturn sharedClientInstance;\n}\n\n/**\n * Reset the shared client instance (useful for testing or auth state changes)\n */\nexport function resetSharedClient(): void {\n\tsharedClientInstance = null;\n}\n\n/**\n * Generate a client-side GraphQL client for use in Vue components and browser contexts\n * This is SSR-safe and should be called within a component's setup function or after hydration\n *\n * @example\n * ```typescript\n * import type { Schema } from '@backend/data/resource';\n * import { generateClient } from '@htlkg/data/client';\n *\n * const client = generateClient<Schema>();\n * const { data: brands } = await client.models.Brand.list();\n * ```\n */\nexport function generateClient<\n\tTSchema extends Record<string, unknown> = Record<string, unknown>,\n>(): ReturnType<typeof generateDataClient<TSchema>> {\n\treturn generateDataClient<TSchema>();\n}\n\n/**\n * Configuration for Amplify (matches amplify_outputs.json format)\n */\nexport type AstroAmplifyConfig = ResourcesConfig;\n\n/**\n * Authentication mode for server-side GraphQL client\n */\nexport type ServerAuthMode = 'userPool' | 'apiKey';\n\n/**\n * Options for generating a server-side GraphQL client\n */\nexport interface GenerateServerClientOptions {\n\t/** Authentication mode - 'userPool' (default) uses JWT from cookies, 'apiKey' uses API key */\n\tauthMode?: ServerAuthMode;\n}\n\n/**\n * Generate a server-side GraphQL client for use within runWithAmplifyServerContext\n * \n * This function creates a GraphQL client that can be used for server-side data fetching in Astro.\n * It MUST be called within runWithAmplifyServerContext to access JWT tokens from cookies.\n * \n * The client supports two authentication modes:\n * - 'userPool' (default): Uses JWT tokens from cookies (requires runWithAmplifyServerContext)\n * - 'apiKey': Uses API key for public/unauthenticated requests\n *\n * **Important**: \n * - Amplify.configure() must be called once at app startup (e.g., in amplify-server.ts)\n * - This function must be called INSIDE the operation function of runWithAmplifyServerContext\n * - The context automatically provides the token provider that reads JWT tokens from cookies\n *\n * @example\n * ```typescript\n * // In your Astro page\n * import type { Schema } from '../amplify/data/resource';\n * import { generateServerClient } from '@htlkg/data/client';\n * import { createRunWithAmplifyServerContext } from '@htlkg/core/amplify-astro-adapter';\n * import outputs from '../amplify_outputs.json';\n *\n * const runWithAmplifyServerContext = createRunWithAmplifyServerContext({ config: outputs });\n *\n * // Fetch data with authentication\n * const result = await runWithAmplifyServerContext({\n * astroServerContext: {\n * cookies: Astro.cookies,\n * request: Astro.request\n * },\n * operation: async (contextSpec) => {\n * // Generate client INSIDE the operation\n * const client = generateServerClient<Schema>({ authMode: 'userPool' });\n * return await client.models.User.list();\n * }\n * });\n * \n * const users = result.data || [];\n * ```\n * \n * @example Using API key for public data\n * ```typescript\n * const result = await runWithAmplifyServerContext({\n * astroServerContext: {\n * cookies: Astro.cookies,\n * request: Astro.request\n * },\n * operation: async (contextSpec) => {\n * const client = generateServerClient<Schema>({ authMode: 'apiKey' });\n * return await client.models.Brand.list();\n * }\n * });\n * ```\n */\nexport function generateServerClient<\n\tTSchema extends Record<string, unknown> = Record<string, unknown>,\n>(_options?: GenerateServerClientOptions): ReturnType<typeof generateDataClient<TSchema>> {\n\t// Generate the client without authMode parameter\n\t// When called within runWithAmplifyServerContext, it will automatically use the token provider\n\t// from the context (which reads JWT tokens from cookies)\n\t// The authMode should be specified per-operation, not at client creation\n\tconst client = generateDataClient<TSchema>();\n\n\treturn client;\n}\n\n/**\n * Context required for getting a server client in API routes\n */\nexport interface ServerClientContext {\n\tlocals: { amplifyClient?: any; user?: any };\n\tcookies: any;\n\trequest: Request;\n}\n\n/**\n * Get the server client from Astro context\n *\n * Uses locals.amplifyClient if available (set by middleware),\n * otherwise creates a new client using Amplify's global config.\n * No config parameter needed - uses the config set by the middleware.\n *\n * @example\n * ```typescript\n * import { getServerClient } from '@htlkg/data/client';\n *\n * export const POST: APIRoute = async (context) => {\n * const client = getServerClient(context);\n * if (!client) return new Response('Not authenticated', { status: 401 });\n *\n * const result = await client.models.User.list();\n * };\n * ```\n */\nexport function getServerClient<TSchema extends Record<string, unknown> = Record<string, unknown>>(\n\tcontext: ServerClientContext,\n): ReturnType<typeof generateServerClientUsingCookies<TSchema>> | null {\n\t// Try to use client from middleware first\n\tif (context.locals.amplifyClient) {\n\t\treturn context.locals.amplifyClient as ReturnType<typeof generateServerClientUsingCookies<TSchema>>;\n\t}\n\n\t// If no client from middleware and user is authenticated, create one using global Amplify config\n\tif (context.locals.user) {\n\t\ttry {\n\t\t\t// Get config from Amplify (set by middleware)\n\t\t\tconst amplifyConfig = Amplify.getConfig();\n\t\t\tif (amplifyConfig) {\n\t\t\t\treturn generateServerClientUsingCookies<TSchema>({\n\t\t\t\t\tconfig: amplifyConfig,\n\t\t\t\t\tcookies: context.cookies,\n\t\t\t\t\trequest: context.request,\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tconsole.error('[getServerClient] Failed to get Amplify config:', e);\n\t\t}\n\t}\n\n\t// No authentication available\n\treturn null;\n}\n","/**\n * Server-side data client for Astro\n *\n * Provides a client generator similar to Next.js's generateServerClientUsingCookies\n * using generateClientWithAmplifyInstance for proper server context integration.\n */\n\nimport type { AstroGlobal } from \"astro\";\nimport type { ResourcesConfig } from \"aws-amplify\";\nimport {\n\tCommonPublicClientOptions,\n\tDefaultCommonClientOptions,\n\tV6ClientSSRCookies,\n\tgenerateClientWithAmplifyInstance,\n} from \"aws-amplify/api/internals\";\nimport { getAmplifyServerContext } from \"aws-amplify/adapter-core/internals\";\nimport { createRunWithAmplifyServerContext, createLogger } from \"@htlkg/core/amplify-astro-adapter\";\n\nconst log = createLogger('server-client');\n\ninterface AstroCookiesClientParams {\n\tcookies: AstroGlobal[\"cookies\"];\n\trequest: AstroGlobal[\"request\"];\n\tconfig: ResourcesConfig;\n}\n\n/**\n * Generates a server-side data client for Astro (matches Next.js implementation)\n *\n * This function creates a client that automatically wraps all operations in the Amplify server context,\n * ensuring that authentication tokens from cookies are properly used.\n *\n * @example\n * ```typescript\n * import type { Schema } from '../amplify/data/resource';\n * import { generateServerClientUsingCookies } from '@htlkg/data/client';\n * import { parseAmplifyConfig } from 'aws-amplify/utils';\n * import outputs from '../amplify_outputs.json';\n *\n * const amplifyConfig = parseAmplifyConfig(outputs);\n *\n * const client = generateServerClientUsingCookies<Schema>({\n * config: amplifyConfig,\n * cookies: Astro.cookies,\n * request: Astro.request,\n * });\n *\n * // Use the client directly - operations are automatically wrapped\n * const result = await client.models.User.list({\n * selectionSet: ['id', 'email'],\n * limit: 100,\n * });\n * ```\n */\nexport function generateServerClientUsingCookies<\n\tT extends Record<any, any> = never,\n\tOptions extends CommonPublicClientOptions &\n\t\tAstroCookiesClientParams = DefaultCommonClientOptions &\n\t\tAstroCookiesClientParams,\n>(options: Options): V6ClientSSRCookies<T, Options> {\n\tconst runWithAmplifyServerContext = createRunWithAmplifyServerContext({\n\t\tconfig: options.config,\n\t});\n\n\tconst resourcesConfig = options.config;\n\n\t// This function reference gets passed down to InternalGraphQLAPI.ts.graphql\n\t// where this._graphql is passed in as the `fn` argument\n\t// causing it to always get invoked inside `runWithAmplifyServerContext`\n\tconst getAmplify = (fn: (amplify: any) => Promise<any>) => {\n\t\treturn runWithAmplifyServerContext({\n\t\t\tastroServerContext: {\n\t\t\t\tcookies: options.cookies,\n\t\t\t\trequest: options.request,\n\t\t\t},\n\t\t\toperation: async (contextSpec: any) => {\n\t\t\t\tconst amplifyInstance = getAmplifyServerContext(contextSpec).amplify;\n\t\t\t\t\n\t\t\t\t// Debug logging (only when DEBUG=true)\n\t\t\t\ttry {\n\t\t\t\t\tconst config = amplifyInstance.getConfig();\n\t\t\t\t\tlog.debug('Amplify config from instance:', {\n\t\t\t\t\t\thasAPI: !!config.API,\n\t\t\t\t\t\thasGraphQL: !!config.API?.GraphQL,\n\t\t\t\t\t\tendpoint: config.API?.GraphQL?.endpoint,\n\t\t\t\t\t\tdefaultAuthMode: config.API?.GraphQL?.defaultAuthMode,\n\t\t\t\t\t\tregion: config.API?.GraphQL?.region,\n\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\tconst session = await amplifyInstance.Auth.fetchAuthSession();\n\t\t\t\t\tlog.debug('Auth session:', {\n\t\t\t\t\t\thasTokens: !!session.tokens,\n\t\t\t\t\t\thasAccessToken: !!session.tokens?.accessToken,\n\t\t\t\t\t\thasIdToken: !!session.tokens?.idToken,\n\t\t\t\t\t\thasCredentials: !!session.credentials,\n\t\t\t\t\t});\n\t\t\t\t} catch (e: any) {\n\t\t\t\t\tlog.debug('Error fetching session:', e.message);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn fn(amplifyInstance);\n\t\t\t},\n\t\t});\n\t};\n\n\tconst {\n\t\tcookies: _cookies,\n\t\trequest: _request,\n\t\tconfig: _config,\n\t\t...params\n\t} = options;\n\n\treturn generateClientWithAmplifyInstance<T, V6ClientSSRCookies<T, Options>>({\n\t\tamplify: getAmplify,\n\t\tconfig: resourcesConfig,\n\t\t...params,\n\t} as any);\n}\n","/**\n * GraphQL Proxy Client\n *\n * Client-side helper for making authenticated GraphQL operations through\n * the server-side proxy. This allows Vue components to perform mutations\n * while keeping auth cookies httpOnly for security.\n *\n * @module @htlkg/data/proxy\n */\n\n/**\n * Valid GraphQL operations\n */\nexport type Operation = \"create\" | \"update\" | \"delete\" | \"get\" | \"list\";\n\n/**\n * Response type from GraphQL operations\n */\nexport interface GraphQLResponse<T = any> {\n\tdata: T | null;\n\terrors?: Array<{ message: string; [key: string]: any }>;\n}\n\n/**\n * Options for proxy requests\n */\nexport interface ProxyOptions {\n\t/** Custom API endpoint (default: /api/graphql) */\n\tendpoint?: string;\n\t/** Additional fetch options */\n\tfetchOptions?: RequestInit;\n}\n\n/**\n * Default proxy endpoint\n */\nconst DEFAULT_ENDPOINT = \"/api/graphql\";\n\n/**\n * Execute a GraphQL mutation through the server proxy\n *\n * @param model - The model name (e.g., 'User', 'Brand', 'Account')\n * @param operation - The operation type ('create', 'update', 'delete')\n * @param data - The operation data/input\n * @param options - Optional configuration\n * @returns Promise with the operation result\n *\n * @example Create\n * ```typescript\n * const result = await mutate('User', 'create', {\n * email: 'user@example.com',\n * accountId: '123',\n * });\n * ```\n *\n * @example Update\n * ```typescript\n * const result = await mutate('User', 'update', {\n * id: 'user-id',\n * status: 'deleted',\n * deletedAt: new Date().toISOString(),\n * });\n * ```\n *\n * @example Delete\n * ```typescript\n * const result = await mutate('User', 'delete', { id: 'user-id' });\n * ```\n */\nexport async function mutate<T = any>(\n\tmodel: string,\n\toperation: \"create\" | \"update\" | \"delete\",\n\tdata: Record<string, any>,\n\toptions?: ProxyOptions,\n): Promise<GraphQLResponse<T>> {\n\treturn proxyRequest<T>(model, operation, data, options);\n}\n\n/**\n * Execute a GraphQL query through the server proxy\n *\n * @param model - The model name (e.g., 'User', 'Brand', 'Account')\n * @param operation - The operation type ('get', 'list')\n * @param data - The query parameters (id for get, filter/limit for list)\n * @param options - Optional configuration\n * @returns Promise with the query result\n *\n * @example Get by ID\n * ```typescript\n * const result = await query('User', 'get', { id: 'user-id' });\n * ```\n *\n * @example List with filter\n * ```typescript\n * const result = await query('User', 'list', {\n * filter: { status: { eq: 'active' } },\n * limit: 100,\n * });\n * ```\n */\nexport async function query<T = any>(\n\tmodel: string,\n\toperation: \"get\" | \"list\",\n\tdata?: Record<string, any>,\n\toptions?: ProxyOptions,\n): Promise<GraphQLResponse<T>> {\n\treturn proxyRequest<T>(model, operation, data, options);\n}\n\n/**\n * Internal function to make proxy requests\n */\nasync function proxyRequest<T>(\n\tmodel: string,\n\toperation: Operation,\n\tdata?: Record<string, any>,\n\toptions?: ProxyOptions,\n): Promise<GraphQLResponse<T>> {\n\tconst endpoint = options?.endpoint ?? DEFAULT_ENDPOINT;\n\n\ttry {\n\t\tconst response = await fetch(endpoint, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tcredentials: \"include\", // Important: include cookies\n\t\t\t...options?.fetchOptions,\n\t\t\tbody: JSON.stringify({ model, operation, data }),\n\t\t});\n\n\t\tconst result: GraphQLResponse<T> = await response.json();\n\n\t\t// Handle auth errors\n\t\tif (response.status === 401) {\n\t\t\tconsole.error(\"[GraphQL Proxy] Unauthorized - session may have expired\");\n\t\t\t// Optionally trigger a redirect to login\n\t\t\t// window.location.href = '/login';\n\t\t}\n\n\t\treturn result;\n\t} catch (error) {\n\t\tconsole.error(\"[GraphQL Proxy] Request failed:\", error);\n\t\treturn {\n\t\t\tdata: null,\n\t\t\terrors: [\n\t\t\t\t{\n\t\t\t\t\tmessage: error instanceof Error ? error.message : \"Network error\",\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t}\n}\n\n/**\n * Helper to check if a response has errors\n */\nexport function hasErrors(response: GraphQLResponse): boolean {\n\treturn !!response.errors && response.errors.length > 0;\n}\n\n/**\n * Helper to get the first error message from a response\n */\nexport function getErrorMessage(response: GraphQLResponse): string | null {\n\tif (!response.errors || response.errors.length === 0) {\n\t\treturn null;\n\t}\n\treturn response.errors[0].message;\n}\n","/**\n * Type-safe Client-Side Reservation Operations\n *\n * Provides type-safe wrappers around the GraphQL proxy for reservation operations.\n * These functions can be used directly in Vue components while maintaining type safety.\n * Includes client-side validation for dates and status transitions.\n */\n\nimport { mutate, query, type GraphQLResponse } from \"./proxy\";\nimport type {\n\tCreateReservationInput,\n\tUpdateReservationInput,\n\tReservationStatus,\n} from \"../mutations/reservations\";\n\n/**\n * Reservation type (simplified for client-side use)\n */\nexport interface Reservation {\n\tid: string;\n\tbrandId: string;\n\tvisitId: string;\n\tconfirmationCode: string;\n\tcheckIn: string;\n\tcheckOut: string;\n\tstatus: ReservationStatus;\n\tsource?: string;\n\tchannel?: string;\n\troomType?: string;\n\troom?: string;\n\ttotalAmount?: number;\n\tcurrency?: string;\n\tnights?: number;\n\tdeletedAt?: string;\n\tdeletedBy?: string;\n\tcreatedAt?: string;\n\tcreatedBy?: string;\n\tupdatedAt?: string;\n\tupdatedBy?: string;\n}\n\n/**\n * Re-export ReservationStatus type for convenience\n */\nexport type { ReservationStatus } from \"../mutations/reservations\";\n\n/**\n * Create a new reservation (client-side)\n *\n * @example\n * ```typescript\n * import { createReservation } from '@htlkg/data/client';\n *\n * const result = await createReservation({\n * brandId: 'brand-123',\n * visitId: 'visit-456',\n * confirmationCode: 'ABC123',\n * checkIn: '2024-01-01',\n * checkOut: '2024-01-05',\n * status: 'confirmed'\n * });\n *\n * if (!result.errors) {\n * console.log('Created:', result.data);\n * }\n * ```\n */\nexport async function createReservation(\n\tinput: CreateReservationInput,\n): Promise<GraphQLResponse<Reservation>> {\n\treturn mutate<Reservation>(\"Reservation\", \"create\", input);\n}\n\n/**\n * Update an existing reservation (client-side)\n *\n * @example\n * ```typescript\n * import { updateReservation } from '@htlkg/data/client';\n *\n * const result = await updateReservation({\n * id: 'reservation-123',\n * status: 'checked_in',\n * room: '201'\n * });\n *\n * if (!result.errors) {\n * console.log('Updated:', result.data);\n * }\n * ```\n */\nexport async function updateReservation(\n\tinput: UpdateReservationInput,\n): Promise<GraphQLResponse<Reservation>> {\n\treturn mutate<Reservation>(\"Reservation\", \"update\", input);\n}\n\n/**\n * Soft delete a reservation (sets deletedAt/deletedBy)\n *\n * @example\n * ```typescript\n * import { softDeleteReservation } from '@htlkg/data/client';\n *\n * const result = await softDeleteReservation('reservation-123', 'admin@example.com');\n *\n * if (!result.errors) {\n * console.log('Soft deleted');\n * }\n * ```\n */\nexport async function softDeleteReservation(\n\tid: string,\n\tdeletedBy: string,\n): Promise<GraphQLResponse<Reservation>> {\n\treturn mutate<Reservation>(\"Reservation\", \"update\", {\n\t\tid,\n\t\tdeletedAt: new Date().toISOString(),\n\t\tdeletedBy,\n\t});\n}\n\n/**\n * Restore a soft-deleted reservation\n *\n * @example\n * ```typescript\n * import { restoreReservation } from '@htlkg/data/client';\n *\n * const result = await restoreReservation('reservation-123');\n *\n * if (!result.errors) {\n * console.log('Restored');\n * }\n * ```\n */\nexport async function restoreReservation(\n\tid: string,\n): Promise<GraphQLResponse<Reservation>> {\n\treturn mutate<Reservation>(\"Reservation\", \"update\", {\n\t\tid,\n\t\tdeletedAt: null,\n\t\tdeletedBy: null,\n\t});\n}\n\n/**\n * Permanently delete a reservation (removes from database)\n *\n * @example\n * ```typescript\n * import { deleteReservation } from '@htlkg/data/client';\n *\n * const result = await deleteReservation('reservation-123');\n *\n * if (!result.errors) {\n * console.log('Permanently deleted');\n * }\n * ```\n */\nexport async function deleteReservation(\n\tid: string,\n): Promise<GraphQLResponse<Reservation>> {\n\treturn mutate<Reservation>(\"Reservation\", \"delete\", { id });\n}\n\n/**\n * Get a single reservation by ID\n *\n * @example\n * ```typescript\n * import { getReservation } from '@htlkg/data/client';\n *\n * const result = await getReservation('reservation-123');\n *\n * if (!result.errors && result.data) {\n * console.log('Reservation:', result.data);\n * }\n * ```\n */\nexport async function getReservation(\n\tid: string,\n): Promise<GraphQLResponse<Reservation>> {\n\treturn query<Reservation>(\"Reservation\", \"get\", { id });\n}\n\n/**\n * List reservations with optional filters\n *\n * @example\n * ```typescript\n * import { listReservations } from '@htlkg/data/client';\n *\n * const result = await listReservations({\n * filter: { brandId: { eq: 'brand-123' } },\n * limit: 100\n * });\n *\n * if (!result.errors && result.data) {\n * console.log('Reservations:', result.data);\n * }\n * ```\n */\nexport async function listReservations(\n\toptions?: {\n\t\tfilter?: Record<string, any>;\n\t\tlimit?: number;\n\t\tnextToken?: string;\n\t\tselectionSet?: string[];\n\t},\n): Promise<GraphQLResponse<Reservation[]>> {\n\treturn query<Reservation[]>(\"Reservation\", \"list\", options);\n}\n\n/**\n * Update reservation status (with server-side validation)\n *\n * The server will validate status transitions:\n * - confirmed → checked_in, cancelled, no_show\n * - checked_in → checked_out, cancelled\n * - checked_out, cancelled, no_show → (terminal states, no transitions)\n *\n * @example\n * ```typescript\n * import { updateReservationStatus } from '@htlkg/data/client';\n *\n * const result = await updateReservationStatus('reservation-123', 'checked_in');\n *\n * if (!result.errors) {\n * console.log('Status updated');\n * } else {\n * console.error('Status transition not allowed:', result.errors[0].message);\n * }\n * ```\n */\nexport async function updateReservationStatus(\n\tid: string,\n\tstatus: ReservationStatus,\n): Promise<GraphQLResponse<Reservation>> {\n\treturn mutate<Reservation>(\"Reservation\", \"update\", { id, status });\n}\n\n/**\n * Bulk soft delete reservations\n *\n * @example\n * ```typescript\n * import { bulkSoftDeleteReservations } from '@htlkg/data/client';\n *\n * const results = await bulkSoftDeleteReservations(\n * ['res-1', 'res-2', 'res-3'],\n * 'admin@example.com'\n * );\n *\n * results.forEach(result => {\n * if (!result.errors) console.log('Deleted:', result.data?.id);\n * });\n * ```\n */\nexport async function bulkSoftDeleteReservations(\n\tids: string[],\n\tdeletedBy: string,\n): Promise<GraphQLResponse<Reservation>[]> {\n\treturn Promise.all(ids.map((id) => softDeleteReservation(id, deletedBy)));\n}\n\n/**\n * Bulk restore reservations\n *\n * @example\n * ```typescript\n * import { bulkRestoreReservations } from '@htlkg/data/client';\n *\n * const results = await bulkRestoreReservations(['res-1', 'res-2', 'res-3']);\n *\n * results.forEach(result => {\n * if (!result.errors) console.log('Restored:', result.data?.id);\n * });\n * ```\n */\nexport async function bulkRestoreReservations(\n\tids: string[],\n): Promise<GraphQLResponse<Reservation>[]> {\n\treturn Promise.all(ids.map((id) => restoreReservation(id)));\n}\n\n/**\n * Bulk permanently delete reservations\n *\n * @example\n * ```typescript\n * import { bulkDeleteReservations } from '@htlkg/data/client';\n *\n * const results = await bulkDeleteReservations(['res-1', 'res-2', 'res-3']);\n *\n * results.forEach(result => {\n * if (!result.errors) console.log('Permanently deleted:', result.data?.id);\n * });\n * ```\n */\nexport async function bulkDeleteReservations(\n\tids: string[],\n): Promise<GraphQLResponse<Reservation>[]> {\n\treturn Promise.all(ids.map((id) => deleteReservation(id)));\n}\n\n/**\n * Bulk update reservation status (with server-side validation per reservation)\n *\n * Note: Each reservation's status transition is validated independently.\n * Some may succeed while others fail if their current status doesn't allow the transition.\n *\n * @example\n * ```typescript\n * import { bulkUpdateReservationStatus } from '@htlkg/data/client';\n *\n * const results = await bulkUpdateReservationStatus(\n * ['res-1', 'res-2', 'res-3'],\n * 'checked_in'\n * );\n *\n * results.forEach(result => {\n * if (!result.errors) {\n * console.log('Updated:', result.data?.id);\n * } else {\n * console.error('Failed:', result.errors[0].message);\n * }\n * });\n * ```\n */\nexport async function bulkUpdateReservationStatus(\n\tids: string[],\n\tstatus: ReservationStatus,\n): Promise<GraphQLResponse<Reservation>[]> {\n\treturn Promise.all(ids.map((id) => updateReservationStatus(id, status)));\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common Mutation Input Base Types
|
|
3
|
+
*
|
|
4
|
+
* Provides reusable base interfaces for audit fields to avoid duplication
|
|
5
|
+
* across all mutation input types.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Audit fields for creation operations
|
|
9
|
+
* Includes timestamps and user tracking
|
|
10
|
+
*/
|
|
11
|
+
interface CreateAuditFields {
|
|
12
|
+
createdAt?: string;
|
|
13
|
+
createdBy?: string;
|
|
14
|
+
updatedAt?: string;
|
|
15
|
+
updatedBy?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Audit fields for update operations
|
|
19
|
+
* Includes timestamps and user tracking
|
|
20
|
+
*/
|
|
21
|
+
interface UpdateAuditFields {
|
|
22
|
+
updatedAt?: string;
|
|
23
|
+
updatedBy?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Soft delete fields for entities that support soft deletion
|
|
27
|
+
* Tracks when and by whom an entity was deleted
|
|
28
|
+
*/
|
|
29
|
+
interface SoftDeleteFields {
|
|
30
|
+
deletedAt?: string | null;
|
|
31
|
+
deletedBy?: string | null;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Complete audit trail for entities with soft delete support
|
|
35
|
+
* Combines update and soft delete fields
|
|
36
|
+
*/
|
|
37
|
+
interface UpdateWithSoftDeleteFields extends UpdateAuditFields, SoftDeleteFields {
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export type { CreateAuditFields as C, SoftDeleteFields as S, UpdateAuditFields as U, UpdateWithSoftDeleteFields as a };
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
import { Ref, ComputedRef } from 'vue';
|
|
2
2
|
import { Brand, Account, User, Product, ProductInstance } from '@htlkg/core/types';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import '
|
|
6
|
-
import 'aws-amplify';
|
|
7
|
-
import '../server/index.js';
|
|
8
|
-
import 'astro';
|
|
9
|
-
import 'aws-amplify/api/internals';
|
|
3
|
+
import { C as CreateProductInstanceInput, U as UpdateProductInstanceInput } from '../productInstances-BpQv1oLS.js';
|
|
4
|
+
import { R as Reservation } from '../reservations-C0FNm__0.js';
|
|
5
|
+
import '../common-DSxswsZ3.js';
|
|
10
6
|
|
|
11
7
|
/**
|
|
12
8
|
* Data Hook Factory
|
|
@@ -62,7 +58,7 @@ interface DataHookReturn<T, TComputed extends Record<string, any> = Record<strin
|
|
|
62
58
|
[K in keyof TComputed]: ComputedRef<TComputed[K]>;
|
|
63
59
|
};
|
|
64
60
|
}
|
|
65
|
-
|
|
61
|
+
declare function resetClientInstance(): void;
|
|
66
62
|
/**
|
|
67
63
|
* Creates a reusable data hook for a specific model
|
|
68
64
|
*
|
|
@@ -379,4 +375,74 @@ interface UseProductInstancesReturn {
|
|
|
379
375
|
*/
|
|
380
376
|
declare function useProductInstances(options?: UseProductInstancesOptions): UseProductInstancesReturn;
|
|
381
377
|
|
|
382
|
-
|
|
378
|
+
/**
|
|
379
|
+
* useReservations Hook
|
|
380
|
+
*
|
|
381
|
+
* Vue composable for fetching and managing reservation data with reactive state.
|
|
382
|
+
* Provides loading states, error handling, pagination, and refetch capabilities.
|
|
383
|
+
*/
|
|
384
|
+
|
|
385
|
+
interface UseReservationsOptions extends BaseHookOptions {
|
|
386
|
+
/** Filter by brand ID */
|
|
387
|
+
brandId?: string;
|
|
388
|
+
/** Filter by start date (check-in date >= startDate) */
|
|
389
|
+
startDate?: string;
|
|
390
|
+
/** Filter by end date (check-in date <= endDate) */
|
|
391
|
+
endDate?: string;
|
|
392
|
+
/** Filter by reservation status */
|
|
393
|
+
status?: Reservation["status"];
|
|
394
|
+
/** Filter by contact/visit ID */
|
|
395
|
+
contactId?: string;
|
|
396
|
+
/** Pagination token for fetching next page */
|
|
397
|
+
nextToken?: string;
|
|
398
|
+
}
|
|
399
|
+
interface UseReservationsReturn {
|
|
400
|
+
/** Reactive array of reservations */
|
|
401
|
+
reservations: Ref<Reservation[]>;
|
|
402
|
+
/** Computed array of confirmed reservations */
|
|
403
|
+
confirmedReservations: ComputedRef<Reservation[]>;
|
|
404
|
+
/** Computed array of active reservations (confirmed or checked_in) */
|
|
405
|
+
activeReservations: ComputedRef<Reservation[]>;
|
|
406
|
+
/** Loading state */
|
|
407
|
+
loading: Ref<boolean>;
|
|
408
|
+
/** Error state */
|
|
409
|
+
error: Ref<Error | null>;
|
|
410
|
+
/** Refetch reservations */
|
|
411
|
+
refetch: () => Promise<void>;
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Composable for fetching and managing reservations
|
|
415
|
+
*
|
|
416
|
+
* @example
|
|
417
|
+
* ```typescript
|
|
418
|
+
* import { useReservations } from '@htlkg/data/hooks';
|
|
419
|
+
*
|
|
420
|
+
* const { reservations, loading, error, refetch } = useReservations({
|
|
421
|
+
* brandId: 'brand-123',
|
|
422
|
+
* startDate: '2026-01-01',
|
|
423
|
+
* endDate: '2026-01-31',
|
|
424
|
+
* status: 'confirmed'
|
|
425
|
+
* });
|
|
426
|
+
* ```
|
|
427
|
+
*
|
|
428
|
+
* @example With contact filter
|
|
429
|
+
* ```typescript
|
|
430
|
+
* const { reservations, loading } = useReservations({
|
|
431
|
+
* contactId: 'contact-123',
|
|
432
|
+
* limit: 50
|
|
433
|
+
* });
|
|
434
|
+
* ```
|
|
435
|
+
*
|
|
436
|
+
* @example With computed properties
|
|
437
|
+
* ```typescript
|
|
438
|
+
* const { reservations, activeReservations, confirmedReservations } = useReservations({
|
|
439
|
+
* brandId: 'brand-123'
|
|
440
|
+
* });
|
|
441
|
+
*
|
|
442
|
+
* // activeReservations includes confirmed + checked_in
|
|
443
|
+
* // confirmedReservations includes only confirmed
|
|
444
|
+
* ```
|
|
445
|
+
*/
|
|
446
|
+
declare function useReservations(options?: UseReservationsOptions): UseReservationsReturn;
|
|
447
|
+
|
|
448
|
+
export { type BaseHookOptions, type CreateDataHookOptions, type DataHookReturn, type InferHookReturn, type UseAccountsOptions, type UseAccountsReturn, type UseBrandsOptions, type UseBrandsReturn, type UseProductInstancesOptions, type UseProductInstancesReturn, type UseProductsOptions, type UseProductsReturn, type UseReservationsOptions, type UseReservationsReturn, type UseUsersOptions, type UseUsersReturn, createDataHook, resetClientInstance, useAccounts, useBrands, useProductInstances, useProducts, useReservations, useUsers };
|