-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feature/eng 866 integrate sites apis with cli sites commands (#94)
- Loading branch information
Showing
11 changed files
with
374 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import Chalk from "chalk" | ||
import { parseBlsConfig } from "../../lib/blsConfig" | ||
import { consoleClient } from "../../lib/http" | ||
import { logger } from "../../lib/logger" | ||
import { normalizeFunctionName } from "../../lib/strings" | ||
|
||
interface DeleteCommandOptions { | ||
target: string | ||
} | ||
|
||
/** | ||
* Entry function for bls site delete | ||
* | ||
* @param options | ||
*/ | ||
export const run = async (options: DeleteCommandOptions) => { | ||
try { | ||
if (options.target) { | ||
await deleteSite({ name: options.target }) | ||
} else { | ||
const { name: configName } = parseBlsConfig() | ||
await deleteSite({ name: configName }) | ||
} | ||
} catch (error: any) { | ||
logger.error('Failed to delete site.', error.message) | ||
} | ||
} | ||
|
||
/** | ||
* | ||
* @param data | ||
* @returns | ||
*/ | ||
const deleteSite = async (data: any) => { | ||
const { name: functionName } = data | ||
|
||
let matchingFunction = null | ||
let internalFunctionId = null | ||
|
||
// Find all matching functions, warn users if they are updating a function that is not deployed | ||
try { | ||
console.log(Chalk.yellow(`Deleting ${functionName} ...`)) | ||
console.log('') | ||
|
||
const { data } = await consoleClient.get(`/api/sites?limit=999`, {}) | ||
const functions = data.docs ? data.docs : [] | ||
|
||
// Sort all matching functions by name and select the last matching function | ||
// TODO: Ensure all functions have unique names under a user's scope | ||
const matchingFunctions = functions.filter((f: any) => | ||
normalizeFunctionName(f.functionName) === normalizeFunctionName(functionName)) | ||
|
||
if (matchingFunctions && matchingFunctions.length > 0) { | ||
matchingFunction = matchingFunctions[matchingFunctions.length - 1] | ||
internalFunctionId = matchingFunction._id | ||
} | ||
|
||
// If a function does not exist, request the user to deploy that function first | ||
if (!matchingFunction) { | ||
throw new Error('Site not found.') | ||
} | ||
} catch (error: any) { | ||
logger.error('Failed to retrive deployed sites.', error.message) | ||
return | ||
} | ||
|
||
// Delete the site | ||
try { | ||
if (!internalFunctionId || !matchingFunction) | ||
throw new Error('Unable to retrive site ID.') | ||
|
||
const { data } = await consoleClient.delete(`/api/sites/${internalFunctionId}`) | ||
|
||
if (!data) throw new Error("") | ||
|
||
console.log( | ||
Chalk.green( | ||
`Successfully deleted site ${functionName}!` | ||
) | ||
) | ||
} catch (error: any) { | ||
logger.error('Failed to delete site.', error.message) | ||
return | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
import Chalk from "chalk" | ||
import { run as runPublish } from "./publish" | ||
import { basename, resolve } from "path" | ||
import { consoleClient } from "../../lib/http" | ||
import promptFnDeploy from "../../prompts/function/deploy" | ||
import { parseBlsConfig } from "../../lib/blsConfig" | ||
import { logger } from "../../lib/logger" | ||
import { normalizeFunctionName, slugify } from "../../lib/strings" | ||
|
||
interface DeployCommandOptions { | ||
name?: string | ||
path?: string | ||
yes?: boolean | ||
} | ||
|
||
/** | ||
* Entry function for bls function deploy | ||
* | ||
* @param options | ||
*/ | ||
export const run = (options: DeployCommandOptions) => { | ||
try { | ||
const { | ||
name: configName | ||
} = parseBlsConfig() | ||
|
||
const { | ||
name = configName || basename(resolve(process.cwd())), | ||
path = process.cwd() | ||
} = options | ||
|
||
runPublish({ | ||
debug: false, | ||
name, | ||
path, | ||
publishCallback: (data: any) => deployFunction(slugify(name), data, options), | ||
rebuild: true, | ||
}) | ||
} catch (error: any) { | ||
logger.error('Failed to deploy site.', error.message) | ||
} | ||
} | ||
|
||
/** | ||
* Helper to deploy a bls site via CLI | ||
* | ||
* 1. Publish package and retrive ipfs site id | ||
* 2. Get list of user sites | ||
* 3. Decide whether to update or create a new site (based on site name), bail if deploying same data | ||
* 4. Call new or update API with site config parameters | ||
* 5. Run deploy | ||
* | ||
* @param data | ||
* @returns | ||
*/ | ||
const deployFunction = async (functionName: string, functionData: any, options: DeployCommandOptions) => { | ||
const { cid: functionId } = functionData | ||
let matchingFunction = null | ||
let internalFunctionId = null | ||
|
||
// Find all matching functions, warn users if they are overwriting a deployed function | ||
try { | ||
const { data } = await consoleClient.get(`/api/sites?limit=999`, {}) | ||
const functions = data.docs ? data.docs : [] | ||
|
||
// Sort all matching functions by name and select the last matching function | ||
// TODO: Ensure all functions have unique names under a user's scope | ||
const matchingFunctions = functions.filter((f: any) => | ||
normalizeFunctionName(f.functionName) === normalizeFunctionName(functionName)) | ||
|
||
if (matchingFunctions && matchingFunctions.length > 0) { | ||
matchingFunction = matchingFunctions[matchingFunctions.length - 1] | ||
internalFunctionId = matchingFunction._id | ||
} | ||
|
||
// If a function exists and has been deployed, request a user's confirmation | ||
if (matchingFunction && matchingFunction.status === 'deployed' && !options.yes) { | ||
const { confirm } = await promptFnDeploy({ name: matchingFunction.functionName }) | ||
|
||
if (!confirm) { | ||
throw new Error("Cancelled by user, aborting deployment.") | ||
} | ||
} | ||
} catch (error: any) { | ||
logger.error('Failed to retrive deployed sites.', error.message) | ||
return | ||
} | ||
|
||
// Create or update site | ||
try { | ||
let response | ||
|
||
if (!internalFunctionId) { | ||
response = await consoleClient.post(`/api/sites`, { functionId, functionName }) | ||
} else { | ||
response = await consoleClient.patch( | ||
`/api/sites/${internalFunctionId}`, | ||
{ functionId, functionName, status: 'deploying' } | ||
) | ||
} | ||
|
||
if (!internalFunctionId && response.data && response.data._id) internalFunctionId = response.data._id | ||
} catch (error: any) { | ||
logger.error('Failed to update site metadata.', error.message) | ||
return | ||
} | ||
|
||
// Deploy Site | ||
try { | ||
if (!internalFunctionId) throw new Error('Unable to retrive site ID') | ||
console.log(Chalk.yellow(`Deploying ${functionName} ...`)) | ||
|
||
const { data } = await consoleClient.put(`/api/sites/${internalFunctionId}/deploy`, { | ||
functionId: functionId | ||
}) | ||
|
||
if (!!data.err) { | ||
console.log(Chalk.red(`Deployment unsuccessful, ${data.message}`)) | ||
} else { | ||
console.log( | ||
Chalk.green( | ||
`Successfully deployed ${functionName} with id ${functionId}` | ||
) | ||
) | ||
} | ||
} catch (error: any) { | ||
logger.error('Failed to deploy site.', error.message) | ||
return | ||
} | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import Chalk from "chalk" | ||
import { consoleClient } from "../../lib/http" | ||
import { logger } from "../../lib/logger" | ||
|
||
export const run = async () => { | ||
try { | ||
const { data } = await consoleClient.get(`/api/sites?limit=999`, {}) | ||
const sites = data.docs ? data.docs : [] | ||
|
||
logger.log('List of Sites:') | ||
logger.log('-----------------------------------') | ||
|
||
if (sites && sites.length > 0) { | ||
sites.forEach && sites.forEach((f: any) => { | ||
logger.log('') | ||
logger.log(`${Chalk.blue('Name:')} ${f.functionName}`) | ||
logger.log(`${Chalk.blue('CID:')} ${f.functionId}`) | ||
logger.log(`${Chalk.blue('Status:')} ${f.status === 'stopped' ? Chalk.red(f.status) : f.status === 'deployed' ? Chalk.green(f.status) : f.status}`) | ||
}) | ||
|
||
logger.log('') | ||
logger.log(`Total Sites: ${sites.length}`) | ||
} else { | ||
logger.log('') | ||
logger.log('You have no sites.') | ||
} | ||
} catch (error: any) { | ||
logger.error('Failed to retrieve site list.', error.message) | ||
return | ||
} | ||
} |
Oops, something went wrong.