import { loadAll } from "js-yaml" ; import fs from "fs-extra" ; import fetch , { RequestInfo , RequestInit } from "node-fetch" ; import { getResourceModule , ResourceKind } from "./module" ; import Debug from "./debug" ; import { importPath } from "@kosko/require" ; const debug = Debug . extend ( "load" ) ; export interface Manifest extends ResourceKind { [ key ] : any ; } type ManifestConstructor = new ( data ) => Manifest ; export interface LoadOptions { transform ? ( manifest ) : Manifest | null | undefined ; } function isRecord ( value ) { return typeof value === "object" && ! Array . isArray ( value ) ; } function isManifest ( value ) { return ( typeof value . apiVersion === "string" && ! ! value . apiVersion && typeof value . kind === "string" && ! ! value . kind ) ; } async function getConstructor ( res ) { const mod = await getResourceModule ( res ) ; if ( ! mod ) { debug ( "No resource modules for" , res ) ; return ; } try { const result = await importPath ( mod . path ) ; return result [ mod . export ] ; } catch { debug ( "Failed to import the resource module" , mod ) ; return ; } } /**
 * Load a Kubernetes YAML file from a string.
 */ export async function loadString ( content , { transform = ( x ) => x } = { } ) { const input = loadAll ( content ) . filter ( ( x ) => x != null ) ; const manifests = [ ] ; for ( const entry of input ) { if ( ! isRecord ( entry ) ) { throw new Error ( `The value must be an object: ${ JSON . stringify ( entry ) }` ) ; } if ( ! isManifest ( entry ) ) { throw new Error ( `apiVersion and kind are required: ${ JSON . stringify ( entry ) }` ) ; } const Constructor = await getConstructor ( entry ) ; const manifest = transform ( Constructor ? new Constructor ( entry ) : entry ) ; if ( manifest ) { manifests . push ( manifest ) ; } } return manifests ; } param path param options export function loadFile ( path , options ? ) { return async ( ) : Promise < readonly Manifest [ ] > => { const content = await fs . readFile ( path , "utf-8" ) ; debug ( "File loaded from: %s" , path ) ; return loadString ( content , options ) ; } ; } param url param options export function loadUrl ( url , options = { } ) { const { transform , ... init } = options ; return async ( ) => { const res = await fetch ( url , init ) ; debug ( `Fetch "%s": status=%d` , url , res . status ) ; if ( ! res . ok ) { throw new Error ( `Failed to fetch YAML file from: ${ url }` ) ; } return loadString ( await res . text ( ) , { transform } ) ; } ; }