@rimelight/config 0.0.10 → 0.0.12

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.
Files changed (4) hide show
  1. package/LICENSE +21 -0
  2. package/astro/index.ts +428 -422
  3. package/astro.d.ts +29 -5
  4. package/package.json +11 -12
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rimelight Entertainment
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/astro/index.ts CHANGED
@@ -1,422 +1,428 @@
1
- import fs from "node:fs"
2
- import path from "node:path"
3
- import cloudflare from "@astrojs/cloudflare"
4
- import { cacheCloudflare } from "@astrojs/cloudflare/cache"
5
- import { fontProviders } from "astro/config"
6
-
7
- export interface CacheRulesPresetOptions {
8
- apiSwrSeconds?: number
9
- pageMaxAgeSeconds?: number
10
- customRules?: Record<string, any>
11
- }
12
-
13
- export function cacheRulesPreset(options: CacheRulesPresetOptions = {}): any {
14
- const { apiSwrSeconds = 600, pageMaxAgeSeconds = 300, customRules = {} } = options
15
- return {
16
- routeRules: {
17
- "/api/[...path]": {
18
- swr: apiSwrSeconds
19
- },
20
- "/[...path]": {
21
- maxAge: pageMaxAgeSeconds
22
- },
23
- ...customRules
24
- }
25
- }
26
- }
27
-
28
- export interface FontsPresetOptions {
29
- fontProviders?: any
30
- fonts?: any[]
31
- }
32
-
33
- export function fontsPreset(options: FontsPresetOptions = {}): any {
34
- const defaultFonts = [
35
- {
36
- name: "Noto Sans",
37
- cssVariable: "--font-sans",
38
- fallbacks: ["sans-serif"],
39
- subsets: ["latin", "latin-ext"],
40
- weights: [400, 500, 600, 700],
41
- styles: ["normal"]
42
- },
43
- {
44
- name: "Noto Serif",
45
- cssVariable: "--font-serif",
46
- fallbacks: ["serif"],
47
- subsets: ["latin", "latin-ext"],
48
- weights: [400, 700],
49
- styles: ["normal"]
50
- },
51
- {
52
- name: "JetBrains Mono",
53
- cssVariable: "--font-mono",
54
- fallbacks: ["monospace"],
55
- subsets: ["latin", "latin-ext"],
56
- weights: [400, 500, 700],
57
- styles: ["normal"]
58
- }
59
- ]
60
-
61
- const provider = (options.fontProviders || fontProviders)?.fontsource
62
- ? (options.fontProviders || fontProviders).fontsource()
63
- : undefined
64
-
65
- return {
66
- fonts: (options.fonts || defaultFonts).map((font) => ({
67
- ...(provider ? { provider } : {}),
68
- ...font
69
- }))
70
- }
71
- }
72
-
73
- export interface ImagePresetOptions {
74
- domains?: string[]
75
- layout?: "constrained" | "fixed" | "full-width" | "responsive"
76
- responsiveStyles?: boolean
77
- }
78
-
79
- export function imagePreset(options: ImagePresetOptions = {}): any {
80
- const { domains = [], layout = "constrained", responsiveStyles = true } = options
81
- return {
82
- image: {
83
- domains,
84
- layout,
85
- responsiveStyles
86
- }
87
- }
88
- }
89
-
90
- export interface CloudflarePresetOptions {
91
- adapter?: any
92
- cacheProvider?: any
93
- session?: boolean
94
- }
95
-
96
- export function cloudflarePreset(options: CloudflarePresetOptions = {}): any {
97
- const { adapter = cloudflare(), cacheProvider = cacheCloudflare(), session = false } = options
98
- return {
99
- output: "server" as const,
100
- session,
101
- adapter,
102
- cache: { provider: cacheProvider }
103
- }
104
- }
105
-
106
- export interface RimelightAstroOptions {
107
- domain?: string
108
- site?: string
109
- imageDomains?: string[]
110
- apiSwrSeconds?: number
111
- pageMaxAgeSeconds?: number
112
- adapter?: any
113
- cacheProvider?: any
114
- fonts?: any[]
115
- solid?: boolean | { include?: string[]; [key: string]: any }
116
- security?:
117
- | boolean
118
- | {
119
- domain?: string
120
- imgSrc?: string[]
121
- directives?: Record<string, any>
122
- [key: string]: any
123
- }
124
- i18n?:
125
- | boolean
126
- | {
127
- translations?: Record<string, any>
128
- locales?: string[]
129
- defaultLocale?: string
130
- prefixDefaultLocale?: boolean
131
- kvBinding?: string
132
- [key: string]: any
133
- }
134
- seo?:
135
- | boolean
136
- | {
137
- robots?: boolean | Record<string, any>
138
- sitemap?: boolean | Record<string, any>
139
- rss?: boolean | Record<string, any>
140
- llms?: boolean | Record<string, any>
141
- llmsFull?: boolean | Record<string, any>
142
- assets?: boolean | Record<string, any>
143
- [key: string]: any
144
- }
145
- cms?:
146
- | boolean
147
- | {
148
- storage?: any
149
- binding?: string
150
- auth?: string
151
- [key: string]: any
152
- }
153
- ui?:
154
- | boolean
155
- | {
156
- logos?: any
157
- shortcuts?: any
158
- [key: string]: any
159
- }
160
- integrations?: any[]
161
- vite?: {
162
- plugins?: any[]
163
- [key: string]: any
164
- }
165
- [key: string]: any
166
- }
167
-
168
- function discoverTranslations(dir = "./src/i18n"): Record<string, any> {
169
- const translations: Record<string, any> = {}
170
- try {
171
- const resolvedDir = path.resolve(process.cwd(), dir)
172
- if (fs.existsSync(resolvedDir)) {
173
- const files = fs.readdirSync(resolvedDir)
174
- for (const file of files) {
175
- if (file.endsWith(".json")) {
176
- const locale = path.basename(file, ".json")
177
- const content = JSON.parse(fs.readFileSync(path.join(resolvedDir, file), "utf8"))
178
- translations[locale] = content
179
- }
180
- }
181
- }
182
- } catch {}
183
- return translations
184
- }
185
-
186
- function discoverLogos(dir = "./src/assets/logos"): Record<string, any> | undefined {
187
- try {
188
- const candidateDirs = [dir, "./src/assets/logo"]
189
- let resolvedDir: string | null = null
190
- for (const d of candidateDirs) {
191
- const p = path.resolve(process.cwd(), d)
192
- if (fs.existsSync(p) && fs.statSync(p).isDirectory()) {
193
- resolvedDir = p
194
- break
195
- }
196
- }
197
- if (!resolvedDir) return undefined
198
-
199
- const files = fs.readdirSync(resolvedDir)
200
- const logos: Record<string, any> = {}
201
-
202
- const variants = ["logomark", "logotype", "logo"]
203
- const modes = ["color", "white", "black", "light", "dark"]
204
- const extensions = [".svg", ".png", ".webp", ".jpg", ".jpeg", ".gif"]
205
-
206
- for (const variant of variants) {
207
- for (const mode of modes) {
208
- for (const ext of extensions) {
209
- const fileName = `${variant}_${mode}${ext}`
210
- if (files.includes(fileName)) {
211
- if (!logos[variant]) logos[variant] = {}
212
- const relPath = `./${path.relative(process.cwd(), path.join(resolvedDir, fileName)).replace(/\\/g, "/")}`
213
- logos[variant][mode] = relPath
214
- }
215
- }
216
- }
217
- for (const ext of extensions) {
218
- const fileName = `${variant}${ext}`
219
- if (files.includes(fileName) && !logos[variant]) {
220
- const relPath = `./${path.relative(process.cwd(), path.join(resolvedDir, fileName)).replace(/\\/g, "/")}`
221
- logos[variant] = relPath
222
- }
223
- }
224
- }
225
-
226
- return Object.keys(logos).length > 0 ? logos : undefined
227
- } catch {
228
- return undefined
229
- }
230
- }
231
-
232
- function defaultShortcuts(): Record<string, any> {
233
- return {
234
- categories: {
235
- system: { label: "System" },
236
- navigation: { label: "Navigation" }
237
- }
238
- }
239
- }
240
-
241
- function rimelightIntegration(
242
- options: RimelightAstroOptions,
243
- imageDomains: string[],
244
- domain?: string
245
- ) {
246
- return {
247
- name: "rimelight-auto-plugins",
248
- hooks: {
249
- "astro:config:setup": async ({ updateConfig }: { updateConfig: (config: any) => void }) => {
250
- const integrations: any[] = []
251
- const plugins: any[] = []
252
-
253
- if (options.solid) {
254
- const solidMod = await import("@astrojs/solid-js")
255
- const solidFn = (solidMod as any).default || solidMod
256
- const solidOpts =
257
- typeof options.solid === "object"
258
- ? options.solid
259
- : { include: ["**/solid/**", "**/*.tsx"] }
260
- integrations.push(solidFn(solidOpts))
261
- }
262
-
263
- if (options.seo) {
264
- const seoMod = await import("@rimelight/seo")
265
- const seoFn =
266
- (seoMod as any).rimelightSeo ||
267
- (seoMod as any).default?.rimelightSeo ||
268
- (seoMod as any).default ||
269
- seoMod
270
- const seoOpts = typeof options.seo === "object" ? options.seo : {}
271
- integrations.push(seoFn(seoOpts))
272
- }
273
-
274
- if (options.cms) {
275
- const cmsMod = await import("@rimelight/cms/integration")
276
- const { rimelightCms } = cmsMod as any
277
- const cmsOpts = typeof options.cms === "object" ? options.cms : {}
278
- let storage = cmsOpts.storage
279
- if (!storage) {
280
- const storageMod = await import("@rimelight/cms/storage")
281
- const { r2 } = storageMod as any
282
- storage = r2({ binding: cmsOpts.binding || "BLOB" })
283
- }
284
- integrations.push(
285
- rimelightCms({
286
- storage,
287
- auth: cmsOpts.auth || "./src/auth/auth.ts",
288
- ...cmsOpts
289
- })
290
- )
291
- }
292
-
293
- if (options.security) {
294
- const secMod = await import("@rimelight/security")
295
- const { security: securityFn } = secMod as any
296
- const secOpts = typeof options.security === "object" ? options.security : {}
297
- const defaultImgSrc = imageDomains.map((d: string) =>
298
- d.startsWith("http://") || d.startsWith("https://") ? d : `https://${d}`
299
- )
300
- const imgSrc = secOpts.imgSrc
301
- ? Array.from(new Set([...defaultImgSrc, ...secOpts.imgSrc]))
302
- : defaultImgSrc
303
-
304
- plugins.push(
305
- securityFn({
306
- domain: secOpts.domain || domain,
307
- imgSrc,
308
- ...secOpts
309
- })
310
- )
311
- }
312
-
313
- if (options.i18n) {
314
- const i18nMod = await import("@rimelight/i18n")
315
- const { i18n: i18nFn } = i18nMod as any
316
- const i18nOpts = typeof options.i18n === "object" ? options.i18n : {}
317
- const translations = i18nOpts.translations || discoverTranslations()
318
- const locales = i18nOpts.locales || Object.keys(translations)
319
- const defaultLocale = i18nOpts.defaultLocale || (locales.length > 0 ? locales[0] : "en")
320
- const kvBinding =
321
- i18nOpts.kvBinding ||
322
- (domain ? `${domain.replaceAll(".", "-")}_translations` : undefined)
323
-
324
- plugins.push(
325
- i18nFn({
326
- locales,
327
- defaultLocale,
328
- prefixDefaultLocale: i18nOpts.prefixDefaultLocale ?? true,
329
- translations,
330
- ...(kvBinding ? { kvBinding } : {}),
331
- ...i18nOpts
332
- })
333
- )
334
- }
335
-
336
- if (options.ui) {
337
- const uiMod = await import("@rimelight/ui")
338
- const { ui: uiFn } = uiMod as any
339
- const uiOpts = typeof options.ui === "object" ? options.ui : {}
340
- const discoveredLogos = discoverLogos()
341
-
342
- const mergedLogos = uiOpts.logos
343
- ? { ...discoveredLogos, ...uiOpts.logos }
344
- : discoveredLogos
345
-
346
- const mergedShortcuts =
347
- uiOpts.shortcuts === false
348
- ? undefined
349
- : {
350
- ...defaultShortcuts(),
351
- ...(typeof uiOpts.shortcuts === "object" ? uiOpts.shortcuts : {})
352
- }
353
-
354
- plugins.push(
355
- uiFn({
356
- ...(mergedLogos ? { logos: mergedLogos } : {}),
357
- ...(mergedShortcuts ? { shortcuts: mergedShortcuts } : {}),
358
- ...uiOpts
359
- })
360
- )
361
- }
362
-
363
- updateConfig({
364
- integrations,
365
- vite: {
366
- plugins
367
- }
368
- })
369
- }
370
- }
371
- }
372
- }
373
-
374
- export function rimelightAstroConfig(options: RimelightAstroOptions = {}): any {
375
- const {
376
- domain,
377
- site = domain ? `https://${domain}` : undefined,
378
- imageDomains = domain ? [domain, `cdn.${domain}`, "cdn.rimelight.com"] : [],
379
- apiSwrSeconds = 600,
380
- pageMaxAgeSeconds = 300,
381
- adapter,
382
- cacheProvider,
383
- fonts,
384
- solid,
385
- security,
386
- i18n,
387
- cms,
388
- ui,
389
- seo,
390
- integrations = [],
391
- vite = {},
392
- ...rest
393
- } = options
394
-
395
- const hasFlags = Boolean(solid || security || i18n || cms || ui || seo)
396
-
397
- return {
398
- ...(site ? { site } : {}),
399
- prefetch: {
400
- prefetchAll: true
401
- },
402
- ...cloudflarePreset({
403
- ...(adapter !== undefined ? { adapter } : {}),
404
- ...(cacheProvider !== undefined ? { cacheProvider } : {})
405
- }),
406
- ...cacheRulesPreset({
407
- ...(apiSwrSeconds !== undefined ? { apiSwrSeconds } : {}),
408
- ...(pageMaxAgeSeconds !== undefined ? { pageMaxAgeSeconds } : {})
409
- }),
410
- ...fontsPreset(fonts !== undefined ? { fonts } : {}),
411
- ...imagePreset({ domains: imageDomains }),
412
- markdown: {
413
- syntaxHighlight: "prism" as const
414
- },
415
- integrations: [
416
- ...(hasFlags ? [rimelightIntegration(options, imageDomains, domain)] : []),
417
- ...integrations
418
- ],
419
- vite,
420
- ...rest
421
- }
422
- }
1
+ import fs from "node:fs"
2
+ import path from "node:path"
3
+ import cloudflare from "@astrojs/cloudflare"
4
+ import { cacheCloudflare } from "@astrojs/cloudflare/cache"
5
+ import { fontProviders } from "astro/config"
6
+
7
+ export interface CacheRulesPresetOptions {
8
+ apiSwrSeconds?: number
9
+ pageMaxAgeSeconds?: number
10
+ customRules?: Record<string, any>
11
+ }
12
+
13
+ export function cacheRulesPreset(options: CacheRulesPresetOptions = {}): any {
14
+ const { apiSwrSeconds = 600, pageMaxAgeSeconds = 300, customRules = {} } = options
15
+ return {
16
+ routeRules: {
17
+ "/api/[...path]": {
18
+ swr: apiSwrSeconds
19
+ },
20
+ "/[...path]": {
21
+ maxAge: pageMaxAgeSeconds
22
+ },
23
+ ...customRules
24
+ }
25
+ }
26
+ }
27
+
28
+ export interface FontsPresetOptions {
29
+ fontProviders?: any
30
+ fonts?: any[]
31
+ }
32
+
33
+ export function fontsPreset(options: FontsPresetOptions = {}): any {
34
+ const defaultFonts = [
35
+ {
36
+ name: "Noto Sans",
37
+ cssVariable: "--font-sans",
38
+ fallbacks: ["sans-serif"],
39
+ subsets: ["latin", "latin-ext"],
40
+ weights: [400, 500, 600, 700],
41
+ styles: ["normal"]
42
+ },
43
+ {
44
+ name: "Noto Serif",
45
+ cssVariable: "--font-serif",
46
+ fallbacks: ["serif"],
47
+ subsets: ["latin", "latin-ext"],
48
+ weights: [400, 700],
49
+ styles: ["normal"]
50
+ },
51
+ {
52
+ name: "JetBrains Mono",
53
+ cssVariable: "--font-mono",
54
+ fallbacks: ["monospace"],
55
+ subsets: ["latin", "latin-ext"],
56
+ weights: [400, 500, 700],
57
+ styles: ["normal"]
58
+ }
59
+ ]
60
+
61
+ const provider = (options.fontProviders || fontProviders)?.fontsource
62
+ ? (options.fontProviders || fontProviders).fontsource()
63
+ : undefined
64
+
65
+ return {
66
+ fonts: (options.fonts || defaultFonts).map((font) => ({
67
+ ...(provider ? { provider } : {}),
68
+ ...font
69
+ }))
70
+ }
71
+ }
72
+
73
+ export interface ImagePresetOptions {
74
+ domains?: string[]
75
+ layout?: "constrained" | "fixed" | "full-width" | "responsive"
76
+ responsiveStyles?: boolean
77
+ }
78
+
79
+ export function imagePreset(options: ImagePresetOptions = {}): any {
80
+ const { domains = [], layout = "constrained", responsiveStyles = true } = options
81
+ return {
82
+ image: {
83
+ domains,
84
+ layout,
85
+ responsiveStyles
86
+ }
87
+ }
88
+ }
89
+
90
+ export interface CloudflarePresetOptions {
91
+ adapter?: any
92
+ cacheProvider?: any
93
+ session?: boolean
94
+ }
95
+
96
+ export function cloudflarePreset(options: CloudflarePresetOptions = {}): any {
97
+ const { adapter = cloudflare(), cacheProvider = cacheCloudflare(), session = false } = options
98
+ return {
99
+ output: "server" as const,
100
+ session,
101
+ adapter,
102
+ cache: { provider: cacheProvider }
103
+ }
104
+ }
105
+
106
+ export interface RimelightAstroOptions {
107
+ domain?: string
108
+ site?: string
109
+ imageDomains?: string[]
110
+ apiSwrSeconds?: number
111
+ pageMaxAgeSeconds?: number
112
+ adapter?: any
113
+ cacheProvider?: any
114
+ fonts?: any[]
115
+ solid?: boolean | { include?: string[]; [key: string]: any }
116
+ security?:
117
+ | boolean
118
+ | {
119
+ domain?: string
120
+ imgSrc?: string[]
121
+ directives?: Record<string, any>
122
+ [key: string]: any
123
+ }
124
+ i18n?:
125
+ | boolean
126
+ | {
127
+ translations?: Record<string, any>
128
+ locales?: string[]
129
+ defaultLocale?: string
130
+ prefixDefaultLocale?: boolean
131
+ kvBinding?: string
132
+ [key: string]: any
133
+ }
134
+ seo?:
135
+ | boolean
136
+ | {
137
+ robots?: boolean | Record<string, any>
138
+ sitemap?: boolean | Record<string, any>
139
+ rss?: boolean | Record<string, any>
140
+ llms?: boolean | Record<string, any>
141
+ llmsFull?: boolean | Record<string, any>
142
+ assets?: boolean | Record<string, any>
143
+ [key: string]: any
144
+ }
145
+ cms?:
146
+ | boolean
147
+ | {
148
+ storage?: any
149
+ binding?: string
150
+ auth?: string
151
+ [key: string]: any
152
+ }
153
+ ui?:
154
+ | boolean
155
+ | {
156
+ logos?: any
157
+ shortcuts?: any
158
+ [key: string]: any
159
+ }
160
+ integrations?: any[]
161
+ vite?: {
162
+ plugins?: any[]
163
+ [key: string]: any
164
+ }
165
+ [key: string]: any
166
+ }
167
+
168
+ function discoverTranslations(dir = "./src/i18n"): Record<string, any> {
169
+ const translations: Record<string, any> = {}
170
+ try {
171
+ const resolvedDir = path.resolve(process.cwd(), dir)
172
+ if (fs.existsSync(resolvedDir)) {
173
+ const files = fs.readdirSync(resolvedDir)
174
+ for (const file of files) {
175
+ if (file.endsWith(".json")) {
176
+ const locale = path.basename(file, ".json")
177
+ const content = JSON.parse(fs.readFileSync(path.join(resolvedDir, file), "utf8"))
178
+ translations[locale] = content
179
+ }
180
+ }
181
+ }
182
+ } catch {}
183
+ return translations
184
+ }
185
+
186
+ function discoverLogos(dir = "./src/assets/logos"): Record<string, any> | undefined {
187
+ try {
188
+ const candidateDirs = [dir, "./src/assets/logo"]
189
+ let resolvedDir: string | null = null
190
+ for (const d of candidateDirs) {
191
+ const p = path.resolve(process.cwd(), d)
192
+ if (fs.existsSync(p) && fs.statSync(p).isDirectory()) {
193
+ resolvedDir = p
194
+ break
195
+ }
196
+ }
197
+ if (!resolvedDir) return undefined
198
+
199
+ const files = fs.readdirSync(resolvedDir)
200
+ const logos: Record<string, any> = {}
201
+
202
+ const variants = ["logomark", "logotype", "logo"]
203
+ const modes = ["color", "white", "black", "light", "dark"]
204
+ const extensions = [".svg", ".png", ".webp", ".jpg", ".jpeg", ".gif"]
205
+
206
+ for (const variant of variants) {
207
+ for (const mode of modes) {
208
+ for (const ext of extensions) {
209
+ const fileName = `${variant}_${mode}${ext}`
210
+ if (files.includes(fileName)) {
211
+ if (!logos[variant]) logos[variant] = {}
212
+ const relPath = `./${path.relative(process.cwd(), path.join(resolvedDir, fileName)).replace(/\\/g, "/")}`
213
+ logos[variant][mode] = relPath
214
+ }
215
+ }
216
+ }
217
+ for (const ext of extensions) {
218
+ const fileName = `${variant}${ext}`
219
+ if (files.includes(fileName) && !logos[variant]) {
220
+ const relPath = `./${path.relative(process.cwd(), path.join(resolvedDir, fileName)).replace(/\\/g, "/")}`
221
+ logos[variant] = relPath
222
+ }
223
+ }
224
+ }
225
+
226
+ return Object.keys(logos).length > 0 ? logos : undefined
227
+ } catch {
228
+ return undefined
229
+ }
230
+ }
231
+
232
+ function defaultShortcuts(): Record<string, any> {
233
+ return {
234
+ categories: {
235
+ system: { label: "System" },
236
+ navigation: { label: "Navigation" }
237
+ }
238
+ }
239
+ }
240
+
241
+ function rimelightIntegration(
242
+ options: RimelightAstroOptions,
243
+ imageDomains: string[],
244
+ domain?: string
245
+ ) {
246
+ return {
247
+ name: "rimelight-auto-plugins",
248
+ hooks: {
249
+ "astro:config:setup": async ({ updateConfig }: { updateConfig: (config: any) => void }) => {
250
+ const integrations: any[] = []
251
+ const plugins: any[] = []
252
+
253
+ if (options.solid) {
254
+ const solidMod = await import("@astrojs/solid-js")
255
+ const solidFn = (solidMod as any).default || solidMod
256
+ const solidOpts =
257
+ typeof options.solid === "object"
258
+ ? options.solid
259
+ : { include: ["**/solid/**", "**/*.tsx"] }
260
+ integrations.push(solidFn(solidOpts))
261
+ }
262
+
263
+ if (options.seo) {
264
+ const seoMod = await import("@rimelight/seo")
265
+ const seoFn =
266
+ (seoMod as any).rimelightSeo ||
267
+ (seoMod as any).default?.rimelightSeo ||
268
+ (seoMod as any).default ||
269
+ seoMod
270
+ const seoOpts = typeof options.seo === "object" ? options.seo : {}
271
+ integrations.push(
272
+ seoFn({
273
+ id: domain,
274
+ url: site || (domain ? `https://${domain}` : undefined),
275
+ ...seoOpts
276
+ })
277
+ )
278
+ }
279
+
280
+ if (options.cms) {
281
+ const cmsMod = await import("@rimelight/cms/integration")
282
+ const { rimelightCms } = cmsMod as any
283
+ const cmsOpts = typeof options.cms === "object" ? options.cms : {}
284
+ let storage = cmsOpts.storage
285
+ if (!storage) {
286
+ const storageMod = await import("@rimelight/cms/storage")
287
+ const { r2 } = storageMod as any
288
+ storage = r2({ binding: cmsOpts.binding || "BLOB" })
289
+ }
290
+ integrations.push(
291
+ rimelightCms({
292
+ storage,
293
+ auth: cmsOpts.auth || "./src/auth/auth.ts",
294
+ ...cmsOpts
295
+ })
296
+ )
297
+ }
298
+
299
+ if (options.security) {
300
+ const secMod = await import("@rimelight/security")
301
+ const { security: securityFn } = secMod as any
302
+ const secOpts = typeof options.security === "object" ? options.security : {}
303
+ const defaultImgSrc = imageDomains.map((d: string) =>
304
+ d.startsWith("http://") || d.startsWith("https://") ? d : `https://${d}`
305
+ )
306
+ const imgSrc = secOpts.imgSrc
307
+ ? Array.from(new Set([...defaultImgSrc, ...secOpts.imgSrc]))
308
+ : defaultImgSrc
309
+
310
+ plugins.push(
311
+ securityFn({
312
+ domain: secOpts.domain || domain,
313
+ imgSrc,
314
+ ...secOpts
315
+ })
316
+ )
317
+ }
318
+
319
+ if (options.i18n) {
320
+ const i18nMod = await import("@rimelight/i18n")
321
+ const { i18n: i18nFn } = i18nMod as any
322
+ const i18nOpts = typeof options.i18n === "object" ? options.i18n : {}
323
+ const translations = i18nOpts.translations || discoverTranslations()
324
+ const locales = i18nOpts.locales || Object.keys(translations)
325
+ const defaultLocale = i18nOpts.defaultLocale || (locales.length > 0 ? locales[0] : "en")
326
+ const kvBinding =
327
+ i18nOpts.kvBinding ||
328
+ (domain ? `${domain.replaceAll(".", "-")}_translations` : undefined)
329
+
330
+ plugins.push(
331
+ i18nFn({
332
+ locales,
333
+ defaultLocale,
334
+ prefixDefaultLocale: i18nOpts.prefixDefaultLocale ?? true,
335
+ translations,
336
+ ...(kvBinding ? { kvBinding } : {}),
337
+ ...i18nOpts
338
+ })
339
+ )
340
+ }
341
+
342
+ if (options.ui) {
343
+ const uiMod = await import("@rimelight/ui")
344
+ const { ui: uiFn } = uiMod as any
345
+ const uiOpts = typeof options.ui === "object" ? options.ui : {}
346
+ const discoveredLogos = discoverLogos()
347
+
348
+ const mergedLogos = uiOpts.logos
349
+ ? { ...discoveredLogos, ...uiOpts.logos }
350
+ : discoveredLogos
351
+
352
+ const mergedShortcuts =
353
+ uiOpts.shortcuts === false
354
+ ? undefined
355
+ : {
356
+ ...defaultShortcuts(),
357
+ ...(typeof uiOpts.shortcuts === "object" ? uiOpts.shortcuts : {})
358
+ }
359
+
360
+ plugins.push(
361
+ uiFn({
362
+ ...(mergedLogos ? { logos: mergedLogos } : {}),
363
+ ...(mergedShortcuts ? { shortcuts: mergedShortcuts } : {}),
364
+ ...uiOpts
365
+ })
366
+ )
367
+ }
368
+
369
+ updateConfig({
370
+ integrations,
371
+ vite: {
372
+ plugins
373
+ }
374
+ })
375
+ }
376
+ }
377
+ }
378
+ }
379
+
380
+ export function rimelightAstroConfig(options: RimelightAstroOptions = {}): any {
381
+ const {
382
+ domain,
383
+ site = domain ? `https://${domain}` : undefined,
384
+ imageDomains = domain ? [domain, `cdn.${domain}`, "cdn.rimelight.com"] : [],
385
+ apiSwrSeconds = 600,
386
+ pageMaxAgeSeconds = 300,
387
+ adapter,
388
+ cacheProvider,
389
+ fonts,
390
+ solid,
391
+ security,
392
+ i18n,
393
+ cms,
394
+ ui,
395
+ seo,
396
+ integrations = [],
397
+ vite = {},
398
+ ...rest
399
+ } = options
400
+
401
+ const hasFlags = Boolean(solid || security || i18n || cms || ui || seo)
402
+
403
+ return {
404
+ ...(site ? { site } : {}),
405
+ prefetch: {
406
+ prefetchAll: true
407
+ },
408
+ ...cloudflarePreset({
409
+ ...(adapter !== undefined ? { adapter } : {}),
410
+ ...(cacheProvider !== undefined ? { cacheProvider } : {})
411
+ }),
412
+ ...cacheRulesPreset({
413
+ ...(apiSwrSeconds !== undefined ? { apiSwrSeconds } : {}),
414
+ ...(pageMaxAgeSeconds !== undefined ? { pageMaxAgeSeconds } : {})
415
+ }),
416
+ ...fontsPreset(fonts !== undefined ? { fonts } : {}),
417
+ ...imagePreset({ domains: imageDomains }),
418
+ markdown: {
419
+ syntaxHighlight: "prism" as const
420
+ },
421
+ integrations: [
422
+ ...(hasFlags ? [rimelightIntegration(options, imageDomains, domain)] : []),
423
+ ...integrations
424
+ ],
425
+ vite,
426
+ ...rest
427
+ }
428
+ }
package/astro.d.ts CHANGED
@@ -1,5 +1,29 @@
1
- /// <reference types="astro/client" />
2
-
3
- declare module "*.astro" {
4
- export default {} as import("astro/runtime/server").AstroComponentFactory
5
- }
1
+ /// <reference types="astro/client" />
2
+
3
+ declare module "*.astro" {
4
+ export default {} as import("astro/runtime/server").AstroComponentFactory
5
+ }
6
+
7
+ declare module "virtual:rimelight/seo" {
8
+ export const siteConfig: import("@rimelight/seo").SiteConfig
9
+ export const SEO_LOCALES: import("@rimelight/seo").LocaleConfig | Record<string, string> | undefined
10
+ export const PRIVATE_PATH_PREFIXES: string[]
11
+ export const seoConfig: {
12
+ SEO_LOCALES?: import("@rimelight/seo").LocaleConfig | Record<string, string>
13
+ PRIVATE_PATH_PREFIXES: string[]
14
+ }
15
+ export default siteConfig
16
+ }
17
+
18
+ declare module "virtual:rimelight/i18n" {
19
+ export const locales: string[]
20
+ export const languages: string[]
21
+ export const defaultLocale: string
22
+ export const prefixDefaultLocale: boolean
23
+ export const translations: Record<string, Record<string, any>> | undefined
24
+ export default {
25
+ locales: [] as string[],
26
+ defaultLocale: ""
27
+ }
28
+ }
29
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rimelight/config",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "private": false,
5
5
  "description": "Rimelight Entertainment's shared configuration package",
6
6
  "homepage": "https://rimelight.com/docs",
@@ -47,19 +47,19 @@
47
47
  },
48
48
  "devDependencies": {
49
49
  "@astrojs/cloudflare": "14.3.1",
50
- "astro": "7.3.2",
50
+ "astro": "7.3.3",
51
51
  "drizzle-kit": "0.31.10",
52
52
  "typescript": "6.0.3",
53
- "vite-plus": "0.3.1"
53
+ "vite-plus": "0.3.2"
54
54
  },
55
55
  "peerDependencies": {
56
56
  "@astrojs/cloudflare": ">=14.0.0",
57
57
  "@astrojs/solid-js": ">=7.0.0",
58
- "@rimelight/cms": "workspace:*",
59
- "@rimelight/i18n": "workspace:*",
60
- "@rimelight/security": "workspace:*",
61
- "@rimelight/seo": "workspace:*",
62
- "@rimelight/ui": "workspace:*",
58
+ "@rimelight/cms": "0.0.13",
59
+ "@rimelight/i18n": "0.0.14",
60
+ "@rimelight/security": "0.0.16",
61
+ "@rimelight/seo": "0.0.9",
62
+ "@rimelight/ui": "0.0.53",
63
63
  "astro": ">=7.0.0",
64
64
  "drizzle-kit": ">=0.30.0"
65
65
  },
@@ -93,7 +93,6 @@
93
93
  }
94
94
  },
95
95
  "engines": {
96
- "node": ">=26.8.2"
97
- },
98
- "packageManager": "pnpm@12.4.1"
99
- }
96
+ "node": ">=26.9.0"
97
+ }
98
+ }