import { K8sResource, K8tsManifest, ManifestSourceEmbedder, ResourceVertex } from "@k8ts/instruments" import type EventEmitter from "eventemitter3" import { cloneDeep, cloneDeepWith, isEmpty, unset } from "lodash" export interface ManifesterOptions { cwd?: string emitter?: EventEmitter } export class Engine_Manifester { constructor(private readonly _options: ManifesterOptions) {} private _cleanSpecificEmptyObjects(manifest: K8tsManifest) { const clone = cloneDeepWith(manifest, (value, key) => { if (key !== "metadata") { return } for (const k in value) { if (["labels", "annotations"].includes(k)) { if (isEmpty(value[k])) { unset(value, k) } } } }) return clone } private _cleanNullishValues(manifest: K8tsManifest) { const _cleanKeys = (obj: any) => { if (typeof obj !== "object") { return obj } for (const [k, v] of Object.entries(obj)) { if (v == null) { delete obj[k] } } return undefined } const clone = cloneDeep(manifest) return cloneDeepWith(clone, _cleanKeys) } private async _generate(resource: K8sResource): Promise { const manifest = await resource["__manifest__"]() const noNullish = this._cleanNullishValues(manifest) const noEmpty = this._cleanSpecificEmptyObjects(noNullish) return noEmpty } async generate(res: ResourceVertex): Promise { this._options.emitter?.emit("manifest", { resource: res }) const manifest = await this._generate(res.entity as K8sResource) ManifestSourceEmbedder.add(manifest, res.entity) return { node: res, manifest: manifest } } } export interface NodeManifest { node: ResourceVertex manifest: K8tsManifest } export interface ManifesterManifestEvent { resource: ResourceVertex } export interface ManifesterEventsTable { manifest: ManifesterManifestEvent }