1+ import Chalk from "chalk"
2+ import { run as runPublish } from "./publish"
3+ import { basename , resolve } from "path"
4+ import { consoleClient } from "../../lib/http"
5+ import promptFnDeploy from "../../prompts/function/deploy"
6+ import { parseBlsConfig } from "../../lib/blsConfig"
7+ import { logger } from "../../lib/logger"
8+ import { normalizeFunctionName , slugify } from "../../lib/strings"
9+
10+ interface DeployCommandOptions {
11+ name ?: string
12+ path ?: string
13+ yes ?: boolean
14+ }
15+
16+ /**
17+ * Entry function for bls function deploy
18+ *
19+ * @param options
20+ */
21+ export const run = ( options : DeployCommandOptions ) => {
22+ try {
23+ const {
24+ name : configName
25+ } = parseBlsConfig ( )
26+
27+ const {
28+ name = configName || basename ( resolve ( process . cwd ( ) ) ) ,
29+ path = process . cwd ( )
30+ } = options
31+
32+ runPublish ( {
33+ debug : false ,
34+ name,
35+ path,
36+ publishCallback : ( data : any ) => deployFunction ( slugify ( name ) , data , options ) ,
37+ rebuild : true ,
38+ } )
39+ } catch ( error : any ) {
40+ logger . error ( 'Failed to deploy site.' , error . message )
41+ }
42+ }
43+
44+ /**
45+ * Helper to deploy a bls site via CLI
46+ *
47+ * 1. Publish package and retrive ipfs site id
48+ * 2. Get list of user sites
49+ * 3. Decide whether to update or create a new site (based on site name), bail if deploying same data
50+ * 4. Call new or update API with site config parameters
51+ * 5. Run deploy
52+ *
53+ * @param data
54+ * @returns
55+ */
56+ const deployFunction = async ( functionName : string , functionData : any , options : DeployCommandOptions ) => {
57+ const { cid : functionId } = functionData
58+ let matchingFunction = null
59+ let internalFunctionId = null
60+
61+ // Find all matching functions, warn users if they are overwriting a deployed function
62+ try {
63+ const { data } = await consoleClient . get ( `/api/sites?limit=999` , { } )
64+ const functions = data . docs ? data . docs : [ ]
65+
66+ // Sort all matching functions by name and select the last matching function
67+ // TODO: Ensure all functions have unique names under a user's scope
68+ const matchingFunctions = functions . filter ( ( f : any ) =>
69+ normalizeFunctionName ( f . functionName ) === normalizeFunctionName ( functionName ) )
70+
71+ if ( matchingFunctions && matchingFunctions . length > 0 ) {
72+ matchingFunction = matchingFunctions [ matchingFunctions . length - 1 ]
73+ internalFunctionId = matchingFunction . _id
74+ }
75+
76+ // If a function exists and has been deployed, request a user's confirmation
77+ if ( matchingFunction && matchingFunction . status === 'deployed' && ! options . yes ) {
78+ const { confirm } = await promptFnDeploy ( { name : matchingFunction . functionName } )
79+
80+ if ( ! confirm ) {
81+ throw new Error ( "Cancelled by user, aborting deployment." )
82+ }
83+ }
84+ } catch ( error : any ) {
85+ logger . error ( 'Failed to retrive deployed sites.' , error . message )
86+ return
87+ }
88+
89+ // Create or update site
90+ try {
91+ let response
92+
93+ if ( ! internalFunctionId ) {
94+ response = await consoleClient . post ( `/api/sites` , { functionId, functionName } )
95+ } else {
96+ response = await consoleClient . patch (
97+ `/api/sites/${ internalFunctionId } ` ,
98+ { functionId, functionName, status : 'deploying' }
99+ )
100+ }
101+
102+ if ( ! internalFunctionId && response . data && response . data . _id ) internalFunctionId = response . data . _id
103+ } catch ( error : any ) {
104+ logger . error ( 'Failed to update site metadata.' , error . message )
105+ return
106+ }
107+
108+ // Deploy Site
109+ try {
110+ if ( ! internalFunctionId ) throw new Error ( 'Unable to retrive site ID' )
111+ console . log ( Chalk . yellow ( `Deploying ${ functionName } ...` ) )
112+
113+ const { data } = await consoleClient . put ( `/api/sites/${ internalFunctionId } /deploy` , {
114+ functionId : functionId
115+ } )
116+
117+ if ( ! ! data . err ) {
118+ console . log ( Chalk . red ( `Deployment unsuccessful, ${ data . message } ` ) )
119+ } else {
120+ console . log (
121+ Chalk . green (
122+ `Successfully deployed ${ functionName } with id ${ functionId } `
123+ )
124+ )
125+ }
126+ } catch ( error : any ) {
127+ logger . error ( 'Failed to deploy site.' , error . message )
128+ return
129+ }
130+
131+ return
132+ }
0 commit comments