Skip to content
This repository has been archived by the owner on Jun 28, 2022. It is now read-only.

Commit

Permalink
NodeJS: generate readme. (#1240)
Browse files Browse the repository at this point in the history
  • Loading branch information
landrito authored May 22, 2017
1 parent 2da784d commit cadd53d
Show file tree
Hide file tree
Showing 8 changed files with 312 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ public String getOutputFileName() {
return getNotImplementedString("PackageMetadataNamer.getOutputFileName");
}

// TODO: (landrito) this is copied from SurfaceNamer. Figure out a way to consolidate the methods.
public String getReleaseAnnotation(ReleaseLevel releaseLevel) {
switch (releaseLevel) {
case UNSET_RELEASE_LEVEL:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,53 +16,178 @@

import com.google.api.codegen.InterfaceView;
import com.google.api.codegen.TargetLanguage;
import com.google.api.codegen.config.FlatteningConfig;
import com.google.api.codegen.config.GapicProductConfig;
import com.google.api.codegen.config.PackageMetadataConfig;
import com.google.api.codegen.nodejs.NodeJSUtils;
import com.google.api.codegen.transformer.DynamicLangApiMethodTransformer;
import com.google.api.codegen.transformer.FileHeaderTransformer;
import com.google.api.codegen.transformer.GapicInterfaceContext;
import com.google.api.codegen.transformer.GapicMethodContext;
import com.google.api.codegen.transformer.InitCodeTransformer;
import com.google.api.codegen.transformer.ModelToViewTransformer;
import com.google.api.codegen.transformer.ModelTypeTable;
import com.google.api.codegen.transformer.PackageMetadataTransformer;
import com.google.api.codegen.transformer.TestCaseTransformer;
import com.google.api.codegen.util.js.JSTypeTable;
import com.google.api.codegen.util.testing.StandardValueProducer;
import com.google.api.codegen.util.testing.ValueProducer;
import com.google.api.codegen.viewmodel.ApiMethodView;
import com.google.api.codegen.viewmodel.ImportSectionView;
import com.google.api.codegen.viewmodel.InitCodeView;
import com.google.api.codegen.viewmodel.OptionalArrayMethodView;
import com.google.api.codegen.viewmodel.ViewModel;
import com.google.api.tools.framework.model.Interface;
import com.google.api.tools.framework.model.Method;
import com.google.api.tools.framework.model.Model;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/** Responsible for producing package metadata related views for NodeJS */
public class NodeJSPackageMetadataTransformer implements ModelToViewTransformer {
private static final String PACKAGE_FILE = "nodejs/package.snip";
private static final String README_FILE = "nodejs/README.md.snip";
private static final String README_OUTPUT_FILE = "README.md";
private static final List<String> TOP_LEVEL_FILES = ImmutableList.of("nodejs/package.json.snip");

PackageMetadataConfig packageConfig;
PackageMetadataTransformer metadataTransformer = new PackageMetadataTransformer();
private static final String GITHUB_DOC_HOST =
"https://googlecloudplatform.github.io/google-cloud-node";
private static final String GITHUB_REPO_HOST =
"https://github.com/GoogleCloudPlatform/google-cloud-node";
private static final String AUTH_DOC_PATH = "/#/docs/google-cloud/master/guides/authentication";
private static final String LIB_DOC_PATH = "/#/docs/%s";
private static final String MAIN_README_PATH = "/blob/master/README.md";
private static final String VERSIONING_DOC_PATH = "#versioning";

private static String NODE_PREFIX = "nodejs/";

private final FileHeaderTransformer fileHeaderTransformer =
new FileHeaderTransformer(new NodeJSImportSectionTransformer());
private final PackageMetadataConfig packageConfig;
private final PackageMetadataTransformer metadataTransformer = new PackageMetadataTransformer();
private final ValueProducer valueProducer = new StandardValueProducer();
private final TestCaseTransformer testCaseTransformer = new TestCaseTransformer(valueProducer);

public NodeJSPackageMetadataTransformer(PackageMetadataConfig packageConfig) {
this.packageConfig = packageConfig;
}

@Override
public List<String> getTemplateFileNames() {
return Arrays.asList(PACKAGE_FILE);
return ImmutableList.<String>builder().addAll(TOP_LEVEL_FILES).add(README_FILE).build();
}

@Override
public List<ViewModel> transform(Model model, GapicProductConfig productConfig) {
Iterable<Interface> services = new InterfaceView().getElementIterable(model);
boolean hasMultipleServices = Iterables.size(services) > 1;
List<ViewModel> models = new ArrayList<ViewModel>();
NodeJSPackageMetadataNamer namer =
new NodeJSPackageMetadataNamer(
productConfig.getPackageName(), productConfig.getDomainLayerLocation());
models.add(generateMetadataView(model, namer, hasMultipleServices));
models.addAll(generateMetadataViews(model, namer));
models.add(generateReadmeView(model, productConfig, namer));
return models;
}

private ViewModel generateMetadataView(
Model model, NodeJSPackageMetadataNamer namer, boolean hasMultipleServices) {
private ViewModel generateReadmeView(
Model model, GapicProductConfig productConfig, NodeJSPackageMetadataNamer namer) {
List<ApiMethodView> exampleMethods = generateExampleMethods(model, productConfig);
Iterable<Interface> services = new InterfaceView().getElementIterable(model);
boolean hasMultipleServices = Iterables.size(services) > 1;
return metadataTransformer
.generateMetadataView(
packageConfig, model, PACKAGE_FILE, "package.json", TargetLanguage.NODEJS)
packageConfig, model, README_FILE, README_OUTPUT_FILE, TargetLanguage.NODEJS)
.identifier(namer.getMetadataIdentifier())
.fileHeader(
fileHeaderTransformer.generateFileHeader(
productConfig,
ImportSectionView.newBuilder().build(),
new NodeJSSurfaceNamer(
productConfig.getPackageName(), NodeJSUtils.isGcloud(productConfig))))
.developmentStatusTitle(
namer.getReleaseAnnotation(packageConfig.releaseLevel(TargetLanguage.NODEJS)))
.exampleMethods(exampleMethods)
.hasMultipleServices(hasMultipleServices)
.targetLanguage("NodeJS")
.mainReadmeLink(GITHUB_REPO_HOST + MAIN_README_PATH)
.libraryDocumentationLink(
GITHUB_DOC_HOST + String.format(LIB_DOC_PATH, packageConfig.shortName()))
.authDocumentationLink(GITHUB_DOC_HOST + AUTH_DOC_PATH)
.versioningDocumentationLink(GITHUB_REPO_HOST + VERSIONING_DOC_PATH)
.build();
}

// Generates methods used as examples for the README.md file.
// Note: This is based on sample gen method calls. In the future, the example
// methods may be configured separately.
private List<ApiMethodView> generateExampleMethods(
Model model, GapicProductConfig productConfig) {
ImmutableList.Builder<ApiMethodView> exampleMethods = ImmutableList.builder();
for (Interface apiInterface : new InterfaceView().getElementIterable(model)) {
GapicInterfaceContext context = createContext(apiInterface, productConfig);
if (context.getInterfaceConfig().getSmokeTestConfig() != null) {
Method method = context.getInterfaceConfig().getSmokeTestConfig().getMethod();
FlatteningConfig flatteningGroup =
testCaseTransformer.getSmokeTestFlatteningGroup(
context.getMethodConfig(method), context.getInterfaceConfig().getSmokeTestConfig());
GapicMethodContext flattenedMethodContext =
context.asFlattenedMethodContext(method, flatteningGroup);
exampleMethods.add(createExampleApiMethodView(flattenedMethodContext));
}
}
return exampleMethods.build();
}

private OptionalArrayMethodView createExampleApiMethodView(GapicMethodContext context) {
OptionalArrayMethodView initialApiMethodView =
new DynamicLangApiMethodTransformer(new NodeJSApiMethodParamTransformer())
.generateMethod(context);

OptionalArrayMethodView.Builder apiMethodView = initialApiMethodView.toBuilder();

InitCodeTransformer initCodeTransformer = new InitCodeTransformer();
InitCodeView initCodeView =
initCodeTransformer.generateInitCode(
context, testCaseTransformer.createSmokeTestInitContext(context));
apiMethodView.initCode(initCodeView);

return apiMethodView.build();
}

private List<ViewModel> generateMetadataViews(Model model, NodeJSPackageMetadataNamer namer) {
ImmutableList.Builder<ViewModel> views = ImmutableList.builder();
for (String template : TOP_LEVEL_FILES) {
views.add(generateMetadataView(model, template, namer));
}
return views.build();
}

private ViewModel generateMetadataView(
Model model, String template, NodeJSPackageMetadataNamer namer) {
String noLeadingNodeDir =
template.startsWith(NODE_PREFIX) ? template.substring(NODE_PREFIX.length()) : template;
int extensionIndex = noLeadingNodeDir.lastIndexOf(".");
String outputPath = noLeadingNodeDir.substring(0, extensionIndex);

Iterable<Interface> services = new InterfaceView().getElementIterable(model);
boolean hasMultipleServices = Iterables.size(services) > 1;

return metadataTransformer
.generateMetadataView(packageConfig, model, template, outputPath, TargetLanguage.NODEJS)
.identifier(namer.getMetadataIdentifier())
.hasMultipleServices(hasMultipleServices)
.build();
}

private GapicInterfaceContext createContext(
Interface apiInterface, GapicProductConfig productConfig) {
return GapicInterfaceContext.create(
apiInterface,
productConfig,
new ModelTypeTable(
new JSTypeTable(productConfig.getPackageName()),
new NodeJSModelTypeNameConverter(productConfig.getPackageName())),
new NodeJSSurfaceNamer(productConfig.getPackageName(), NodeJSUtils.isGcloud(productConfig)),
new NodeJSFeatureConfig());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@
import com.google.api.codegen.config.GrpcStreamingConfig.GrpcStreamingType;
import com.google.api.codegen.config.SingleResourceNameConfig;
import com.google.api.codegen.config.VisibilityConfig;
import com.google.api.codegen.metacode.InitFieldConfig;
import com.google.api.codegen.transformer.FeatureConfig;
import com.google.api.codegen.transformer.GapicInterfaceContext;
import com.google.api.codegen.transformer.ModelTypeFormatterImpl;
import com.google.api.codegen.transformer.ModelTypeTable;
import com.google.api.codegen.transformer.SurfaceNamer;
import com.google.api.codegen.transformer.Synchronicity;
import com.google.api.codegen.util.CommonRenderingUtil;
import com.google.api.codegen.util.Name;
import com.google.api.codegen.util.NamePath;
import com.google.api.codegen.util.js.JSCommentReformatter;
Expand All @@ -40,9 +42,11 @@
import com.google.api.tools.framework.model.Method;
import com.google.api.tools.framework.model.ProtoFile;
import com.google.api.tools.framework.model.TypeRef;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

Expand Down Expand Up @@ -465,4 +469,25 @@ public String getStreamTypeName(GrpcStreamingType type) {
"SurfaceNamer.getStreamTypeName(GrpcStreamingType." + type.toString() + ")");
}
}

@Override
public String injectRandomStringGeneratorCode(String randomString) {
String delimiter = ",";
String[] split =
CommonRenderingUtil.stripQuotes(randomString)
.replace(
InitFieldConfig.RANDOM_TOKEN, delimiter + InitFieldConfig.RANDOM_TOKEN + delimiter)
.split(delimiter);
ArrayList<String> stringParts = new ArrayList<>();
for (String token : split) {
if (token.length() > 0) {
if (token.equals(InitFieldConfig.RANDOM_TOKEN)) {
stringParts.add("Date.now().toString()");
} else {
stringParts.add("\"" + token + "\"");
}
}
}
return Joiner.on(" + ").join(stringParts);
}
}
23 changes: 23 additions & 0 deletions src/main/resources/com/google/api/codegen/nodejs/README.md.snip
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
@extends "nodejs/method_sample.snip"
@extends "readme.snip"

@snippet generate(metadata)
{@readme(metadata, exampleMethods(metadata.exampleMethods, metadata), installationLines(metadata))}
@end

@private exampleMethods(methods, metadata)
@join method : methods on BREAK
@#### {@method.apiClassName}
```js
var {@method.apiModuleName} = require('{@metadata.identifier}').{@metadata.majorVersion}({
// optional auth parameters.
});
{@decorateSampleCode(method, sampleCode(method))}
```
@end
@end

@private installationLines(metadata)
$ npm install {@metadata.identifier}
@end
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
============== file: README.md ==============
# NodeJS Client for Google Example Library API ([Alpha](https://github.com/GoogleCloudPlatform/google-cloud-node#versioning))

Idiomatic NodeJS client for [Google Example Library API][Product Documentation]
- [Client Library Documentation][]
- [Product Documentation][]

## Quick Start
In order to use this library, you first need to go through the following steps:

1. [Select or create a Cloud Platform project.](https://console.cloud.google.com/project)
2. [Enable the library api.](https://console.cloud.google.com/apis/api/library)
3. [Setup Authentication.](https://googlecloudplatform.github.io/google-cloud-node/#/docs/google-cloud/master/guides/authentication)

### Installation
```
$ npm install @google-cloud/library
```

### Preview
#### LibraryServiceClient
```js
var libraryV1 = require('@google-cloud/library').v1({
// optional auth parameters.
});

var client = libraryV1.libraryServiceClient();
var formattedName = client.bookPath("testShelf-" + Date.now().toString(), projectId);
var rating = libraryV1.Book.Rating.GOOD;
var book = {
rating : rating
};
var request = {
name: formattedName,
book: book
};
client.updateBook(request).then(function(responses) {
var response = responses[0];
// doThingsWith(response)
}).catch(function(err) {
console.error(err);
});
```

### Next Steps
- Read the [Client Library Documentation][] for Google Example Library API to see other available methods on the client.
- Read the [Google Example Library API Product documentation][Product Documentation] to learn more about the product and see How-to Guides.
- View this [repository's main README](https://github.com/GoogleCloudPlatform/google-cloud-node/blob/master/README.md) to see the full list of Cloud APIs that we cover.

[Client Library Documentation]: https://googlecloudplatform.github.io/google-cloud-node/#/docs/library
[Product Documentation]: https://cloud.google.com/library
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
============== file: README.md ==============
# NodeJS Client for Google Fake API ([Alpha](https://github.com/GoogleCloudPlatform/google-cloud-node#versioning))

Idiomatic NodeJS client for [Google Fake API][Product Documentation]
- [Client Library Documentation][]
- [Product Documentation][]

## Quick Start
In order to use this library, you first need to go through the following steps:

1. [Select or create a Cloud Platform project.](https://console.cloud.google.com/project)
2. [Enable the library api.](https://console.cloud.google.com/apis/api/library)
3. [Setup Authentication.](https://googlecloudplatform.github.io/google-cloud-node/#/docs/google-cloud/master/guides/authentication)

### Installation
```
$ npm install example
```

### Next Steps
- Read the [Client Library Documentation][] for Google Fake API to see other available methods on the client.
- Read the [Google Fake API Product documentation][Product Documentation] to learn more about the product and see How-to Guides.
- View this [repository's main README](https://github.com/GoogleCloudPlatform/google-cloud-node/blob/master/README.md) to see the full list of Cloud APIs that we cover.

[Client Library Documentation]: https://googlecloudplatform.github.io/google-cloud-node/#/docs/library
[Product Documentation]: https://cloud.google.com/library
Loading

0 comments on commit cadd53d

Please sign in to comment.