qlara 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aws.cjs +18 -11
- package/dist/aws.js +20 -13
- package/dist/cli.js +23 -16
- package/package.json +7 -3
- package/src/provider/aws/edge-handler.ts +303 -0
- package/src/provider/aws/renderer.ts +869 -0
- package/src/types.ts +561 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
// ── Metadata Types ───────────────────────────────────────────────
|
|
2
|
+
// Framework-agnostic metadata types. Covers the full range of HTML
|
|
3
|
+
// metadata that modern frameworks (Next.js, etc.) can generate.
|
|
4
|
+
// All fields are optional except `title`.
|
|
5
|
+
|
|
6
|
+
export interface QlaraAuthor {
|
|
7
|
+
name?: string;
|
|
8
|
+
url?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type QlaraReferrer =
|
|
12
|
+
| 'no-referrer'
|
|
13
|
+
| 'origin'
|
|
14
|
+
| 'no-referrer-when-downgrade'
|
|
15
|
+
| 'origin-when-cross-origin'
|
|
16
|
+
| 'same-origin'
|
|
17
|
+
| 'strict-origin'
|
|
18
|
+
| 'strict-origin-when-cross-origin';
|
|
19
|
+
|
|
20
|
+
// ── Robots ───────────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
export interface QlaraRobotsInfo {
|
|
23
|
+
index?: boolean;
|
|
24
|
+
follow?: boolean;
|
|
25
|
+
noarchive?: boolean;
|
|
26
|
+
nosnippet?: boolean;
|
|
27
|
+
noimageindex?: boolean;
|
|
28
|
+
nocache?: boolean;
|
|
29
|
+
notranslate?: boolean;
|
|
30
|
+
indexifembedded?: boolean;
|
|
31
|
+
nositelinkssearchbox?: boolean;
|
|
32
|
+
unavailable_after?: string;
|
|
33
|
+
'max-video-preview'?: number | string;
|
|
34
|
+
'max-image-preview'?: 'none' | 'standard' | 'large';
|
|
35
|
+
'max-snippet'?: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type QlaraRobots = string | (QlaraRobotsInfo & {
|
|
39
|
+
googleBot?: string | QlaraRobotsInfo;
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// ── Alternates ───────────────────────────────────────────────────
|
|
43
|
+
|
|
44
|
+
export interface QlaraAlternateLinkDescriptor {
|
|
45
|
+
title?: string;
|
|
46
|
+
url: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface QlaraAlternateURLs {
|
|
50
|
+
canonical?: string | QlaraAlternateLinkDescriptor;
|
|
51
|
+
languages?: Record<string, string | QlaraAlternateLinkDescriptor[]>;
|
|
52
|
+
media?: Record<string, string | QlaraAlternateLinkDescriptor[]>;
|
|
53
|
+
types?: Record<string, string | QlaraAlternateLinkDescriptor[]>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ── Icons ────────────────────────────────────────────────────────
|
|
57
|
+
|
|
58
|
+
export interface QlaraIconDescriptor {
|
|
59
|
+
url: string;
|
|
60
|
+
type?: string;
|
|
61
|
+
sizes?: string;
|
|
62
|
+
color?: string;
|
|
63
|
+
rel?: string;
|
|
64
|
+
media?: string;
|
|
65
|
+
fetchPriority?: 'high' | 'low' | 'auto';
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export type QlaraIcon = string | QlaraIconDescriptor;
|
|
69
|
+
|
|
70
|
+
export interface QlaraIcons {
|
|
71
|
+
icon?: QlaraIcon | QlaraIcon[];
|
|
72
|
+
shortcut?: QlaraIcon | QlaraIcon[];
|
|
73
|
+
apple?: QlaraIcon | QlaraIcon[];
|
|
74
|
+
other?: QlaraIconDescriptor | QlaraIconDescriptor[];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// ── Open Graph ───────────────────────────────────────────────────
|
|
78
|
+
|
|
79
|
+
export interface QlaraOGImageDescriptor {
|
|
80
|
+
url: string;
|
|
81
|
+
secureUrl?: string;
|
|
82
|
+
alt?: string;
|
|
83
|
+
type?: string;
|
|
84
|
+
width?: string | number;
|
|
85
|
+
height?: string | number;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export type QlaraOGImage = string | QlaraOGImageDescriptor;
|
|
89
|
+
|
|
90
|
+
export interface QlaraOGAudioDescriptor {
|
|
91
|
+
url: string;
|
|
92
|
+
secureUrl?: string;
|
|
93
|
+
type?: string;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export type QlaraOGAudio = string | QlaraOGAudioDescriptor;
|
|
97
|
+
|
|
98
|
+
export interface QlaraOGVideoDescriptor {
|
|
99
|
+
url: string;
|
|
100
|
+
secureUrl?: string;
|
|
101
|
+
type?: string;
|
|
102
|
+
width?: string | number;
|
|
103
|
+
height?: string | number;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export type QlaraOGVideo = string | QlaraOGVideoDescriptor;
|
|
107
|
+
|
|
108
|
+
export interface QlaraOpenGraphBase {
|
|
109
|
+
title?: string;
|
|
110
|
+
description?: string;
|
|
111
|
+
url?: string;
|
|
112
|
+
siteName?: string;
|
|
113
|
+
locale?: string;
|
|
114
|
+
alternateLocale?: string | string[];
|
|
115
|
+
determiner?: 'a' | 'an' | 'the' | 'auto' | '';
|
|
116
|
+
emails?: string | string[];
|
|
117
|
+
phoneNumbers?: string | string[];
|
|
118
|
+
faxNumbers?: string | string[];
|
|
119
|
+
countryName?: string;
|
|
120
|
+
ttl?: number;
|
|
121
|
+
images?: QlaraOGImage | QlaraOGImage[];
|
|
122
|
+
audio?: QlaraOGAudio | QlaraOGAudio[];
|
|
123
|
+
videos?: QlaraOGVideo | QlaraOGVideo[];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export interface QlaraOpenGraphWebsite extends QlaraOpenGraphBase {
|
|
127
|
+
type?: 'website';
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export interface QlaraOpenGraphArticle extends QlaraOpenGraphBase {
|
|
131
|
+
type: 'article';
|
|
132
|
+
publishedTime?: string;
|
|
133
|
+
modifiedTime?: string;
|
|
134
|
+
expirationTime?: string;
|
|
135
|
+
authors?: string | string[];
|
|
136
|
+
section?: string;
|
|
137
|
+
tags?: string | string[];
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export interface QlaraOpenGraphBook extends QlaraOpenGraphBase {
|
|
141
|
+
type: 'book';
|
|
142
|
+
isbn?: string;
|
|
143
|
+
releaseDate?: string;
|
|
144
|
+
authors?: string | string[];
|
|
145
|
+
tags?: string | string[];
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export interface QlaraOpenGraphProfile extends QlaraOpenGraphBase {
|
|
149
|
+
type: 'profile';
|
|
150
|
+
firstName?: string;
|
|
151
|
+
lastName?: string;
|
|
152
|
+
username?: string;
|
|
153
|
+
gender?: string;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export interface QlaraOpenGraphMusicSong extends QlaraOpenGraphBase {
|
|
157
|
+
type: 'music.song';
|
|
158
|
+
duration?: number;
|
|
159
|
+
albums?: string | string[];
|
|
160
|
+
musicians?: string | string[];
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export interface QlaraOpenGraphMusicAlbum extends QlaraOpenGraphBase {
|
|
164
|
+
type: 'music.album';
|
|
165
|
+
songs?: string | string[];
|
|
166
|
+
musicians?: string | string[];
|
|
167
|
+
releaseDate?: string;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export interface QlaraOpenGraphMusicPlaylist extends QlaraOpenGraphBase {
|
|
171
|
+
type: 'music.playlist';
|
|
172
|
+
songs?: string | string[];
|
|
173
|
+
creators?: string | string[];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export interface QlaraOpenGraphMusicRadioStation extends QlaraOpenGraphBase {
|
|
177
|
+
type: 'music.radio_station';
|
|
178
|
+
creators?: string | string[];
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export interface QlaraOpenGraphVideoMovie extends QlaraOpenGraphBase {
|
|
182
|
+
type: 'video.movie';
|
|
183
|
+
actors?: string | string[];
|
|
184
|
+
directors?: string | string[];
|
|
185
|
+
writers?: string | string[];
|
|
186
|
+
duration?: number;
|
|
187
|
+
releaseDate?: string;
|
|
188
|
+
tags?: string | string[];
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export interface QlaraOpenGraphVideoEpisode extends QlaraOpenGraphBase {
|
|
192
|
+
type: 'video.episode';
|
|
193
|
+
actors?: string | string[];
|
|
194
|
+
directors?: string | string[];
|
|
195
|
+
writers?: string | string[];
|
|
196
|
+
duration?: number;
|
|
197
|
+
releaseDate?: string;
|
|
198
|
+
tags?: string | string[];
|
|
199
|
+
series?: string;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export interface QlaraOpenGraphVideoTVShow extends QlaraOpenGraphBase {
|
|
203
|
+
type: 'video.tv_show';
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export interface QlaraOpenGraphVideoOther extends QlaraOpenGraphBase {
|
|
207
|
+
type: 'video.other';
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export type QlaraOpenGraph =
|
|
211
|
+
| QlaraOpenGraphWebsite
|
|
212
|
+
| QlaraOpenGraphArticle
|
|
213
|
+
| QlaraOpenGraphBook
|
|
214
|
+
| QlaraOpenGraphProfile
|
|
215
|
+
| QlaraOpenGraphMusicSong
|
|
216
|
+
| QlaraOpenGraphMusicAlbum
|
|
217
|
+
| QlaraOpenGraphMusicPlaylist
|
|
218
|
+
| QlaraOpenGraphMusicRadioStation
|
|
219
|
+
| QlaraOpenGraphVideoMovie
|
|
220
|
+
| QlaraOpenGraphVideoEpisode
|
|
221
|
+
| QlaraOpenGraphVideoTVShow
|
|
222
|
+
| QlaraOpenGraphVideoOther;
|
|
223
|
+
|
|
224
|
+
// ── Twitter ──────────────────────────────────────────────────────
|
|
225
|
+
|
|
226
|
+
export interface QlaraTwitterImageDescriptor {
|
|
227
|
+
url: string;
|
|
228
|
+
alt?: string;
|
|
229
|
+
secureUrl?: string;
|
|
230
|
+
type?: string;
|
|
231
|
+
width?: string | number;
|
|
232
|
+
height?: string | number;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export type QlaraTwitterImage = string | QlaraTwitterImageDescriptor;
|
|
236
|
+
|
|
237
|
+
export interface QlaraTwitterPlayerDescriptor {
|
|
238
|
+
playerUrl: string;
|
|
239
|
+
streamUrl: string;
|
|
240
|
+
width: number;
|
|
241
|
+
height: number;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export interface QlaraTwitterAppDescriptor {
|
|
245
|
+
id: {
|
|
246
|
+
iphone?: string | number;
|
|
247
|
+
ipad?: string | number;
|
|
248
|
+
googleplay?: string;
|
|
249
|
+
};
|
|
250
|
+
url?: {
|
|
251
|
+
iphone?: string;
|
|
252
|
+
ipad?: string;
|
|
253
|
+
googleplay?: string;
|
|
254
|
+
};
|
|
255
|
+
name?: string;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export interface QlaraTwitterBase {
|
|
259
|
+
site?: string;
|
|
260
|
+
siteId?: string;
|
|
261
|
+
creator?: string;
|
|
262
|
+
creatorId?: string;
|
|
263
|
+
title?: string;
|
|
264
|
+
description?: string;
|
|
265
|
+
images?: QlaraTwitterImage | QlaraTwitterImage[];
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export interface QlaraTwitterSummary extends QlaraTwitterBase {
|
|
269
|
+
card: 'summary';
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export interface QlaraTwitterSummaryLargeImage extends QlaraTwitterBase {
|
|
273
|
+
card: 'summary_large_image';
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export interface QlaraTwitterPlayer extends QlaraTwitterBase {
|
|
277
|
+
card: 'player';
|
|
278
|
+
players: QlaraTwitterPlayerDescriptor | QlaraTwitterPlayerDescriptor[];
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export interface QlaraTwitterApp extends QlaraTwitterBase {
|
|
282
|
+
card: 'app';
|
|
283
|
+
app: QlaraTwitterAppDescriptor;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export type QlaraTwitter =
|
|
287
|
+
| QlaraTwitterBase
|
|
288
|
+
| QlaraTwitterSummary
|
|
289
|
+
| QlaraTwitterSummaryLargeImage
|
|
290
|
+
| QlaraTwitterPlayer
|
|
291
|
+
| QlaraTwitterApp;
|
|
292
|
+
|
|
293
|
+
// ── Verification ─────────────────────────────────────────────────
|
|
294
|
+
|
|
295
|
+
export interface QlaraVerification {
|
|
296
|
+
google?: string | string[];
|
|
297
|
+
yahoo?: string | string[];
|
|
298
|
+
yandex?: string | string[];
|
|
299
|
+
me?: string | string[];
|
|
300
|
+
other?: Record<string, string | string[]>;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// ── Apple Web App ────────────────────────────────────────────────
|
|
304
|
+
|
|
305
|
+
export interface QlaraAppleImageDescriptor {
|
|
306
|
+
url: string;
|
|
307
|
+
media?: string;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export type QlaraAppleImage = string | QlaraAppleImageDescriptor;
|
|
311
|
+
|
|
312
|
+
export interface QlaraAppleWebApp {
|
|
313
|
+
capable?: boolean;
|
|
314
|
+
title?: string;
|
|
315
|
+
startupImage?: QlaraAppleImage | QlaraAppleImage[];
|
|
316
|
+
statusBarStyle?: 'default' | 'black' | 'black-translucent';
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// ── Format Detection ─────────────────────────────────────────────
|
|
320
|
+
|
|
321
|
+
export interface QlaraFormatDetection {
|
|
322
|
+
telephone?: boolean;
|
|
323
|
+
date?: boolean;
|
|
324
|
+
address?: boolean;
|
|
325
|
+
email?: boolean;
|
|
326
|
+
url?: boolean;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// ── iTunes App ───────────────────────────────────────────────────
|
|
330
|
+
|
|
331
|
+
export interface QlaraItunesApp {
|
|
332
|
+
appId: string;
|
|
333
|
+
appArgument?: string;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// ── Facebook ─────────────────────────────────────────────────────
|
|
337
|
+
|
|
338
|
+
export interface QlaraFacebook {
|
|
339
|
+
appId?: string;
|
|
340
|
+
admins?: string | string[];
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// ── Pinterest ────────────────────────────────────────────────────
|
|
344
|
+
|
|
345
|
+
export interface QlaraPinterest {
|
|
346
|
+
richPin?: string | boolean;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// ── App Links ────────────────────────────────────────────────────
|
|
350
|
+
|
|
351
|
+
export interface QlaraAppLinksApple {
|
|
352
|
+
url: string;
|
|
353
|
+
app_store_id?: string | number;
|
|
354
|
+
app_name?: string;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
export interface QlaraAppLinksAndroid {
|
|
358
|
+
package: string;
|
|
359
|
+
url?: string;
|
|
360
|
+
class?: string;
|
|
361
|
+
app_name?: string;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
export interface QlaraAppLinksWindows {
|
|
365
|
+
url: string;
|
|
366
|
+
app_id?: string;
|
|
367
|
+
app_name?: string;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
export interface QlaraAppLinksWeb {
|
|
371
|
+
url: string;
|
|
372
|
+
should_fallback?: boolean;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
export interface QlaraAppLinks {
|
|
376
|
+
ios?: QlaraAppLinksApple | QlaraAppLinksApple[];
|
|
377
|
+
iphone?: QlaraAppLinksApple | QlaraAppLinksApple[];
|
|
378
|
+
ipad?: QlaraAppLinksApple | QlaraAppLinksApple[];
|
|
379
|
+
android?: QlaraAppLinksAndroid | QlaraAppLinksAndroid[];
|
|
380
|
+
windows_phone?: QlaraAppLinksWindows | QlaraAppLinksWindows[];
|
|
381
|
+
windows?: QlaraAppLinksWindows | QlaraAppLinksWindows[];
|
|
382
|
+
windows_universal?: QlaraAppLinksWindows | QlaraAppLinksWindows[];
|
|
383
|
+
web?: QlaraAppLinksWeb | QlaraAppLinksWeb[];
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// ── Main Metadata Interface ──────────────────────────────────────
|
|
387
|
+
|
|
388
|
+
/** Metadata returned by a route's metaDataGenerator function. */
|
|
389
|
+
export interface QlaraMetadata {
|
|
390
|
+
// Basic metadata
|
|
391
|
+
title: string;
|
|
392
|
+
description?: string;
|
|
393
|
+
applicationName?: string;
|
|
394
|
+
authors?: QlaraAuthor | QlaraAuthor[];
|
|
395
|
+
generator?: string;
|
|
396
|
+
keywords?: string | string[];
|
|
397
|
+
referrer?: QlaraReferrer;
|
|
398
|
+
creator?: string;
|
|
399
|
+
publisher?: string;
|
|
400
|
+
category?: string;
|
|
401
|
+
classification?: string;
|
|
402
|
+
abstract?: string;
|
|
403
|
+
|
|
404
|
+
// Robots
|
|
405
|
+
robots?: QlaraRobots;
|
|
406
|
+
|
|
407
|
+
// Alternates (canonical, hreflang, etc.)
|
|
408
|
+
alternates?: QlaraAlternateURLs;
|
|
409
|
+
|
|
410
|
+
// Icons
|
|
411
|
+
icons?: string | QlaraIcon[] | QlaraIcons;
|
|
412
|
+
|
|
413
|
+
// Open Graph
|
|
414
|
+
openGraph?: QlaraOpenGraph;
|
|
415
|
+
|
|
416
|
+
// Twitter
|
|
417
|
+
twitter?: QlaraTwitter;
|
|
418
|
+
|
|
419
|
+
// Verification
|
|
420
|
+
verification?: QlaraVerification;
|
|
421
|
+
|
|
422
|
+
// Apple
|
|
423
|
+
appleWebApp?: boolean | QlaraAppleWebApp;
|
|
424
|
+
|
|
425
|
+
// Format detection
|
|
426
|
+
formatDetection?: QlaraFormatDetection;
|
|
427
|
+
|
|
428
|
+
// iTunes
|
|
429
|
+
itunes?: QlaraItunesApp;
|
|
430
|
+
|
|
431
|
+
// Facebook
|
|
432
|
+
facebook?: QlaraFacebook;
|
|
433
|
+
|
|
434
|
+
// Pinterest
|
|
435
|
+
pinterest?: QlaraPinterest;
|
|
436
|
+
|
|
437
|
+
// App links
|
|
438
|
+
appLinks?: QlaraAppLinks;
|
|
439
|
+
|
|
440
|
+
// Web app manifest
|
|
441
|
+
manifest?: string;
|
|
442
|
+
|
|
443
|
+
// Link tags
|
|
444
|
+
archives?: string | string[];
|
|
445
|
+
assets?: string | string[];
|
|
446
|
+
bookmarks?: string | string[];
|
|
447
|
+
|
|
448
|
+
// Pagination
|
|
449
|
+
pagination?: {
|
|
450
|
+
previous?: string;
|
|
451
|
+
next?: string;
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
// Catch-all for custom meta tags
|
|
455
|
+
other?: Record<string, string | number | (string | number)[]>;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Function that fetches data for a dynamic route and returns metadata.
|
|
460
|
+
* Equivalent to Next.js `generateMetadata()` — runs in the renderer Lambda
|
|
461
|
+
* with access to the data source.
|
|
462
|
+
*
|
|
463
|
+
* @param params - The route parameters, e.g. { id: '42' } for /product/:id
|
|
464
|
+
* @returns Metadata for the page, or null if the page doesn't exist
|
|
465
|
+
*/
|
|
466
|
+
export type QlaraMetaDataGenerator = (params: Record<string, string>) => Promise<QlaraMetadata | null>;
|
|
467
|
+
|
|
468
|
+
/** A single route definition with its pattern and metadata generator. */
|
|
469
|
+
export interface QlaraRouteDefinition {
|
|
470
|
+
/** Dynamic route pattern, e.g. '/product/:id' */
|
|
471
|
+
route: string;
|
|
472
|
+
/** Function that fetches metadata for this route from the data source */
|
|
473
|
+
metaDataGenerator: QlaraMetaDataGenerator;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* The route file default export type: an array of route definitions.
|
|
478
|
+
*
|
|
479
|
+
* Example:
|
|
480
|
+
* ```typescript
|
|
481
|
+
* import type { QlaraRoutes } from 'qlara';
|
|
482
|
+
* const routes: QlaraRoutes = [
|
|
483
|
+
* {
|
|
484
|
+
* route: '/product/:id',
|
|
485
|
+
* metaDataGenerator: async (params) => {
|
|
486
|
+
* const product = await getProduct(params.id);
|
|
487
|
+
* if (!product) return null;
|
|
488
|
+
* return { title: product.name, description: product.description };
|
|
489
|
+
* },
|
|
490
|
+
* },
|
|
491
|
+
* ];
|
|
492
|
+
* export default routes;
|
|
493
|
+
* ```
|
|
494
|
+
*/
|
|
495
|
+
export type QlaraRoutes = QlaraRouteDefinition[];
|
|
496
|
+
|
|
497
|
+
export interface QlaraRoute {
|
|
498
|
+
/** Dynamic route pattern, e.g. '/product/:id' */
|
|
499
|
+
pattern: string;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
export interface QlaraPluginConfig {
|
|
503
|
+
/**
|
|
504
|
+
* Path to a file that defines dynamic routes and their metadata generators.
|
|
505
|
+
* Each entry has a `route` pattern and a `metaDataGenerator` function.
|
|
506
|
+
*
|
|
507
|
+
* The file should `export default` a `QlaraRoutes` array.
|
|
508
|
+
* Route patterns are extracted from the `route` properties automatically.
|
|
509
|
+
*
|
|
510
|
+
* Example: `'./qlara.routes.ts'`
|
|
511
|
+
*/
|
|
512
|
+
routeFile: string;
|
|
513
|
+
provider: QlaraProvider;
|
|
514
|
+
/** Env var names to forward to the renderer Lambda (values read from process.env at build time) */
|
|
515
|
+
env?: string[];
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
export interface QlaraProvider {
|
|
519
|
+
name: string;
|
|
520
|
+
/** The serializable config passed to the provider factory (e.g. { region: 'eu-west-1' }) */
|
|
521
|
+
config: Record<string, unknown>;
|
|
522
|
+
setup(config: QlaraDeployConfig): Promise<ProviderResources>;
|
|
523
|
+
deploy(config: QlaraDeployConfig, resources: ProviderResources): Promise<void>;
|
|
524
|
+
exists(config: QlaraDeployConfig): Promise<ProviderResources | null>;
|
|
525
|
+
teardown(resources: ProviderResources): Promise<void>;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
export interface ProviderResources {
|
|
529
|
+
provider: string;
|
|
530
|
+
[key: string]: unknown;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/** Serialized config written to .qlara/config.json by the build plugin. Read by `qlara deploy`. */
|
|
534
|
+
export interface QlaraDeployConfig {
|
|
535
|
+
routes: QlaraRoute[];
|
|
536
|
+
provider: {
|
|
537
|
+
name: string;
|
|
538
|
+
[key: string]: unknown;
|
|
539
|
+
};
|
|
540
|
+
outputDir: string;
|
|
541
|
+
/** Absolute path to the route file. Bundled into the renderer Lambda at deploy time. */
|
|
542
|
+
routeFile: string;
|
|
543
|
+
/** Environment variables for the renderer Lambda (key-value pairs resolved at build time) */
|
|
544
|
+
env?: Record<string, string>;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
export interface QlaraManifest {
|
|
548
|
+
version: 1;
|
|
549
|
+
routes: ManifestRoute[];
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
export interface ManifestRoute {
|
|
553
|
+
pattern: string;
|
|
554
|
+
paramNames: string[];
|
|
555
|
+
regex: string;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
export interface RouteMatch {
|
|
559
|
+
route: ManifestRoute;
|
|
560
|
+
params: Record<string, string>;
|
|
561
|
+
}
|