// Menu: Cloudinary upload // Description: Upload an image to cloudinary // Shortcut: command option control c // Author: Kent C. Dodds // Twitter: @kentcdodds import path from 'path' const cloudinaryCloudName = await env('CLOUDINARY_CLOUD_NAME') const cloudinaryKey = await env('CLOUDINARY_API_KEY') const cloudinarySecret = await env('CLOUDINARY_API_SECRET') const cloudiaryConsoleId = await env('CLOUDINARY_CONSOLE_ID') await npm('cloudinary') import cloudinary from 'cloudinary' const cacheDb = await db('cloudinary-cache', {lastChoice: '', folders: {}}) await cacheDb.read() cloudinary.config({ cloud_name: cloudinaryCloudName, api_key: cloudinaryKey, api_secret: cloudinarySecret, secure: true, }) const actions = { CREATE_NEW: 'creating new folder', REFRESH_CACHE: 'refreshing cache', OPEN_DIR: 'opening directory', } let chosenDirectory = await cacheDb.data.lastChoice let lastSelection while (true) { // if the last action was to create a new directory then we know the chosen // directory is new and has no folders otherwise we have to wait a few seconds // for the API to be prepared for us to make a request for the contents. const directories = lastSelection === actions.CREATE_NEW ? [] : await getFolders(chosenDirectory) lastSelection = await arg( `Select directory in ${chosenDirectory || '/'}`, [ {name: '.', value: '.', description: '✅ Choose this directory'}, !chosenDirectory ? null : {name: '..', value: '..', description: '⤴️ Go up a directory'}, ...directories.map(folder => ({ name: folder.name, value: folder.path, description: '⤵️ Select directory', })), { name: 'Open directory', value: actions.OPEN_DIR, description: '🌐 Open this directory in the browser', }, { name: 'Refresh cache', value: actions.REFRESH_CACHE, description: '🔄 Refresh the cache for this directory', }, { name: 'Create new directory', value: actions.CREATE_NEW, description: '➕ Create a new directory here', }, ].filter(Boolean), ) if (lastSelection === '..') { chosenDirectory = chosenDirectory.split('/').slice(0, -1).join('/') } else if (lastSelection === '.') { break } else if (lastSelection === actions.CREATE_NEW) { const newFolderName = await arg(`What's the new folder name?`) const newDirectory = `${chosenDirectory}/${newFolderName}` await cloudinary.v2.api.create_folder(newDirectory) delete cacheDb.data.folders[chosenDirectory] chosenDirectory = newDirectory } else if (lastSelection === actions.REFRESH_CACHE) { delete cacheDb.data.folders[chosenDirectory] } else if (lastSelection === actions.OPEN_DIR) { await openFolder(chosenDirectory) } else { chosenDirectory = lastSelection } } cacheDb.data.lastChoice = chosenDirectory await cacheDb.write() const images = await drop('Drop the image(s) you want to upload') let renameSome = true if (images.length > 1) { const renameChoice = await arg('Do you want to rename any of these?', [ 'yes', 'no', ]) renameSome = renameChoice === 'yes' } for (const image of images) { const defaultName = path.parse(image.path).name const name = renameSome ? (await arg({ placeholder: `Name of this image?`, hint: `Default is: "${defaultName}"`, })) || defaultName : defaultName setPlaceholder(`Uploading ${name}`) const uploadedImage = await cloudinary.v2.uploader.upload(image.path, { public_id: name, overwrite: false, folder: chosenDirectory, }) // If you have multiple files then this isn't really useful unless you have // clipbloard history (which I recommend you get!) await copy(uploadedImage.secure_url) } await openFolder(chosenDirectory) function openFolder(folder) { const encodedFolder = encodeURIComponent(folder) console.log('opening') return exec( `open "https://cloudinary.com/console/${cloudiaryConsoleId}/media_library/folders/${encodedFolder}"`, ) } async function getFolders(directory) { const cachedDirectories = cacheDb.data.folders[directory] if (cachedDirectories) { return cachedDirectories } try { const {folders: directories} = !directory ? await cloudinary.v2.api.root_folders() : await cloudinary.v2.api.sub_folders(directory) cacheDb.data.folders[directory] = directories await cacheDb.write() return directories } catch (error) { console.error('error with the directory') return [] } }