diff --git a/appveyor.yml b/appveyor.yml
index 2f22bfc438b..008ac171f88 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -70,7 +70,7 @@ test_script:
# test ps pestore
- ps: |
$ErrorActionPreference = "Stop"
- cd samples\client\petstore\powershell-experimental\
+ cd samples\client\petstore\powershell\
.\Build.ps1
Import-Module -Name '.\src\PSPetstore'
$Result = Invoke-Pester -PassThru
diff --git a/bin/openapi3/powershell-experimental-petstore.sh b/bin/openapi3/powershell-experimental-petstore.sh
deleted file mode 100755
index 148fd2690e5..00000000000
--- a/bin/openapi3/powershell-experimental-petstore.sh
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/bin/sh
-
-SCRIPT="$0"
-echo "# START SCRIPT: $SCRIPT"
-
-while [ -h "$SCRIPT" ] ; do
- ls=$(ls -ld "$SCRIPT")
- link=$(expr "$ls" : '.*-> \(.*\)$')
- if expr "$link" : '/.*' > /dev/null; then
- SCRIPT="$link"
- else
- SCRIPT=$(dirname "$SCRIPT")/"$link"
- fi
-done
-
-if [ ! -d "${APP_DIR}" ]; then
- APP_DIR=$(dirname "$SCRIPT")/..
- APP_DIR=$(cd "${APP_DIR}"; pwd)
-fi
-
-executable="./modules/openapi-generator-cli/target/openapi-generator-cli.jar"
-
-if [ ! -f "$executable" ]
-then
- mvn -B clean package
-fi
-
-# if you've executed sbt assembly previously it will use that instead.
-export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties"
-ags="generate -t modules/openapi-generator/src/main/resources/powershell-experimental -i modules/openapi-generator/src/test/resources/3_0/powershell/petstore.yaml -g powershell-experimental -o samples/client/petstore/powershell-experimental --additional-properties powershellGalleryUrl=https://www.powershellgallery.com/packages/PSPetstore,packageGuid=a27b908d-2a20-467f-bc32-af6f3a654ac5,packageName=PSPetstore,apiNamePrefix=PS,packageVersion=0.1.2,commonVerbs=Delete=Remove:Patch=Update $@"
-
-java ${JAVA_OPTS} -jar ${executable} ${ags}
diff --git a/bin/openapi3/powershell-petstore.sh b/bin/openapi3/powershell-petstore.sh
deleted file mode 100755
index fe5da4a22f6..00000000000
--- a/bin/openapi3/powershell-petstore.sh
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/bin/sh
-
-SCRIPT="$0"
-echo "# START SCRIPT: $SCRIPT"
-
-while [ -h "$SCRIPT" ] ; do
- ls=`ls -ld "$SCRIPT"`
- link=`expr "$ls" : '.*-> \(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- SCRIPT="$link"
- else
- SCRIPT=`dirname "$SCRIPT"`/"$link"
- fi
-done
-
-if [ ! -d "${APP_DIR}" ]; then
- APP_DIR=`dirname "$SCRIPT"`/..
- APP_DIR=`cd "${APP_DIR}"; pwd`
-fi
-
-executable="./modules/openapi-generator-cli/target/openapi-generator-cli.jar"
-
-if [ ! -f "$executable" ]
-then
- mvn clean package
-fi
-
-# if you've executed sbt assembly previously it will use that instead.
-export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties"
-ags="generate -t modules/openapi-generator/src/main/resources/powershell -i modules/openapi-generator/src/test/resources/3_0/petstore.yaml -g powershell -o samples/client/petstore/powershell --additional-properties packageGuid=a27b908d-2a20-467f-bc32-af6f3a654ac5,csharpClientPath=\$ScriptDir\..\..\petstore\csharp\OpenAPIClient $@"
-
-java $JAVA_OPTS -jar $executable $ags
diff --git a/bin/powershell-petstore.sh b/bin/powershell-petstore.sh
index dcad1f299ab..264e58d9f5b 100755
--- a/bin/powershell-petstore.sh
+++ b/bin/powershell-petstore.sh
@@ -27,6 +27,6 @@ fi
# if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties"
-ags="generate -t modules/openapi-generator/src/main/resources/powershell -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g powershell -o samples/client/petstore/powershell --additional-properties packageGuid=a27b908d-2a20-467f-bc32-af6f3a654ac5,csharpClientPath=\$ScriptDir\..\..\petstore\csharp\OpenAPIClient $@"
+ags="generate -t modules/openapi-generator/src/main/resources/powershell -i modules/openapi-generator/src/test/resources/3_0/powershell/petstore.yaml -g powershell -o samples/client/petstore/powershell --additional-properties powershellGalleryUrl=https://www.powershellgallery.com/packages/PSPetstore,packageGuid=a27b908d-2a20-467f-bc32-af6f3a654ac5,packageName=PSPetstore,apiNamePrefix=PS,packageVersion=0.1.2,commonVerbs=Delete=Remove:Patch=Update $@"
java ${JAVA_OPTS} -jar ${executable} ${ags}
diff --git a/bin/windows/powershell-petsstore.bat b/bin/windows/powershell-petsstore.bat
deleted file mode 100644
index ca7e08dcaa8..00000000000
--- a/bin/windows/powershell-petsstore.bat
+++ /dev/null
@@ -1,10 +0,0 @@
-set executable=.\modules\openapi-generator-cli\target\openapi-generator-cli.jar
-
-If Not Exist %executable% (
- mvn clean package
-)
-
-REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M -DloggerPath=conf/log4j.properties
-set ags=generate -i modules\openapi-generator\src\test\resources\2_0\petstore.yaml -g powershell -o samples\client\petstore\powershell --additional-properties packageGuid=a27b908d-2a20-467f-bc32-af6f3a654ac5,csharpClientPath=$ScriptDir\..\..\petstore\csharp\OpenAPIClient
-
-java %JAVA_OPTS% -jar %executable% %ags%
diff --git a/bin/windows/powershell-petstore.bat b/bin/windows/powershell-petstore.bat
new file mode 100755
index 00000000000..f5ea2c5f910
--- /dev/null
+++ b/bin/windows/powershell-petstore.bat
@@ -0,0 +1,10 @@
+set executable=.\modules\openapi-generator-cli\target\openapi-generator-cli.jar
+
+If Not Exist %executable% (
+ mvn clean package
+)
+
+REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M -DloggerPath=conf/log4j.properties
+set ags=generate -i modules\openapi-generator\src\test\resources\3_0\petstore.yaml -g powershell -o samples\client\petstorep\powershell --additional-properties powershellGalleryUrl=https://www.powershellgallery.com/packages/PSPetstore,packageGuid=a27b908d-2a20-467f-bc32-af6f3a654ac5,packageName=PSPetstore,apiNamePrefix=PS,packageVersion=0.1.2,commonVerbs=Delete=Remove:Patch=Update
+
+java %JAVA_OPTS% -jar %executable% %ags%
diff --git a/docs/generators.md b/docs/generators.md
index cc730aab7d8..6d7800fd694 100644
--- a/docs/generators.md
+++ b/docs/generators.md
@@ -46,8 +46,7 @@ The following generators are available:
* [ocaml](generators/ocaml.md)
* [perl](generators/perl.md)
* [php](generators/php.md)
-* [powershell](generators/powershell.md)
-* [powershell-experimental (beta)](generators/powershell-experimental.md)
+* [powershell (beta)](generators/powershell.md)
* [python](generators/python.md)
* [python-experimental (experimental)](generators/python-experimental.md)
* [r](generators/r.md)
diff --git a/docs/generators/powershell.md b/docs/generators/powershell.md
index ae0a0e5ce65..8d395f0f7ba 100644
--- a/docs/generators/powershell.md
+++ b/docs/generators/powershell.md
@@ -5,9 +5,12 @@ sidebar_label: powershell
| Option | Description | Values | Default |
| ------ | ----------- | ------ | ------- |
-|csharpClientPath|Path to the C# API client generated by OpenAPI Generator, e.g. $ScriptDir\..\csharp\OpenAPIClient where $ScriptDir is the current directory. NOTE: you will need to generate the C# API client separately.| |$ScriptDir\csharp\OpenAPIClient|
+|apiNamePrefix|Prefix that will be appended to all PS objects. Default: empty string. e.g. Pet => PSPet.| |null|
+|commonVerbs|PS common verb mappings. e.g. Delete=Remove:Patch=Update to map Delete with Remove and Patch with Update accordingly.| |null|
|packageGuid|GUID for PowerShell module (e.g. a27b908d-2a20-467f-bc32-af6f3a654ac5). A random GUID will be generated by default.| |null|
-|packageName|Client package name (e.g. org.openapitools.client).| |Org.OpenAPITools|
+|packageName|Client package name (e.g. PSTwitter).| |PSOpenAPITools|
+|packageVersion|Package version (e.g. 0.1.2).| |0.1.2|
+|powershellGalleryUrl|URL to the module in PowerShell Gallery (e.g. https://www.powershellgallery.com/packages/PSTwitter/).| |null|
## IMPORT MAPPING
@@ -56,6 +59,7 @@ sidebar_label: powershell
Single
String
System.DateTime
+System.IO.FileInfo
TimeSpan
UInt16
UInt32
@@ -68,37 +72,70 @@ sidebar_label: powershell
## RESERVED WORDS
-- Begin
-- Break
-- Catch
-- Continue
-- Data
-- Do
-- Dynamicparam
-- Else
-- Elseif
-- End
-- Exit
-- Filter
-- Finally
-- For
-- Foreach
-- From
-- Function
-- If
-- In
-- Local
-- Param
-- Private
-- Process
-- Return
-- Switch
-- Throw
-- Trap
-- Try
-- Until
-- Where
-- While
+- args
+- begin
+- break
+- catch
+- consolefilename
+- continue
+- data
+- do
+- dynamicparam
+- else
+- elseif
+- end
+- error
+- event
+- eventargs
+- eventsubscriber
+- executioncontext
+- exit
+- false
+- filter
+- finally
+- for
+- foreach
+- from
+- function
+- home
+- host
+- if
+- in
+- input
+- lastexitcode
+- local
+- matches
+- myinvocation
+- nestedpromptlevel
+- null
+- param
+- pid
+- private
+- process
+- profile
+- pscmdlet
+- pscommandpath
+- psculture
+- psdebugcontext
+- pshome
+- psitem
+- psscriptroot
+- pssenderinfo
+- psuiculture
+- psversiontable
+- return
+- sender
+- shellid
+- stacktrace
+- switch
+- this
+- throw
+- trap
+- true
+- try
+- until
+- where
+- while
## FEATURE SET
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PowerShellClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PowerShellClientCodegen.java
index cc2ba5bbd56..6c3625e1222 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PowerShellClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PowerShellClientCodegen.java
@@ -1,6 +1,5 @@
/*
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
- * Copyright 2018 SmartBear Software
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,8 +18,12 @@ package org.openapitools.codegen.languages;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.Schema;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.*;
+import org.openapitools.codegen.meta.GeneratorMetadata;
+import org.openapitools.codegen.meta.Stability;
import org.openapitools.codegen.meta.features.*;
import org.openapitools.codegen.utils.ModelUtils;
import org.openapitools.codegen.utils.ProcessUtils;
@@ -39,10 +42,17 @@ public class PowerShellClientCodegen extends DefaultCodegen implements CodegenCo
private String packageGuid = "{" + randomUUID().toString().toUpperCase(Locale.ROOT) + "}";
protected String sourceFolder = "src";
- protected String packageName = "Org.OpenAPITools";
- protected String csharpClientPath = "$ScriptDir\\csharp\\OpenAPIClient";
+ protected String packageName = "PSOpenAPITools";
+ protected String packageVersion = "0.1.2";
protected String apiDocPath = "docs/";
protected String modelDocPath = "docs/";
+ protected String apiTestPath = "tests/Api";
+ protected String modelTestPath = "tests/Model";
+ protected HashSet nullablePrimitives;
+ protected String powershellGalleryUrl;
+ protected HashSet powershellVerbs;
+ protected Map commonVerbs; // verbs not in the official ps verb list but can be mapped to one of the verbs
+ protected HashSet methodNames; // store a list of method names to detect duplicates
/**
* Constructs an instance of `PowerShellClientCodegen`.
@@ -71,16 +81,20 @@ public class PowerShellClientCodegen extends DefaultCodegen implements CodegenCo
ParameterFeature.Cookie
)
);
-
- outputFolder = "generated-code" + File.separator + "powershell";
+
+ generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
+ .stability(Stability.BETA)
+ .build();
+
+ outputFolder = "generated-code" + File.separator + "powershell-expiermental";
modelTemplateFiles.put("model.mustache", ".ps1");
apiTemplateFiles.put("api.mustache", ".ps1");
modelTestTemplateFiles.put("model_test.mustache", ".ps1");
apiTestTemplateFiles.put("api_test.mustache", ".ps1");
- modelDocTemplateFiles.clear();
- apiDocTemplateFiles.clear();
+ modelDocTemplateFiles.put("model_doc.mustache", ".md");
+ apiDocTemplateFiles.put("api_doc.mustache", ".md");
embeddedTemplateDir = templateDir = "powershell";
- apiPackage = packageName + File.separator + "API";
+ apiPackage = packageName + File.separator + "Api";
modelPackage = packageName + File.separator + "Model";
// https://blogs.msdn.microsoft.com/powershell/2010/01/07/how-objects-are-sent-to-and-from-remote-sessions/
@@ -107,44 +121,329 @@ public class PowerShellClientCodegen extends DefaultCodegen implements CodegenCo
"Boolean",
"Guid",
"Uri",
+ "System.IO.FileInfo",
"Version"
));
- // https://richardspowershellblog.wordpress.com/2009/05/02/powershell-reserved-words/
- reservedWords = new HashSet(Arrays.asList(
- "Begin",
- "Break",
- "Catch",
- "Continue",
- "Data",
- "Do",
- "Dynamicparam",
- "Else",
- "Elseif",
- "End",
+ commonVerbs = new HashMap();
+
+ Map> verbMappings = new HashMap>();
+
+ // common
+ verbMappings.put("Add", Arrays.asList("Append", "Attach", "Concatenate", "Insert"));
+ verbMappings.put("Clear", Arrays.asList("Flush", "Erase", "Release", "Unmark", "Unset", "Nullify"));
+ verbMappings.put("Close", Arrays.asList());
+ verbMappings.put("Copy", Arrays.asList("Duplicate", "Clone", "Replicate", "Sync"));
+ verbMappings.put("Enter", Arrays.asList("PushInto"));
+ verbMappings.put("Exit", Arrays.asList("PopOut"));
+ verbMappings.put("Find", Arrays.asList());
+ verbMappings.put("Format", Arrays.asList());
+ verbMappings.put("Get", Arrays.asList("Read", "Open", "Cat", "Type", "Dir", "Obtain", "Dump", "Acquire", "Examine", "Find", "Search"));
+ verbMappings.put("Hide", Arrays.asList("Block"));
+ verbMappings.put("Join", Arrays.asList("Combine", "Unite", "Connect", "Associate"));
+ verbMappings.put("Lock", Arrays.asList("RestrictSecure"));
+ verbMappings.put("Move", Arrays.asList("Transfer", "Name", "Migrate"));
+ verbMappings.put("New", Arrays.asList("Create", "Generate", "Build", "Make", "Allocate"));
+ verbMappings.put("Open", Arrays.asList());
+ verbMappings.put("Optimize", Arrays.asList());
+ verbMappings.put("Pop", Arrays.asList());
+ verbMappings.put("Push", Arrays.asList());
+ verbMappings.put("Redo", Arrays.asList());
+ verbMappings.put("Remove", Arrays.asList("Clear", "Cut", "Dispose", "Discard", "Erase"));
+ verbMappings.put("Rename", Arrays.asList("Change"));
+ verbMappings.put("Reset", Arrays.asList());
+ verbMappings.put("Search", Arrays.asList("FindLocate"));
+ verbMappings.put("Select", Arrays.asList("FindLocate"));
+ verbMappings.put("Set", Arrays.asList("Write", "Reset", "Assign", "Configure"));
+ verbMappings.put("Show", Arrays.asList("DisplayProduce"));
+ verbMappings.put("Skip", Arrays.asList("BypassJump"));
+ verbMappings.put("Split", Arrays.asList("parate"));
+ verbMappings.put("Step", Arrays.asList());
+ verbMappings.put("Switch", Arrays.asList());
+ verbMappings.put("Undo", Arrays.asList());
+ verbMappings.put("Unlock", Arrays.asList("Release", "Unrestrict", "Unsecure"));
+ verbMappings.put("Watch", Arrays.asList());
+
+ // communication
+ verbMappings.put("Connect", Arrays.asList("JoinTelnet"));
+ verbMappings.put("Disconnect", Arrays.asList("BreakLogoff"));
+ verbMappings.put("Read", Arrays.asList("Acquire", "Prompt", "Get"));
+ verbMappings.put("Receive", Arrays.asList("Read", "Accept", "Peek"));
+ verbMappings.put("Send", Arrays.asList("Put", "Broadcast", "Mail", "Fax"));
+ verbMappings.put("Write", Arrays.asList("PutPrint"));
+
+ // data
+ verbMappings.put("Backup", Arrays.asList(" Save", " Burn", " Replicate", "Sync"));
+ verbMappings.put("Checkpoint", Arrays.asList(" Diff"));
+ verbMappings.put("Compare", Arrays.asList(" Diff"));
+ verbMappings.put("Compress", Arrays.asList(" Compact"));
+ verbMappings.put("Convert", Arrays.asList(" Change", " Resize", "Resample"));
+ verbMappings.put("ConvertFrom", Arrays.asList(" Export", " Output", "Out"));
+ verbMappings.put("ConvertTo", Arrays.asList(" Import", " Input", "In"));
+ verbMappings.put("Dismount", Arrays.asList(" UnmountUnlink"));
+ verbMappings.put("Edit", Arrays.asList(" Change", " Update", "Modify"));
+ verbMappings.put("Expand", Arrays.asList(" ExplodeUncompress"));
+ verbMappings.put("Export", Arrays.asList(" ExtractBackup"));
+ verbMappings.put("Group", Arrays.asList(" Aggregate", " Arrange", " Associate", "Correlate"));
+ verbMappings.put("Import", Arrays.asList(" BulkLoadLoad"));
+ verbMappings.put("Initialize", Arrays.asList(" Erase", " Init", " Renew", " Rebuild", " Reinitialize", "Setup"));
+ verbMappings.put("Limit", Arrays.asList(" Quota"));
+ verbMappings.put("Merge", Arrays.asList(" CombineJoin"));
+ verbMappings.put("Mount", Arrays.asList(" Connect"));
+ verbMappings.put("Out", Arrays.asList());
+ verbMappings.put("Publish", Arrays.asList(" Deploy", " Release", "Install"));
+ verbMappings.put("Restore", Arrays.asList(" Repair", " Return", " Undo", "Fix"));
+ verbMappings.put("Save", Arrays.asList());
+ verbMappings.put("Sync", Arrays.asList(" Replicate", " Coerce", "Match"));
+ verbMappings.put("Unpublish", Arrays.asList(" Uninstall", " Revert", "Hide"));
+ verbMappings.put("Update", Arrays.asList(" Refresh", " Renew", " Recalculate", "Re-index"));
+
+ // diagnostic
+ verbMappings.put("Debug", Arrays.asList("Diagnose"));
+ verbMappings.put("Measure", Arrays.asList("Calculate", "Determine", "Analyze"));
+ verbMappings.put("Ping", Arrays.asList());
+ verbMappings.put("Repair", Arrays.asList("FixRestore"));
+ verbMappings.put("Resolve", Arrays.asList("ExpandDetermine"));
+ verbMappings.put("Test", Arrays.asList("Diagnose", "Analyze", "Salvage", "Verify"));
+ verbMappings.put("Trace", Arrays.asList("Track", "Follow", "Inspect", "Dig"));
+
+ // lifecycle
+ verbMappings.put("Approve", Arrays.asList());
+ verbMappings.put("Assert", Arrays.asList("Certify"));
+ verbMappings.put("Build", Arrays.asList());
+ verbMappings.put("Complete", Arrays.asList());
+ verbMappings.put("Confirm", Arrays.asList("Acknowledge", "Agree", "Certify", "Validate", "Verify"));
+ verbMappings.put("Deny", Arrays.asList("Block", "Object", "Refuse", "Reject"));
+ verbMappings.put("Deploy", Arrays.asList());
+ verbMappings.put("Disable", Arrays.asList("HaltHide"));
+ verbMappings.put("Enable", Arrays.asList("StartBegin"));
+ verbMappings.put("Install", Arrays.asList("Setup"));
+ verbMappings.put("Invoke", Arrays.asList("RunStart"));
+ verbMappings.put("Register", Arrays.asList());
+ verbMappings.put("Request", Arrays.asList());
+ verbMappings.put("Restart", Arrays.asList("Recycle"));
+ verbMappings.put("Resume", Arrays.asList());
+ verbMappings.put("Start", Arrays.asList("Launch", "Initiate", "Boot"));
+ verbMappings.put("Stop", Arrays.asList("End", "Kill", "Terminate", "Cancel"));
+ verbMappings.put("Submit", Arrays.asList("Post"));
+ verbMappings.put("Suspend", Arrays.asList("Pause"));
+ verbMappings.put("Uninstall", Arrays.asList());
+ verbMappings.put("Unregister", Arrays.asList("Remove"));
+ verbMappings.put("Wait", Arrays.asList("SleepPause"));
+
+ // security
+ verbMappings.put("Block", Arrays.asList("Prevent", "Limit", "Deny"));
+ verbMappings.put("Grant", Arrays.asList("AllowEnable"));
+ verbMappings.put("Protect", Arrays.asList("Encrypt", "Safeguard", "Seal"));
+ verbMappings.put("Revoke", Arrays.asList("RemoveDisable"));
+ verbMappings.put("Unblock", Arrays.asList("ClearAllow"));
+ verbMappings.put("Unprotect", Arrays.asList("DecryptUnseal"));
+
+ // other
+ verbMappings.put("Use", Arrays.asList());
+
+ for (Map.Entry> entry : verbMappings.entrySet()) {
+ // loop through each verb in the list
+ for (String verb : entry.getValue()) {
+ if (verbMappings.containsKey(verb)) {
+ // the verb to be mapped is also a common verb, do nothing
+ LOGGER.debug("verbmapping: skipped {}", verb);
+ } else {
+ commonVerbs.put(verb, entry.getKey());
+ LOGGER.debug("verbmapping: adding {} => {}", verb, entry.getKey());
+ }
+ }
+ }
+
+ powershellVerbs = new HashSet(Arrays.asList(
+ "Add",
+ "Clear",
+ "Close",
+ "Copy",
+ "Enter",
"Exit",
- "Filter",
- "Finally",
- "For",
- "Foreach",
- "From",
- "Function",
- "If",
- "In",
- "Param",
- "Process",
- "Return",
+ "Find",
+ "Format",
+ "Get",
+ "Hide",
+ "Join",
+ "Lock",
+ "Move",
+ "New",
+ "Open",
+ "Optimize",
+ "Pop",
+ "Push",
+ "Redo",
+ "Remove",
+ "Rename",
+ "Reset",
+ "Search",
+ "Select",
+ "Set",
+ "Show",
+ "Skip",
+ "Split",
+ "Step",
"Switch",
- "Throw",
- "Trap",
- "Try",
- "Until",
- "While",
- "Local",
- "Private",
- "Where"
+ "Undo",
+ "Unlock",
+ "Watch",
+ "Connect",
+ "Disconnect",
+ "Read",
+ "Receive",
+ "Send",
+ "Write",
+ "Backup",
+ "Checkpoint",
+ "Compare",
+ "Compress",
+ "Convert",
+ "ConvertFrom",
+ "ConvertTo",
+ "Dismount",
+ "Edit",
+ "Expand",
+ "Export",
+ "Group",
+ "Import",
+ "Initialize",
+ "Limit",
+ "Merge",
+ "Mount",
+ "Out",
+ "Publish",
+ "Restore",
+ "Save",
+ "Sync",
+ "Unpublish",
+ "Update",
+ "Debug",
+ "Measure",
+ "Ping",
+ "Repair",
+ "Resolve",
+ "Test",
+ "Trace",
+ "Approve",
+ "Assert",
+ "Build",
+ "Complete",
+ "Confirm",
+ "Deny",
+ "Deploy",
+ "Disable",
+ "Enable",
+ "Install",
+ "Invoke",
+ "Register",
+ "Request",
+ "Restart",
+ "Resume",
+ "Start",
+ "Stop",
+ "Submit",
+ "Suspend",
+ "Uninstall",
+ "Unregister",
+ "Wait",
+ "Block",
+ "Grant",
+ "Protect",
+ "Revoke",
+ "Unblock",
+ "Unprotect",
+ "Use"
));
+ methodNames = new HashSet();
+
+ nullablePrimitives = new HashSet(Arrays.asList(
+ "System.Nullable[Byte]",
+ "System.Nullable[SByte]",
+ "System.Nullable[Int16]",
+ "System.Nullable[Int32]",
+ "System.Nullable[Int64]",
+ "System.Nullable[UInt16]",
+ "System.Nullable[UInt32]",
+ "System.Nullable[UInt64]",
+ "System.Nullable[Decimal]",
+ "System.Nullable[Single]",
+ "System.Nullable[Double]",
+ "System.Nullable[Boolean]"
+ ));
+
+ // list of reserved words - must be in lower case
+ reservedWords = new HashSet(Arrays.asList(
+ // https://richardspowershellblog.wordpress.com/2009/05/02/powershell-reserved-words/
+ "begin",
+ "break",
+ "catch",
+ "continue",
+ "data",
+ "do",
+ "dynamicparam",
+ "else",
+ "elseif",
+ "end",
+ "exit",
+ "filter",
+ "finally",
+ "for",
+ "foreach",
+ "from",
+ "function",
+ "if",
+ "in",
+ "param",
+ "process",
+ "return",
+ "switch",
+ "throw",
+ "trap",
+ "try",
+ "until",
+ "while",
+ "local",
+ "private",
+ "where",
+ // special variables
+ "args",
+ "consolefilename",
+ "error",
+ "event",
+ "eventargs",
+ "eventsubscriber",
+ "executioncontext",
+ "false",
+ "foreach",
+ "home",
+ "host",
+ "input",
+ "lastexitcode",
+ "matches",
+ "myinvocation",
+ "nestedpromptlevel",
+ "null",
+ "pid",
+ "profile",
+ "pscmdlet",
+ "pscommandpath",
+ "psculture",
+ "psdebugcontext",
+ "pshome",
+ "psitem",
+ "psscriptroot",
+ "pssenderinfo",
+ "psuiculture",
+ "psversiontable",
+ "sender",
+ "shellid",
+ "stacktrace",
+ "this",
+ "true"
+ ));
defaultIncludes = new HashSet(Arrays.asList(
"Byte",
@@ -169,6 +468,7 @@ public class PowerShellClientCodegen extends DefaultCodegen implements CodegenCo
"Boolean",
"Guid",
"Uri",
+ "System.IO.FileInfo",
"Version"
));
@@ -180,18 +480,24 @@ public class PowerShellClientCodegen extends DefaultCodegen implements CodegenCo
typeMapping.put("long", "Int64");
typeMapping.put("double", "Double");
typeMapping.put("number", "Decimal");
- typeMapping.put("date-time", "System.DateTime");
+ typeMapping.put("object", "System.Collections.Hashtable");
+ typeMapping.put("file", "System.IO.FileInfo");
+ typeMapping.put("ByteArray", "System.Byte[]");
+ typeMapping.put("binary", "System.IO.FileInfo");
typeMapping.put("date", "System.DateTime");
- typeMapping.put("file", "String");
- typeMapping.put("object", "String");
- typeMapping.put("binary", "String");
+ typeMapping.put("date-time", "System.DateTime");
typeMapping.put("Date", "System.DateTime");
typeMapping.put("DateTime", "System.DateTime");
+ typeMapping.put("UUID", "String");
+ typeMapping.put("URI", "String");
cliOptions.clear();
- cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "Client package name (e.g. org.openapitools.client).").defaultValue(this.packageName));
+ cliOptions.add(new CliOption("powershellGalleryUrl", "URL to the module in PowerShell Gallery (e.g. https://www.powershellgallery.com/packages/PSTwitter/)."));
+ cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "Client package name (e.g. PSTwitter).").defaultValue(this.packageName));
+ cliOptions.add(new CliOption(CodegenConstants.PACKAGE_VERSION, "Package version (e.g. 0.1.2).").defaultValue(this.packageVersion));
cliOptions.add(new CliOption(CodegenConstants.OPTIONAL_PROJECT_GUID, "GUID for PowerShell module (e.g. a27b908d-2a20-467f-bc32-af6f3a654ac5). A random GUID will be generated by default."));
- cliOptions.add(new CliOption("csharpClientPath", "Path to the C# API client generated by OpenAPI Generator, e.g. $ScriptDir\\..\\csharp\\OpenAPIClient where $ScriptDir is the current directory. NOTE: you will need to generate the C# API client separately.").defaultValue(this.csharpClientPath));
+ cliOptions.add(new CliOption(CodegenConstants.API_NAME_PREFIX, "Prefix that will be appended to all PS objects. Default: empty string. e.g. Pet => PSPet."));
+ cliOptions.add(new CliOption("commonVerbs", "PS common verb mappings. e.g. Delete=Remove:Patch=Update to map Delete with Remove and Patch with Update accordingly."));
}
@@ -204,17 +510,17 @@ public class PowerShellClientCodegen extends DefaultCodegen implements CodegenCo
}
public String getHelp() {
- return "Generates a PowerShell API client (beta). (The dependency C# API client needs to be generated separately.";
+ return "Generates a PowerShell API client (beta)";
}
public void setPackageName(String packageName) {
this.packageName = packageName;
- this.apiPackage = packageName + File.separator + "API";
+ this.apiPackage = packageName + File.separator + "Api";
this.modelPackage = packageName + File.separator + "Model";
}
- public void setCsharpClientPath(String csharpClientPath) {
- this.csharpClientPath = csharpClientPath;
+ public void setPackageVersion(String packageVersion) {
+ this.packageVersion = packageVersion;
}
public void setSourceFolder(String sourceFolder) {
@@ -225,14 +531,36 @@ public class PowerShellClientCodegen extends DefaultCodegen implements CodegenCo
this.packageGuid = packageGuid;
}
+ public void setPowershellGalleryUrl(String powershellGalleryUrl) {
+ this.powershellGalleryUrl = powershellGalleryUrl;
+ }
+
@Override
public void processOpts() {
super.processOpts();
+ if (StringUtils.isEmpty(System.getenv("POWERSHELL_POST_PROCESS_FILE"))) {
+ LOGGER.info("Environment variable POWERSHELL_POST_PROCESS_FILE not defined so the PowerShell code may not be properly formatted. To define it, try 'export POWERSHELL_POST_PROCESS_FILE=\"Edit-DTWBeautifyScript\"'");
+ LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
+ }
+
+ if (additionalProperties.containsKey("powershellGalleryUrl")) {
+ setPowershellGalleryUrl((String) additionalProperties.get("powershellGalleryUrl"));
+ } else {
+ additionalProperties.put("powershellGalleryUrl", powershellGalleryUrl);
+ }
+
+ if (StringUtils.isNotBlank(powershellGalleryUrl)) {
+ // get the last segment of the URL
+ // e.g. https://www.powershellgallery.com/packages/PSTwitter => PSTwitter
+ additionalProperties.put("powershellGalleryId", powershellGalleryUrl.replaceFirst(".*/([^/?]+).*", "$1"));
+ }
+
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_PROJECT_GUID)) {
setPackageGuid((String) additionalProperties.get(CodegenConstants.OPTIONAL_PROJECT_GUID));
+ } else {
+ additionalProperties.put("packageGuid", packageGuid);
}
- additionalProperties.put("packageGuid", packageGuid);
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
this.setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
@@ -240,10 +568,23 @@ public class PowerShellClientCodegen extends DefaultCodegen implements CodegenCo
additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
}
- if (additionalProperties.containsKey("csharpClientPath")) {
- this.setCsharpClientPath((String) additionalProperties.get("csharpClientPath"));
+ if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) {
+ this.setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION));
} else {
- additionalProperties.put("csharpClientPath", csharpClientPath);
+ additionalProperties.put(CodegenConstants.PACKAGE_VERSION, packageVersion);
+ }
+
+ if (additionalProperties.containsKey("commonVerbs")) {
+ String[] entries = ((String)additionalProperties.get("commonVerbs")).split(":");
+ for (String entry : entries) {
+ String[] pair = entry.split("=");
+ if (pair.length == 2) {
+ commonVerbs.put(pair[0], pair[1]);
+ LOGGER.debug("Add commonVerbs: {} => {}", pair[0], pair[1]);
+ } else {
+ LOGGER.error("Failed to parse commonVerbs: {}", entry);
+ }
+ }
}
if (additionalProperties.containsKey(CodegenConstants.MODEL_PACKAGE)) {
@@ -267,15 +608,47 @@ public class PowerShellClientCodegen extends DefaultCodegen implements CodegenCo
supportingFiles.add(new SupportingFile("Org.OpenAPITools.psm1.mustache", infrastructureFolder, packageName + ".psm1"));
+ // client/configuration
+ supportingFiles.add(new SupportingFile("configuration.mustache", infrastructureFolder + "Client", apiNamePrefix + "Configuration.ps1"));
+
// private
- supportingFiles.add(new SupportingFile("Get-CommonParameters.ps1", infrastructureFolder + File.separator + "Private" + File.separator, "Get-CommonParameters.ps1"));
- supportingFiles.add(new SupportingFile("Out-DebugParameter.ps1", infrastructureFolder + File.separator + "Private" + File.separator, "Out-DebugParameter.ps1"));
+ supportingFiles.add(new SupportingFile("api_client.mustache", infrastructureFolder + "Private", apiNamePrefix + "ApiClient.ps1"));
+ supportingFiles.add(new SupportingFile("Get-CommonParameters.mustache", infrastructureFolder + File.separator + "Private" + File.separator, "Get-CommonParameters.ps1"));
+ supportingFiles.add(new SupportingFile("Out-DebugParameter.mustache", infrastructureFolder + File.separator + "Private" + File.separator, "Out-DebugParameter.ps1"));
+ supportingFiles.add(new SupportingFile("http_signature_auth.mustache", infrastructureFolder + "Private", apiNamePrefix + "HttpSignatureAuth.ps1"));
+ supportingFiles.add(new SupportingFile("rsa_provider.mustache", infrastructureFolder + "Private", apiNamePrefix + "RSAEncryptionProvider.cs"));
+
// en-US
supportingFiles.add(new SupportingFile("about_Org.OpenAPITools.help.txt.mustache", infrastructureFolder + File.separator + "en-US" + File.separator + "about_" + packageName + ".help.txt"));
+ // appveyor
+ supportingFiles.add(new SupportingFile("appveyor.mustache", "", "appveyor.yml"));
}
+ @SuppressWarnings("static-method")
+ @Override
+ public String escapeText(String input) {
+
+ if (input == null) {
+ return input;
+ }
+
+ // remove \t, \n, \r
+ // replace \ with \\
+ // replace " with \"
+ // outter unescape to retain the original multi-byte characters
+ // finally escalate characters avoiding code injection
+ return escapeUnsafeCharacters(
+ StringEscapeUtils.unescapeJava(
+ StringEscapeUtils.escapeJava(input)
+ .replace("\\/", "/"))
+ .replaceAll("[\\t\\n\\r]", " ")
+ .replace("\\", "\\\\")
+ .replace("\"", "\"\""));
+
+ }
+
@Override
public String escapeUnsafeCharacters(String input) {
return input.replace("#>", "#_>").replace("<#", "<_#");
@@ -287,9 +660,19 @@ public class PowerShellClientCodegen extends DefaultCodegen implements CodegenCo
return input.replace("\"", "");
}
+ @Override
+ public String toApiTestFilename(String name) {
+ return toApiFilename(name) + ".Tests";
+ }
+
+ @Override
+ public String toModelTestFilename(String name) {
+ return toModelFilename(name) + ".Tests";
+ }
+
@Override
public String apiTestFileFolder() {
- return (outputFolder + "/test").replace('/', File.separatorChar);
+ return (outputFolder + "/" + apiTestPath).replace('/', File.separatorChar);
}
@Override
@@ -304,7 +687,7 @@ public class PowerShellClientCodegen extends DefaultCodegen implements CodegenCo
@Override
public String modelTestFileFolder() {
- return (outputFolder + "/test").replace('/', File.separatorChar);
+ return (outputFolder + "/" + modelTestPath).replace('/', File.separatorChar);
}
@Override
@@ -320,7 +703,7 @@ public class PowerShellClientCodegen extends DefaultCodegen implements CodegenCo
@Override
public String escapeReservedWord(String name) {
- return "_" + name;
+ return "Var" + name;
}
/**
@@ -340,29 +723,29 @@ public class PowerShellClientCodegen extends DefaultCodegen implements CodegenCo
name = name + "_" + modelNameSuffix;
}
- name = sanitizeName(name);
+ // camelize the model name
+ // phone_number => PhoneNumber
+ name = camelize(sanitizeName(name));
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(name)) {
- LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + camelize("model_" + name));
- name = "model_" + name; // e.g. return => ModelReturn (after camelize)
+ LOGGER.warn(name + " (reserved word or special variable name) cannot be used as model name. Renamed to " + camelize("model_" + name));
+ name = camelize("model_" + name); // e.g. return => ModelReturn (after camelize)
}
// model name starts with number
if (name.matches("^\\d.*")) {
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + camelize("model_" + name));
- name = "model_" + name; // e.g. 200Response => Model200Response (after camelize)
+ name = camelize("model_" + name); // e.g. 200Response => Model200Response (after camelize)
}
- // camelize the model name
- // phone_number => PhoneNumber
- return camelize(name);
+ return name;
}
@Override
public String toModelFilename(String name) {
// should be the same as the model name
- return "New-" + toModelName(name);
+ return toModelName(name);
}
/**
@@ -403,11 +786,9 @@ public class PowerShellClientCodegen extends DefaultCodegen implements CodegenCo
Schema inner = ap.getItems();
return getTypeDeclaration(inner) + "[]";
} else if (ModelUtils.isMapSchema(p)) {
- Schema inner = ModelUtils.getAdditionalProperties(p);
- // TODO not sure if the following map/hash declaration is correct
- return "{String, " + getTypeDeclaration(inner) + "}";
+ return "System.Collections.Hashtable";
} else if (!languageSpecificPrimitives.contains(getSchemaType(p))) {
- return packageName + ".Model." + super.getTypeDeclaration(p);
+ return super.getTypeDeclaration(p);
}
return super.getTypeDeclaration(p);
}
@@ -419,25 +800,61 @@ public class PowerShellClientCodegen extends DefaultCodegen implements CodegenCo
throw new RuntimeException("Empty method name (operationId) not allowed");
}
- // method name cannot use reserved keyword, e.g. return
- if (isReservedWord(operationId)) {
- LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + camelize(sanitizeName("call_" + operationId)));
- operationId = "call_" + operationId;
- }
+ return sanitizeName(operationId);
+ }
- return camelize(sanitizeName(operationId));
+ @Override
+ public String toParamName(String name) {
+ return toVarName(name);
}
@Override
public Map postProcessOperationsWithModels(Map objs, List