import fs from "fs" ; import path from "path" ; import createOrUpdateResources from "../util/createOrUpdateResources" ; import * as esbuild from "esbuild" ; import { IndexResource , ProviderResource , Resource , ResourceType , UploadResourcesOptions } from "../types" ; import { detailedError , status } from "../util/logger" ; import getProviders from "../util/getProviders" ; import updateIndexes from "../util/updateIndexes" ; import CLISpinner from "cli-spinner" ; const Spinner = CLISpinner . Spinner ; const cwd = process . cwd ( ) ; const allowedExts = [ ".js" , ".ts" ] ; async function uploadResources ( dir , type , options ? ) { const failedUploadError = `Failed to upload ${ type }\n` ; const resourceDir = path . join ( dir , "output" ) ; const files = await fs . promises . readdir ( dir ) . catch ( err => { return null ; } ) ; if ( ! files || ( files && files . length === 0 ) ) { return ; } const entries = files . filter ( file => { const ext = getExt ( file ) ; if ( allowedExts . includes ( ext ) ) { return true ; } return false ; } ) . map ( file => path . join ( dir , file ) ) ; const containsTs = files . some ( file => getExt ( file ) === ".ts" ) ; if ( containsTs ) { const { typeCheck } = require ( "../util/typescript" ) ; const ok = await typeCheck ( entries , dir ) ; if ( ! ok ) { status ( failedUploadError , "error" ) ; return ; } } try { await esbuild . build ( { entryPoints : entries , outdir : resourceDir , bundle : true , platform : "node" , outExtension : { ".js" : ".cjs" } , target : [ "esnext" ] } ) ; } catch ( err ) { status ( failedUploadError , "error" ) ; return ; } const resourceFiles = ( await Promise . all ( files . map ( async ( file ) => { try { if ( ! allowedExts . includes ( getExt ( file ) ) ) return null ; const resourcePath = path . join ( cwd , resourceDir , removeExt ( file ) + ".cjs" ) ; const resource = await import ( resourcePath ) ; return resource . default || resource ; } catch ( err ) { status ( `Error reading file ${ dir }/${ file }` , "error" ) ; console . error ( err ) ; return null ; } } ) ) ) . filter ( value => value !== null ) ; await fs . promises . rmdir ( resourceDir , { recursive : true } ) ; try { const result = await createOrUpdateResources ( resourceFiles , type , options ) ; if ( type === "functions" && ! options ?. fnsWithRoles ) return ; status ( `successfully uploaded ${ type }` , "success" ) ; if ( type === "providers" ) { const providers = await getProviders ( result as ProviderResource [ ] ) ; providers . forEach ( provider => { status ( `audience for ${ provider . name }: ${ provider . audience }` , "info" ) ; } ) ; } } catch ( err ) { if ( type === "functions" && ! options ?. fnsWithRoles ) return ; if ( type === "indexes" && err . requestResult . responseRaw . includes ( "Index sources, terms, values, and partition count may not be updated." ) ) { status ( "Index sources, terms, values, and partition count cannot be updated normally. We must first delete the index and create it again. This will happen automatically, hold on..." , "info" ) ; try { const indexes = resourceFiles . filter ( val => ! ! val . source ) ; const spinner = new Spinner ( "Updating mutated indexes... %s" ) ; spinner . start ( ) ; await updateIndexes ( indexes as IndexResource [ ] ) ; spinner . stop ( ) ; console . log ( ) ; status ( "Successfully updated mutated indexes" , "success" ) ; return ; } catch ( err ) { status ( "Failed to update mutated indexes" , "error" ) ; console . error ( err ) ; } } detailedError ( err , type ) ; } } function removeExt ( str ) { return str . split ( "." ) . slice ( 0 , - 1 ) . join ( "" ) ; } function getExt ( str ) { return path . extname ( str ) ; } export default uploadResources ;