Added filebase64sha256 support for NodeJS

This commit is contained in:
Vova Ivanov 2021-11-23 16:49:19 -08:00
parent cae67f1f83
commit fba8aa6575
3 changed files with 48 additions and 14 deletions

View file

@ -53,6 +53,9 @@ func GenerateProgram(program *pcl.Program) (map[string][]byte, hcl.Diagnostics,
}
g.Formatter = format.NewFormatter(g)
// Creating a list to store and later print helper methods if they turn out to be needed
preambleHelperMethods := codegen.NewStringSet()
for _, p := range program.Packages() {
if err := p.ImportLanguages(map[string]schema.Language{"nodejs": Importer}); err != nil {
return nil, nil, err
@ -60,7 +63,7 @@ func GenerateProgram(program *pcl.Program) (map[string][]byte, hcl.Diagnostics,
}
var index bytes.Buffer
g.genPreamble(&index, program)
g.genPreamble(&index, program, preambleHelperMethods)
for _, n := range nodes {
if r, ok := n.(*pcl.Resource); ok && requiresAsyncMain(r) {
g.asyncMain = true
@ -150,7 +153,7 @@ func (g *generator) genComment(w io.Writer, comment syntax.Comment) {
}
}
func (g *generator) genPreamble(w io.Writer, program *pcl.Program) {
func (g *generator) genPreamble(w io.Writer, program *pcl.Program, preambleHelperMethods codegen.StringSet) {
// Print the @pulumi/pulumi import at the top.
g.Fprintln(w, `import * as pulumi from "@pulumi/pulumi";`)
@ -164,8 +167,13 @@ func (g *generator) genPreamble(w io.Writer, program *pcl.Program) {
}
diags := n.VisitExpressions(nil, func(n model.Expression) (model.Expression, hcl.Diagnostics) {
if call, ok := n.(*model.FunctionCallExpression); ok {
if i := g.getFunctionImports(call); i != "" {
importSet.Add(i)
if i := g.getFunctionImports(call); i[0] != "" {
for _, importPackage := range i {
importSet.Add(importPackage)
}
}
if helperMethodBody, ok := getHelperMethodIfNeeded(call.Name); ok {
preambleHelperMethods.Add(helperMethodBody)
}
}
return n, nil
@ -192,6 +200,11 @@ func (g *generator) genPreamble(w io.Writer, program *pcl.Program) {
g.Fprintln(w, i)
}
g.Fprint(w, "\n")
// If we collected any helper methods that should be added, write them just before the main func
for _, preambleHelperMethodBody := range preambleHelperMethods.SortedValues() {
g.Fprintf(w, "%s\n\n", preambleHelperMethodBody)
}
}
func (g *generator) genNode(w io.Writer, n pcl.Node) {

View file

@ -266,24 +266,25 @@ func (g *generator) genRange(w io.Writer, call *model.FunctionCallExpression, en
genSuffix()
}
var functionImports = map[string]string{
intrinsicInterpolate: "@pulumi/pulumi",
"fileArchive": "@pulumi/pulumi",
"fileAsset": "@pulumi/pulumi",
"filebase64": "fs",
"readFile": "fs",
"readDir": "fs",
"sha1": "crypto",
var functionImports = map[string][]string{
intrinsicInterpolate: []string{"@pulumi/pulumi"},
"fileArchive": []string{"@pulumi/pulumi"},
"fileAsset": []string{"@pulumi/pulumi"},
"filebase64": []string{"fs"},
"filebase64sha256": []string{"fs", "crypto"},
"readFile": []string{"fs"},
"readDir": []string{"fs"},
"sha1": []string{"crypto"},
}
func (g *generator) getFunctionImports(x *model.FunctionCallExpression) string {
func (g *generator) getFunctionImports(x *model.FunctionCallExpression) []string {
if x.Name != pcl.Invoke {
return functionImports[x.Name]
}
pkg, _, _, diags := functionName(x.Args[0])
contract.Assert(len(diags) == 0)
return "@pulumi/" + pkg
return []string{"@pulumi/" + pkg}
}
func (g *generator) GenFunctionCallExpression(w io.Writer, expr *model.FunctionCallExpression) {
@ -322,6 +323,9 @@ func (g *generator) GenFunctionCallExpression(w io.Writer, expr *model.FunctionC
g.Fgenf(w, "new pulumi.asset.FileAsset(%.v)", expr.Args[0])
case "filebase64":
g.Fgenf(w, "Buffer.from(fs.readFileSync(%v), 'binary').toString('base64')", expr.Args[0])
case "filebase64sha256":
// Assuming the existence of the following helper method
g.Fgenf(w, "computeFilebase64sha256(%v)", expr.Args[0])
case pcl.Invoke:
pkg, module, fn, diags := functionName(expr.Args[0])
contract.Assert(len(diags) == 0)

View file

@ -0,0 +1,17 @@
package nodejs
// Provides code for a method which will be placed in the program preamble if deemed
// necessary. Because many tasks in Go such as reading a file require extensive error
// handling, it is much prettier to encapsulate that error handling boilerplate as its
// own function in the preamble.
func getHelperMethodIfNeeded(functionName string) (string, bool) {
switch functionName {
case "filebase64sha256":
return `func computeFilebase64sha256(path string) string {
const fileData = Buffer.from(fs.readFileSync(path), 'binary')
return crypto.createHash('sha256').update(fileData).digest('hex')
}`, true
default:
return "", false
}
}