func buildFn()

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
}