in cmd/nodejs/legacy_worker/main.go [54:139]
func buildFn(ctx *gcp.Context) error {
if _, ok := os.LookupEnv(env.FunctionSource); ok {
return gcp.UserErrorf("%s is not currently supported for Node.js buildpacks", env.FunctionSource)
}
// Function source code should be defined in the "main" field in package.json, index.js or function.js.
// https://cloud.google.com/functions/docs/writing#structuring_source_code
fnFile := "function.js"
indexJSExists, err := ctx.FileExists("index.js")
if err != nil {
return err
}
if indexJSExists {
fnFile = "index.js"
}
pjs, err := nodejs.ReadPackageJSONIfExists(ctx.ApplicationRoot())
if err != nil {
return err
}
if pjs != nil && pjs.Main != "" {
fnFile = pjs.Main
}
fnFileExists, err := ctx.FileExists(fnFile)
if err != nil {
return err
}
if !fnFileExists {
return gcp.UserErrorf("%s does not exist", fnFile)
}
// Syntax check the function code without executing to prevent run-time errors.
if _, err := ctx.Exec([]string{"node", "--check", fnFile}, gcp.WithUserAttribution); err != nil {
return err
}
l, err := ctx.Layer(layerName, gcp.BuildLayer, gcp.CacheLayer, gcp.LaunchLayer)
if err != nil {
return fmt.Errorf("creating %v layer: %w", layerName, err)
}
if err := installLegacyWorker(ctx, l); err != nil {
return fmt.Errorf("installing worker.js: %w", err)
}
nm := filepath.Join(ctx.ApplicationRoot(), "node_modules")
nmExists, err := ctx.FileExists(nm)
if err != nil {
return err
}
// The environment variables required by worker.js are different than those expected
// by the Functions Frameworks (hence we don't use ctx.SetFunctionsEnvVars()).
// Add user's node_modules to NODE_PATH so functions-framework can always find user's packages.
if nmExists {
l.LaunchEnvironment.Prepend("NODE_PATH", string(os.PathListSeparator), nm)
}
if target := os.Getenv(env.FunctionTarget); target != "" {
l.LaunchEnvironment.Default("X_GOOGLE_FUNCTION_NAME", target)
l.LaunchEnvironment.Default("X_GOOGLE_ENTRY_POINT", target)
} else {
// This should never happen because this env var is used by the detect phase.
return gcp.InternalErrorf("required env var %s not found", env.FunctionTarget)
}
signature := os.Getenv(env.FunctionSignatureType)
if signature == "http" || signature == "" {
// The name of the HTTP signature type is slightly different for worker.js
// than that of Functions Frameworks.
signature = "HTTP_TRIGGER"
}
l.LaunchEnvironment.Default("X_GOOGLE_FUNCTION_TRIGGER_TYPE", signature)
l.LaunchEnvironment.Default("X_GOOGLE_CODE_LOCATION", ctx.ApplicationRoot())
// TODO(b/184077805) this can be removed after the corresponding code from worker.js is removed
l.LaunchEnvironment.Default("X_GOOGLE_NEW_FUNCTION_SIGNATURE", "true")
// TODO(b/184077805) default to 8080 match FF runtimes?
l.LaunchEnvironment.Default("X_GOOGLE_WORKER_PORT", 8091)
l.LaunchEnvironment.Default("WORKER_PORT", 8091)
// TODO(b/181987135) historically worker.js was run with the --max-old-space-size to set the heap
// size. We should replicate this behaviour via the NODE_OPTIONS env var.
worker := filepath.Join(l.Path, "worker.js")
ctx.AddWebProcess([]string{"node", worker})
return nil
}