Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix the init command #336

Merged
merged 11 commits into from
Mar 20, 2024
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved.
* Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 5a7297f

*
* WSO2 LLC. licenses this file to you 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.
*/

package io.ballerina.persist.tools;

import io.ballerina.persist.cmd.Init;
import org.testng.annotations.Test;
import picocli.CommandLine;

import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Path;
import java.nio.file.Paths;

import static io.ballerina.persist.tools.utils.GeneratedSourcesTestUtils.assertGeneratedSources;

public class ToolingInitTest {
public static final String GENERATED_SOURCES_DIRECTORY = Paths.get("build", "generated-sources")
.toString();
private static final PrintStream errStream = System.err;

@Test(enabled = true)
public void testInitWithDatastore() {
executeInitCommand("tool_test_init_1", "mysql");
assertGeneratedSources("tool_test_init_1");
}

@Test(enabled = true)
public void testInitWithoutArguments() {
executeInitCommand("tool_test_init_1");
assertGeneratedSources("tool_test_init_1");
}

@Test(enabled = true)
public void testInitWithBothDatastoreAndModule() {
executeInitCommand("tool_test_init_1", "mysql", "test_module");
assertGeneratedSources("tool_test_init_1");
}

public static void executeInitCommand(String subDir, String... args) {
Class<?> persistClass;
Path sourcePath = Paths.get(GENERATED_SOURCES_DIRECTORY, subDir);
try {
persistClass = Class.forName("io.ballerina.persist.cmd.Init");
Init persistCmd = (Init) persistClass.getDeclaredConstructor(String.class)
.newInstance(sourcePath.toAbsolutePath().toString());
if (args.length > 1) {
// ballerina persist init --datastore <datastore> --module <module>
new CommandLine(persistCmd).parseArgs("--datastore", args[0], "--module", args[1]);
} else if (args.length == 1) {
// ballerina persist init --datastore <datastore>
new CommandLine(persistCmd).parseArgs("--datastore", args[0]);
} else {
// ballerina persist init
new CommandLine(persistCmd).parseArgs();
}
persistCmd.execute();
} catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException
| InvocationTargetException e) {
errStream.println(e.getMessage());
}
}
}
67 changes: 19 additions & 48 deletions persist-cli/src/main/java/io/ballerina/persist/cmd/Init.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,13 @@

import io.ballerina.cli.BLauncherCmd;
import io.ballerina.persist.BalException;
import io.ballerina.persist.PersistToolsConstants;
import io.ballerina.persist.nodegenerator.syntax.constants.BalSyntaxConstants;
import io.ballerina.projects.util.ProjectUtils;
import picocli.CommandLine;

import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
Expand All @@ -39,9 +35,7 @@
import static io.ballerina.persist.PersistToolsConstants.COMPONENT_IDENTIFIER;
import static io.ballerina.persist.PersistToolsConstants.MIGRATIONS;
import static io.ballerina.persist.PersistToolsConstants.PERSIST_DIRECTORY;
import static io.ballerina.persist.PersistToolsConstants.SUPPORTED_DB_PROVIDERS;
import static io.ballerina.persist.nodegenerator.syntax.constants.BalSyntaxConstants.BAL_EXTENSION;
import static io.ballerina.persist.nodegenerator.syntax.utils.TomlSyntaxUtils.readPackageName;
import static io.ballerina.persist.utils.BalProjectUtils.validateBallerinaProject;

/**
Expand Down Expand Up @@ -85,55 +79,20 @@ public void execute() {
return;
}

if (datastore == null) {
datastore = PersistToolsConstants.SupportedDataSources.IN_MEMORY_TABLE;
} else if (!SUPPORTED_DB_PROVIDERS.contains(datastore)) {
errStream.printf("ERROR: the persist layer supports one of data stores: %s" +
". but found '%s' datasource.%n", Arrays.toString(SUPPORTED_DB_PROVIDERS.toArray()), datastore);
return;
}

if (Files.isDirectory(Paths.get(sourcePath, PERSIST_DIRECTORY, MIGRATIONS))) {
errStream.println("ERROR: reinitializing persistence after executing the migrate command is not " +
"permitted. please remove the migrations directory within the persist directory and try " +
"executing the command again.");
return;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we remove this too? As we are not adding any configuration, this validation is not valid

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 5a7297f


if (datastore.equals(PersistToolsConstants.SupportedDataSources.GOOGLE_SHEETS)) {
errStream.printf(BalSyntaxConstants.EXPERIMENTAL_NOTICE, "The support for Google Sheets data store " +
"is currently an experimental feature, and its behavior may be subject to change in future " +
"releases." + System.lineSeparator());
}

Path projectPath = Paths.get(sourcePath);
try {
validateBallerinaProject(projectPath);
} catch (BalException e) {
errStream.println(e.getMessage());
return;
}
String packageName;
try {
packageName = readPackageName(this.sourcePath);
} catch (BalException e) {
errStream.println(e.getMessage());
return;
}
if (module == null) {
module = packageName;
} else {
module = module.replaceAll("\"", "");
}
if (!ProjectUtils.validateModuleName(module)) {
errStream.println("ERROR: invalid module name : '" + module + "' :\n" +
"module name can only contain alphanumerics, underscores and periods");
return;
} else if (!ProjectUtils.validateNameLength(module)) {
errStream.println("ERROR: invalid module name : '" + module + "' :\n" +
"maximum length of module name is 256 characters");
return;
}

Path persistDirPath = Paths.get(this.sourcePath, PERSIST_DIRECTORY);
if (!Files.exists(persistDirPath)) {
Expand Down Expand Up @@ -171,13 +130,25 @@ public void execute() {
return;
}
}
errStream.println("Initialized the package for persistence.");
errStream.println(System.lineSeparator() + "Next steps:");

errStream.println("- Define your data model in \"persist/model.bal\".");
errStream.println("- Run \"bal persist generate\" to generate persist client and " +
"entity types for your data model.");

if (datastore != null || module != null) {
errStream.println("The behavior of the `bal persist init` command has been updated starting " +
"from Ballerina update 09.");
errStream.println("Now, you no longer need to provide any parameters. The command will exclusively " +
"create the `persist` directory in the project's root directory. This directory contains the " +
"data model definition file (`model.bal`) for the project." + System.lineSeparator());
errStream.println("If you have any questions or need further assistance, refer to the updated " +
"documentation.");
} else {
errStream.println("Initialized the package for persistence.");
errStream.println(System.lineSeparator() + "Next steps:");

errStream.println("1. Define your data model in \"persist/model.bal\".");
errStream.println("2. Execute `bal persist add --datastore <datastore> --module <module>` to add an" +
" entry to \"Ballerina.toml\" for integrating code generation with the package build process.");
errStream.println("OR");
errStream.println("Execute `bal persist generate --datastore <datastore> --module <module>` for " +
"a one-time generation of the client.");
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ EXAMPLES
$ bal persist generate --help

Generate client objects for the model definition file inside persist directory.
$ bal persist generate
$ bal persist generate --module persist --datastore mysql
Copy link
Member

@daneshk daneshk Mar 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SYNOPSIS
       bal persist generate [--module <module name>]
                                        [--datastore <store type>]
                                        [<-h> | <--help>]

OPTIONS
       --module <module name>
              The name of the module to initialize the persistence layer. If not specified, the default module will be used.
       --datastore <store type>
              The type of the datastore to be used for persistence.
              The supported datastores are 'inmemory', 'mysql', 'mssql', 'postgresql', 'googlesheets', and redis.
       -h, --help
           Print the usage details of all commands.

We need to mention the options like above here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 48cc647


26 changes: 21 additions & 5 deletions persist-cli/src/main/resources/cli-help/ballerina-persist.help
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ DESCRIPTION
data persistence in a Ballerina package. This step creates the required
directories and configuration files. For example:

$ bal persist init
$ bal persist add

Define the application's data model as the next step. Use the generated
definition file in the "persist" directory to define the data model
Expand All @@ -31,11 +31,25 @@ DESCRIPTION
Department department;
|};

Then, generate the client API based on the data model. Use the generated
API to query and manipulate the persistent data in the application.
Then, generate the client API based on the data model. You can use the `bal build` command to generate the client.
This process will automatically regenerate the client whenever you modify the data model during project builds.
Use the generated API to query and manipulate the persistent data in the application.
For example:

$ bal persist generate
$ bal build

Apart from the above commands, the following commands are also available:

$ bal persist init

This command initializes the package for persistence and used in one time generation of the clients.
Bhashinee marked this conversation as resolved.
Show resolved Hide resolved
This command will create a new directory named 'persist' in the project directory. The 'persist' directory will
contain empty model definition file which can be used to define the data model of the Ballerina project.

$ bal persist generate --module persist --datastore mysql

This command generates the client API based on the data model defined in the "persist" directory. Usually used
for one time generation of the client.

OPTIONS
-h, --help
Expand All @@ -44,7 +58,9 @@ OPTIONS
BALLERINA COMMANDS
The below is a list of available subcommands:

init Initialize the package for persistence
add Initialize the package for persistence. Used along with `bal build` command.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
add Initialize the package for persistence. Used along with `bal build` command.
add Initialize the package for persistence and integrate the client generation to the `bal build` command.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed the suggestions in 103a302

init Initialize the package for persistence for one time code generation. Used along with
`generate` command.
Bhashinee marked this conversation as resolved.
Show resolved Hide resolved
generate Generate the client API based on the data model defined in the "persist" directory

Use 'bal persist <command> --help' for more information on a specific command.
Loading