webapps/packages/layers/content/utils/content-files.ts
Dominik Milacher 73083ded58
Some checks failed
Build and deploy updated apps / Build & deploy (push) Failing after 1m7s
Overhaul content management
2025-10-22 19:31:38 +02:00

82 lines
2.6 KiB
TypeScript

import {getLayerDirectories} from '@nuxt/kit'
import {existsSync, lstatSync} from 'fs'
import {readFile} from 'fs/promises'
import {join} from 'path'
import {parse} from 'yaml'
import {fromInputJson, merge, type CanonicalValue} from './content-canonical'
import {type Plugin, build} from 'esbuild'
export function getLayerFiles(slug: string): string[] {
return getLayerDirectories().flatMap(d => ['mts', 'yaml'].map(e => join(d.root, `${slug}.${e}`)))
}
export async function getLayerContent(files: string[]): Promise<CanonicalValue | undefined> {
const ts = await mergeTsFiles(files.filter(f => f.endsWith('.mts') && existsSync(f) && lstatSync(f).isFile()))
const yaml = await mergeYamlFiles(files.filter(f => f.endsWith('.yaml') && existsSync(f) && lstatSync(f).isFile()))
const merged = merge([ts, yaml].filter(c => c !== undefined))
return merged?.dropTags(['de', 'en', 'summer', 'winter']) // TODO
}
async function mergeTsFiles(files: string[]): Promise<CanonicalValue | undefined> {
if (!files.length) return undefined
try {
const loader: Plugin = {
name: 'file-loader',
setup(build) {
build.onLoad({filter: /\.mts$/}, async (args) => {
let code = await readFile(args.path, 'utf-8')
const index = files.indexOf(args.path)
if (index < files.length - 1) {
code = `
export * from '${files[index + 1]}';
import * as parent from '${files[index + 1]}';
${code}
`
}
return {contents: code, loader: 'ts'}
})
}
}
const bundle = await build({
entryPoints: [files[0]!],
bundle: true,
format: 'esm',
platform: 'node',
target: 'node22',
write: false,
sourcemap: 'inline',
plugins: [loader]
})
const url = 'data:text/javascript;base64,' + Buffer.from(bundle.outputFiles[0]!.text).toString('base64')
const module = await import(url)
return fromInputJson([], module.default)
} catch (e) {
const message = e instanceof Error ? e.message : String(e)
console.error(`Unable to load merged ts: ${message}`)
return undefined
}
}
async function mergeYamlFiles(files: string[]): Promise<CanonicalValue | undefined> {
const objects = await Promise.all(files.map(async f => {
try {
return fromInputJson([], parse(await readFile(f, 'utf-8')))
} catch (e) {
const message = e instanceof Error ? e.message : String(e)
console.error(`Unable to load content file ${f}: ${message}`)
return undefined
}
}))
return merge(objects.filter(o => !!o))
}