mirror of https://github.com/pulumi/pulumi.git
128 lines
4.4 KiB
Go
128 lines
4.4 KiB
Go
// Copyright 2016-2022, Pulumi Corporation.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// Large providers like azure-native generate code that has a high
|
|
// startup overhead in Node JS due to loading thousands of modules at
|
|
// once. The code in this file is dedicated to support on-demand
|
|
// (lazy) loading of modules at Node level to speed up program
|
|
// startup.
|
|
|
|
package nodejs
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract"
|
|
)
|
|
|
|
type lazyLoadGen struct{}
|
|
|
|
func newLazyLoadGen() *lazyLoadGen {
|
|
return &lazyLoadGen{}
|
|
}
|
|
|
|
// Generates TypeScript code to re-export a generated module. For
|
|
// resources and functions this is optimized to use lazy loading.
|
|
// Falls back to eager re-export for everything else.
|
|
func (ll *lazyLoadGen) genReexport(w io.Writer, exp fileInfo, importPath string) {
|
|
if exp.fileType == functionFileType {
|
|
// optimize lazy-loading function modules
|
|
ll.genFunctionReexport(w, exp.functionFileInfo, importPath)
|
|
} else if exp.fileType == resourceFileType {
|
|
// optimize lazy-loading resource modules
|
|
ll.genResourceReexport(w, exp.resourceFileInfo, importPath)
|
|
} else {
|
|
// non-optimized but foolproof eager reexport
|
|
fmt.Fprintf(w, "export * from %q;\n", importPath)
|
|
}
|
|
}
|
|
|
|
// Used as a follow up to multiple genReexport calls to generate a
|
|
// lazy-load polyfill to all the properties that need that.
|
|
func (*lazyLoadGen) genLazyLoads(w io.Writer, importPath string, properties ...string) {
|
|
sort.Strings(properties)
|
|
j, err := json.Marshal(properties)
|
|
contract.AssertNoErrorf(err, "error serializing properties")
|
|
fmt.Fprintf(w, "utilities.lazyLoad(exports, %s, () => require(%q));\n",
|
|
string(j), importPath)
|
|
}
|
|
|
|
// Generates TypeScript code that lazily imports and re-exports a
|
|
// module defining a resource, while also importing the resoure class
|
|
// in-scope. Needs to know which names the module defines
|
|
// (resourceFileInfo).
|
|
func (ll *lazyLoadGen) genResourceReexport(w io.Writer, i resourceFileInfo, importPath string) {
|
|
defer fmt.Fprintf(w, "\n")
|
|
|
|
quotedImport := fmt.Sprintf("%q", importPath)
|
|
|
|
// not sure how to lazy-load in presence of re-exported
|
|
// namespaces; bail and use an eager load in this case; also
|
|
// eager-import the class.
|
|
if i.methodsNamespaceName != "" {
|
|
fmt.Fprintf(w, "export * from %s;\n", quotedImport)
|
|
fmt.Fprintf(w, "import { %s } from %s;\n", i.resourceClassName, quotedImport)
|
|
return
|
|
}
|
|
|
|
// Re-export interfaces. This is type-only and does not
|
|
// generate a require() call.
|
|
fmt.Fprintf(w, "export { %s } from %s;\n",
|
|
strings.Join(i.interfaces(), ", "),
|
|
quotedImport)
|
|
|
|
// Re-export class type into the type group, see
|
|
// https://www.typescriptlang.org/docs/handbook/declaration-merging.html
|
|
fmt.Fprintf(w, "export type %[1]s = import(%[2]s).%[1]s;\n",
|
|
i.resourceClassName,
|
|
quotedImport)
|
|
|
|
// Mock re-export class value into the value group - for compilation.
|
|
fmt.Fprintf(w, "export const %[1]s: typeof import(%[2]s).%[1]s = null as any;\n",
|
|
i.resourceClassName,
|
|
quotedImport)
|
|
|
|
ll.genLazyLoads(w, importPath, i.resourceClassName)
|
|
}
|
|
|
|
// Generates TypeScript code that lazily imports and re-exports a
|
|
// module defining a function. Needs to which names the module defines
|
|
// (functionFileInfo).
|
|
func (ll *lazyLoadGen) genFunctionReexport(w io.Writer, i functionFileInfo, importPath string) {
|
|
defer fmt.Fprintf(w, "\n")
|
|
|
|
quotedImport := fmt.Sprintf("%q", importPath)
|
|
|
|
// Re-export interfaces. This is type-only and does not
|
|
// generate a require() call.
|
|
interfaces := i.interfaces()
|
|
if len(interfaces) > 0 {
|
|
fmt.Fprintf(w, "export { %s } from %s;\n",
|
|
strings.Join(interfaces, ", "),
|
|
quotedImport)
|
|
}
|
|
|
|
// Re-export function values into the value group, and install lazy loading.
|
|
funcs := i.functions()
|
|
for _, f := range funcs {
|
|
fmt.Fprintf(w, "export const %[1]s: typeof import(%[2]s).%[1]s = null as any;\n",
|
|
f, quotedImport)
|
|
}
|
|
ll.genLazyLoads(w, importPath, funcs...)
|
|
}
|