@rimelight/config 0.0.12 → 0.0.14

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/astro/index.js CHANGED
@@ -153,7 +153,7 @@ function defaultShortcuts() {
153
153
  }
154
154
  }
155
155
 
156
- function rimelightIntegration(options, imageDomains, domain) {
156
+ function rimelightIntegration(options, imageDomains, domain, site) {
157
157
  return {
158
158
  name: "rimelight-auto-plugins",
159
159
  hooks: {
@@ -176,7 +176,13 @@ function rimelightIntegration(options, imageDomains, domain) {
176
176
  const seoFn =
177
177
  seoMod.rimelightSeo || seoMod.default?.rimelightSeo || seoMod.default || seoMod
178
178
  const seoOpts = typeof options.seo === "object" ? options.seo : {}
179
- integrations.push(seoFn(seoOpts))
179
+ integrations.push(
180
+ seoFn({
181
+ id: domain,
182
+ url: site || (domain ? `https://${domain}` : undefined),
183
+ ...seoOpts
184
+ })
185
+ )
180
186
  }
181
187
 
182
188
  if (options.cms) {
@@ -192,7 +198,7 @@ function rimelightIntegration(options, imageDomains, domain) {
192
198
  integrations.push(
193
199
  rimelightCms({
194
200
  storage,
195
- auth: cmsOpts.auth || "./src/auth/auth.ts",
201
+ ...(cmsOpts.auth ? { auth: cmsOpts.auth } : {}),
196
202
  ...cmsOpts
197
203
  })
198
204
  )
@@ -218,6 +224,16 @@ function rimelightIntegration(options, imageDomains, domain) {
218
224
  )
219
225
  }
220
226
 
227
+ if (options.auth) {
228
+ const authMod = await import("@rimelight/auth/vite")
229
+ const { auth: authFn } = authMod
230
+ const authOpts =
231
+ typeof options.auth === "object"
232
+ ? options.auth
233
+ : { adapter: options.auth === true ? "cf-access" : options.auth }
234
+ plugins.push(authFn(authOpts))
235
+ }
236
+
221
237
  if (options.i18n) {
222
238
  const i18nMod = await import("@rimelight/i18n")
223
239
  const { i18n: i18nFn } = i18nMod
@@ -295,12 +311,13 @@ export function rimelightAstroConfig(options = {}) {
295
311
  cms,
296
312
  ui,
297
313
  seo,
314
+ auth,
298
315
  integrations = [],
299
316
  vite = {},
300
317
  ...rest
301
318
  } = options
302
319
 
303
- const hasFlags = Boolean(solid || security || i18n || cms || ui || seo)
320
+ const hasFlags = Boolean(solid || security || i18n || cms || ui || seo || auth)
304
321
 
305
322
  return {
306
323
  ...(site ? { site } : {}),
@@ -321,7 +338,7 @@ export function rimelightAstroConfig(options = {}) {
321
338
  syntaxHighlight: "prism"
322
339
  },
323
340
  integrations: [
324
- ...(hasFlags ? [rimelightIntegration(options, imageDomains, domain)] : []),
341
+ ...(hasFlags ? [rimelightIntegration(options, imageDomains, domain, site)] : []),
325
342
  ...integrations
326
343
  ],
327
344
  vite,
package/astro/index.ts CHANGED
@@ -1,428 +1,450 @@
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
- }
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
+ auth?:
154
+ | boolean
155
+ | "cf-access"
156
+ | "auth0"
157
+ | "mock"
158
+ | {
159
+ adapter?: "cf-access" | "auth0" | "mock" | "custom" | (string & {})
160
+ customModule?: string
161
+ [key: string]: any
162
+ }
163
+ ui?:
164
+ | boolean
165
+ | {
166
+ logos?: any
167
+ shortcuts?: any
168
+ [key: string]: any
169
+ }
170
+ integrations?: any[]
171
+ vite?: {
172
+ plugins?: any[]
173
+ [key: string]: any
174
+ }
175
+ [key: string]: any
176
+ }
177
+
178
+ function discoverTranslations(dir = "./src/i18n"): Record<string, any> {
179
+ const translations: Record<string, any> = {}
180
+ try {
181
+ const resolvedDir = path.resolve(process.cwd(), dir)
182
+ if (fs.existsSync(resolvedDir)) {
183
+ const files = fs.readdirSync(resolvedDir)
184
+ for (const file of files) {
185
+ if (file.endsWith(".json")) {
186
+ const locale = path.basename(file, ".json")
187
+ const content = JSON.parse(fs.readFileSync(path.join(resolvedDir, file), "utf8"))
188
+ translations[locale] = content
189
+ }
190
+ }
191
+ }
192
+ } catch {}
193
+ return translations
194
+ }
195
+
196
+ function discoverLogos(dir = "./src/assets/logos"): Record<string, any> | undefined {
197
+ try {
198
+ const candidateDirs = [dir, "./src/assets/logo"]
199
+ let resolvedDir: string | null = null
200
+ for (const d of candidateDirs) {
201
+ const p = path.resolve(process.cwd(), d)
202
+ if (fs.existsSync(p) && fs.statSync(p).isDirectory()) {
203
+ resolvedDir = p
204
+ break
205
+ }
206
+ }
207
+ if (!resolvedDir) return undefined
208
+
209
+ const files = fs.readdirSync(resolvedDir)
210
+ const logos: Record<string, any> = {}
211
+
212
+ const variants = ["logomark", "logotype", "logo"]
213
+ const modes = ["color", "white", "black", "light", "dark"]
214
+ const extensions = [".svg", ".png", ".webp", ".jpg", ".jpeg", ".gif"]
215
+
216
+ for (const variant of variants) {
217
+ for (const mode of modes) {
218
+ for (const ext of extensions) {
219
+ const fileName = `${variant}_${mode}${ext}`
220
+ if (files.includes(fileName)) {
221
+ if (!logos[variant]) logos[variant] = {}
222
+ const relPath = `./${path.relative(process.cwd(), path.join(resolvedDir, fileName)).replace(/\\/g, "/")}`
223
+ logos[variant][mode] = relPath
224
+ }
225
+ }
226
+ }
227
+ for (const ext of extensions) {
228
+ const fileName = `${variant}${ext}`
229
+ if (files.includes(fileName) && !logos[variant]) {
230
+ const relPath = `./${path.relative(process.cwd(), path.join(resolvedDir, fileName)).replace(/\\/g, "/")}`
231
+ logos[variant] = relPath
232
+ }
233
+ }
234
+ }
235
+
236
+ return Object.keys(logos).length > 0 ? logos : undefined
237
+ } catch {
238
+ return undefined
239
+ }
240
+ }
241
+
242
+ function defaultShortcuts(): Record<string, any> {
243
+ return {
244
+ categories: {
245
+ system: { label: "System" },
246
+ navigation: { label: "Navigation" }
247
+ }
248
+ }
249
+ }
250
+
251
+ function rimelightIntegration(
252
+ options: RimelightAstroOptions,
253
+ imageDomains: string[],
254
+ domain?: string,
255
+ site?: string
256
+ ) {
257
+ return {
258
+ name: "rimelight-auto-plugins",
259
+ hooks: {
260
+ "astro:config:setup": async ({ updateConfig }: { updateConfig: (config: any) => void }) => {
261
+ const integrations: any[] = []
262
+ const plugins: any[] = []
263
+
264
+ if (options.solid) {
265
+ const solidMod = await import("@astrojs/solid-js")
266
+ const solidFn = (solidMod as any).default || solidMod
267
+ const solidOpts =
268
+ typeof options.solid === "object"
269
+ ? options.solid
270
+ : { include: ["**/solid/**", "**/*.tsx"] }
271
+ integrations.push(solidFn(solidOpts))
272
+ }
273
+
274
+ if (options.seo) {
275
+ const seoMod = await import("@rimelight/seo")
276
+ const seoFn =
277
+ (seoMod as any).rimelightSeo ||
278
+ (seoMod as any).default?.rimelightSeo ||
279
+ (seoMod as any).default ||
280
+ seoMod
281
+ const seoOpts = typeof options.seo === "object" ? options.seo : {}
282
+ integrations.push(
283
+ seoFn({
284
+ id: domain,
285
+ url: site || (domain ? `https://${domain}` : undefined),
286
+ ...seoOpts
287
+ })
288
+ )
289
+ }
290
+
291
+ if (options.cms) {
292
+ const cmsMod = await import("@rimelight/cms/integration")
293
+ const { rimelightCms } = cmsMod as any
294
+ const cmsOpts = typeof options.cms === "object" ? options.cms : {}
295
+ let storage = cmsOpts.storage
296
+ if (!storage) {
297
+ const storageMod = await import("@rimelight/cms/storage")
298
+ const { r2 } = storageMod as any
299
+ storage = r2({ binding: cmsOpts.binding || "BLOB" })
300
+ }
301
+ integrations.push(
302
+ rimelightCms({
303
+ storage,
304
+ ...(cmsOpts.auth ? { auth: cmsOpts.auth } : {}),
305
+ ...cmsOpts
306
+ })
307
+ )
308
+ }
309
+
310
+ if (options.security) {
311
+ const secMod = await import("@rimelight/security")
312
+ const { security: securityFn } = secMod as any
313
+ const secOpts = typeof options.security === "object" ? options.security : {}
314
+ const defaultImgSrc = imageDomains.map((d: string) =>
315
+ d.startsWith("http://") || d.startsWith("https://") ? d : `https://${d}`
316
+ )
317
+ const imgSrc = secOpts.imgSrc
318
+ ? Array.from(new Set([...defaultImgSrc, ...secOpts.imgSrc]))
319
+ : defaultImgSrc
320
+
321
+ plugins.push(
322
+ securityFn({
323
+ domain: secOpts.domain || domain,
324
+ imgSrc,
325
+ ...secOpts
326
+ })
327
+ )
328
+ }
329
+
330
+ if (options.auth) {
331
+ const authMod = await import("@rimelight/auth/vite")
332
+ const { auth: authFn } = authMod as any
333
+ const authOpts =
334
+ typeof options.auth === "object"
335
+ ? options.auth
336
+ : { adapter: options.auth === true ? "cf-access" : options.auth }
337
+ plugins.push(authFn(authOpts))
338
+ }
339
+
340
+ if (options.i18n) {
341
+ const i18nMod = await import("@rimelight/i18n")
342
+ const { i18n: i18nFn } = i18nMod as any
343
+ const i18nOpts = typeof options.i18n === "object" ? options.i18n : {}
344
+ const translations = i18nOpts.translations || discoverTranslations()
345
+ const locales = i18nOpts.locales || Object.keys(translations)
346
+ const defaultLocale = i18nOpts.defaultLocale || (locales.length > 0 ? locales[0] : "en")
347
+ const kvBinding =
348
+ i18nOpts.kvBinding ||
349
+ (domain ? `${domain.replaceAll(".", "-")}_translations` : undefined)
350
+
351
+ plugins.push(
352
+ i18nFn({
353
+ locales,
354
+ defaultLocale,
355
+ prefixDefaultLocale: i18nOpts.prefixDefaultLocale ?? true,
356
+ translations,
357
+ ...(kvBinding ? { kvBinding } : {}),
358
+ ...i18nOpts
359
+ })
360
+ )
361
+ }
362
+
363
+ if (options.ui) {
364
+ const uiMod = await import("@rimelight/ui")
365
+ const { ui: uiFn } = uiMod as any
366
+ const uiOpts = typeof options.ui === "object" ? options.ui : {}
367
+ const discoveredLogos = discoverLogos()
368
+
369
+ const mergedLogos = uiOpts.logos
370
+ ? { ...discoveredLogos, ...uiOpts.logos }
371
+ : discoveredLogos
372
+
373
+ const mergedShortcuts =
374
+ uiOpts.shortcuts === false
375
+ ? undefined
376
+ : {
377
+ ...defaultShortcuts(),
378
+ ...(typeof uiOpts.shortcuts === "object" ? uiOpts.shortcuts : {})
379
+ }
380
+
381
+ plugins.push(
382
+ uiFn({
383
+ ...(mergedLogos ? { logos: mergedLogos } : {}),
384
+ ...(mergedShortcuts ? { shortcuts: mergedShortcuts } : {}),
385
+ ...uiOpts
386
+ })
387
+ )
388
+ }
389
+
390
+ updateConfig({
391
+ integrations,
392
+ vite: {
393
+ plugins
394
+ }
395
+ })
396
+ }
397
+ }
398
+ }
399
+ }
400
+
401
+ export function rimelightAstroConfig(options: RimelightAstroOptions = {}): any {
402
+ const {
403
+ domain,
404
+ site = domain ? `https://${domain}` : undefined,
405
+ imageDomains = domain ? [domain, `cdn.${domain}`, "cdn.rimelight.com"] : [],
406
+ apiSwrSeconds = 600,
407
+ pageMaxAgeSeconds = 300,
408
+ adapter,
409
+ cacheProvider,
410
+ fonts,
411
+ solid,
412
+ security,
413
+ i18n,
414
+ cms,
415
+ ui,
416
+ seo,
417
+ auth,
418
+ integrations = [],
419
+ vite = {},
420
+ ...rest
421
+ } = options
422
+
423
+ const hasFlags = Boolean(solid || security || i18n || cms || ui || seo || auth)
424
+
425
+ return {
426
+ ...(site ? { site } : {}),
427
+ prefetch: {
428
+ prefetchAll: true
429
+ },
430
+ ...cloudflarePreset({
431
+ ...(adapter !== undefined ? { adapter } : {}),
432
+ ...(cacheProvider !== undefined ? { cacheProvider } : {})
433
+ }),
434
+ ...cacheRulesPreset({
435
+ ...(apiSwrSeconds !== undefined ? { apiSwrSeconds } : {}),
436
+ ...(pageMaxAgeSeconds !== undefined ? { pageMaxAgeSeconds } : {})
437
+ }),
438
+ ...fontsPreset(fonts !== undefined ? { fonts } : {}),
439
+ ...imagePreset({ domains: imageDomains }),
440
+ markdown: {
441
+ syntaxHighlight: "prism" as const
442
+ },
443
+ integrations: [
444
+ ...(hasFlags ? [rimelightIntegration(options, imageDomains, domain, site)] : []),
445
+ ...integrations
446
+ ],
447
+ vite,
448
+ ...rest
449
+ }
450
+ }
package/astro.d.ts CHANGED
@@ -1,29 +1,55 @@
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
-
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:
10
+ | import("@rimelight/seo").LocaleConfig
11
+ | Record<string, string>
12
+ | undefined
13
+ export const PRIVATE_PATH_PREFIXES: string[]
14
+ export const seoConfig: {
15
+ SEO_LOCALES?: import("@rimelight/seo").LocaleConfig | Record<string, string>
16
+ PRIVATE_PATH_PREFIXES: string[]
17
+ }
18
+ export default siteConfig
19
+ }
20
+
21
+ declare module "virtual:rimelight/i18n" {
22
+ export const locales: string[]
23
+ export const languages: string[]
24
+ export const defaultLocale: string
25
+ export const prefixDefaultLocale: boolean
26
+ export const translations: Record<string, Record<string, any>> | undefined
27
+ export default {
28
+ locales: [] as string[],
29
+ defaultLocale: ""
30
+ }
31
+ }
32
+
33
+ declare module "virtual:rimelight-auth" {
34
+ export const auth: import("@rimelight/auth").AuthAdapter
35
+ export const authAdapter: import("@rimelight/auth").AuthAdapter
36
+ export default auth
37
+ }
38
+
39
+ declare module "virtual:rimelight-auth-client" {
40
+ export const authClient: import("@rimelight/auth/client").AuthClient
41
+ export const createAuthClient: typeof import("@rimelight/auth/client").createAuthClient
42
+ export default authClient
43
+ }
44
+
45
+ declare module "#auth/auth" {
46
+ export const auth: import("@rimelight/auth").AuthAdapter
47
+ export const authAdapter: import("@rimelight/auth").AuthAdapter
48
+ export default auth
49
+ }
50
+
51
+ declare module "#auth/auth-client" {
52
+ export const authClient: import("@rimelight/auth/client").AuthClient
53
+ export const createAuthClient: typeof import("@rimelight/auth/client").createAuthClient
54
+ export default authClient
55
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rimelight/config",
3
- "version": "0.0.12",
3
+ "version": "0.0.14",
4
4
  "private": false,
5
5
  "description": "Rimelight Entertainment's shared configuration package",
6
6
  "homepage": "https://rimelight.com/docs",
@@ -55,11 +55,12 @@
55
55
  "peerDependencies": {
56
56
  "@astrojs/cloudflare": ">=14.0.0",
57
57
  "@astrojs/solid-js": ">=7.0.0",
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",
58
+ "@rimelight/auth": "0.0.9",
59
+ "@rimelight/cms": "0.0.15",
60
+ "@rimelight/i18n": "0.0.16",
61
+ "@rimelight/security": "0.0.17",
62
+ "@rimelight/seo": "0.0.12",
63
+ "@rimelight/ui": "0.0.56",
63
64
  "astro": ">=7.0.0",
64
65
  "drizzle-kit": ">=0.30.0"
65
66
  },
@@ -70,6 +71,9 @@
70
71
  "@astrojs/solid-js": {
71
72
  "optional": true
72
73
  },
74
+ "@rimelight/auth": {
75
+ "optional": true
76
+ },
73
77
  "@rimelight/cms": {
74
78
  "optional": true
75
79
  },
@@ -93,6 +97,6 @@
93
97
  }
94
98
  },
95
99
  "engines": {
96
- "node": ">=26.9.0"
100
+ "node": ">=26.8.2"
97
101
  }
98
102
  }