@suitegeezus/suitecloud-cli 3.1.6-1 → 3.1.6-3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DELTA.md +20 -14
- package/README.md +12 -17
- package/messages.json +1 -1
- package/package.json +1 -1
- package/src/ApplicationConstants.js +1 -0
- package/src/CLI.js +100 -70
- package/src/core/CommandActionExecutor.js +6 -16
- package/src/core/CommandRegistrationService.js +1 -1
- package/src/metadata/CommandGenerators.json +1 -1
- package/src/metadata/NodeCommandsMetadata.json +43 -20
- package/src/metadata/SdkCommandsMetadata.json +1 -0
- package/src/suitecloud.js +9 -1
package/DELTA.md
CHANGED
|
@@ -2,18 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
- binary name is `sdf` (not `suitecloud`)
|
|
4
4
|
- package name is `@suitegeezus/suitecloud-cli`
|
|
5
|
-
-
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
5
|
+
- hunts for a config file in the directory tree
|
|
6
|
+
- `package.json#configFile` can be used to set expected names of config files to hunt for
|
|
7
|
+
- environment variables while running:
|
|
8
|
+
- SUITECLOUD_AUTHID
|
|
9
|
+
- SUITECLOUD_PROJECT_FOLDER
|
|
10
|
+
- SUITECLOUD_PROJECT_PATH
|
|
11
|
+
- SUITECLOUD_PROJECT_ROOT
|
|
12
|
+
- SUITECLOUD_EXE
|
|
13
|
+
- `authid` option available on any command including in interactive
|
|
14
|
+
- `project` option available on any commands (to find resource files) including in interactive
|
|
15
|
+
- `config` option available on any command (to be exact about config file to use) including in interactive
|
|
16
|
+
- `noconfig` option available on any command including in interactive
|
|
17
|
+
- `customflag` option available on any command including in interactive
|
|
18
|
+
- `customoptions` option available on any command including in interactive
|
|
12
19
|
- `debug` option available on any command including in interactive
|
|
20
|
+
- `skiphooks` option available on any command including in interactive
|
|
13
21
|
|
|
14
22
|
<p align="left"><a href="#"><img width="250" src="resources/Netsuite-logo-ocean-150-bg.png"></a></p>
|
|
15
23
|
|
|
16
|
-
- It can coexist with the regular version. You can install both at the same time.
|
|
24
|
+
- It can coexist with the regular version. You can install both at the same time.
|
|
25
|
+
- But why.
|
|
17
26
|
- They will share account credentials and the underlying SDK. They will reference the same `~/.suitecloud-sdk` resource folder.
|
|
18
27
|
- Example, They can use different config files and not conflict with each other within the same project.
|
|
19
28
|
- By default, this uses `sdf.config.js`.
|
|
@@ -103,9 +112,7 @@ Note: this example does not require a config file
|
|
|
103
112
|
| [`account:setup`](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/article_89132630266.html) | Sets up an account to use with SuiteCloud SDK and configures the default auth ID for the SuiteCloud project. It requires browser-based login to NetSuite. |
|
|
104
113
|
| [`account:setup:ci`](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/article_81134826821.html) | Sets up an account to use with SuiteCloud SDK and configures the default auth ID for the SuiteCloud project. It does not require browser-based login to NetSuite. This command is helpful for automated environments such as CI. |
|
|
105
114
|
| `custom:hello` | A sanity command to check configuration. You can use hooks but you should leave it ias it is. |
|
|
106
|
-
| `custom:
|
|
107
|
-
| `custom:job` | Run pre-configured commands such as running admindocs queries. This also supports hooks |
|
|
108
|
-
| `custom:config` | Show location and contents of config file |
|
|
115
|
+
| `custom:hook` | A passthrough command that does nothing. You can build hooks for it |
|
|
109
116
|
| [`file:create`](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_162810635242.html) | Creates SuiteScript files in the selected folder using the correct template with SuiteScript modules injected. |
|
|
110
117
|
| [`file:import`](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_156041963273.html) | Imports files from an account to your account customization project. |
|
|
111
118
|
| [`file:list`](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_156042966488.html) | Lists the files in the File Cabinet of your account. |
|
|
@@ -149,7 +156,7 @@ sdf custom:config --show
|
|
|
149
156
|
|
|
150
157
|
#### Project Folder & Project Root
|
|
151
158
|
|
|
152
|
-
The projectFolder is not the location of the `sdf.config.js`. It can be anywhere on your file system, but typically it is the same directory or a subDirectory of the project. It can be overridden in some commands using the `--project` flag
|
|
159
|
+
The projectFolder is not necessarily the location of the `sdf.config.js`. It can be anywhere on your file system, but typically it is the same directory or a subDirectory of the project. It can be overridden in some commands using the `--project` flag
|
|
153
160
|
|
|
154
161
|
If the config (or command line override) specifies a value for `defaultProjectFolder` then that value is appended to the project root to determine the `projectFolder`. That location is expected to contain things such as:
|
|
155
162
|
|
|
@@ -162,8 +169,7 @@ If the config (or command line override) specifies a value for `defaultProjectFo
|
|
|
162
169
|
many `sdf` commands can run without any config file. You may need to provide additional command line flags in lieu.
|
|
163
170
|
|
|
164
171
|
There are some commands where a `manifest.xml` file or `deploy.xml` file is required in the discovered root, but the file isn't actually
|
|
165
|
-
|
|
166
|
-
TODO: use `--forceManifest` which will create a temporary `manifest.xml` file and then remove it when done.
|
|
172
|
+
used. In this case you could use the hook to detect this and create a dummy file and then remove it onCompleted.
|
|
167
173
|
|
|
168
174
|
Ranked from top priority to bottom priority
|
|
169
175
|
|
package/README.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
# SuiteCloud CLI for Node.js
|
|
4
4
|
<p>
|
|
5
|
-
<a href="https://www.npmjs.com/package/@
|
|
6
|
-
<img src="https://img.shields.io/npm/dm/@
|
|
7
|
-
<img src="https://img.shields.io/npm/v/@
|
|
5
|
+
<a href="https://www.npmjs.com/package/@suitegeezus/suitecloud-cli">
|
|
6
|
+
<img src="https://img.shields.io/npm/dm/@suitegeezus/suitecloud-cli.svg" alt="npm-cli"/>
|
|
7
|
+
<img src="https://img.shields.io/npm/v/@suitegeezus/suitecloud-cli.svg" alt="npm-cli"/>
|
|
8
8
|
</a>
|
|
9
9
|
</p>
|
|
10
10
|
|
|
@@ -19,35 +19,30 @@ The following software is required to work with SuiteCloud CLI for Node.js:
|
|
|
19
19
|
Read the full list of prerequisites in [SuiteCloud CLI for Node.js Installation Prerequisites](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_1558708810.html).
|
|
20
20
|
|
|
21
21
|
## Supported Versions
|
|
22
|
-
|
|
22
|
+
This is a fork of `@oracle/suitecloud-cli`. It supports older command lines but with a new binary `sdf`.
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
| CLI Versions Available in NPM |
|
|
27
|
-
|:-----------------------------:|
|
|
28
|
-
| 3.1.2 |
|
|
29
|
-
| 3.1.1 |
|
|
24
|
+
It is enhanced for easier customizing via hooks. See [./DELTA.md] for more
|
|
30
25
|
|
|
31
26
|
|
|
32
27
|
## Installation
|
|
33
28
|
Since CLI for Node.js is a development tool, use a global instance to install it by running the following command:
|
|
34
29
|
|
|
35
30
|
```
|
|
36
|
-
npm install -g @
|
|
31
|
+
npm install -g @suitegeezus/suitecloud-cli
|
|
37
32
|
```
|
|
38
33
|
When installing SuiteCloud CLI for Node.js via script, for instance in a CI environment, you can skip showing the license presented during the normal installation process by adding the --acceptSuiteCloudSDKLicense flag to the install script as shown below. Note that by adding the mentioned flag to the script, you confirm that you have read and accepted the Oracle Free Use Terms and Conditions license. See the [License](#license) section for details.
|
|
39
34
|
|
|
40
35
|
```
|
|
41
|
-
npm install -g --acceptSuiteCloudSDKLicense @
|
|
36
|
+
npm install -g --acceptSuiteCloudSDKLicense @suitegeezus/suitecloud-cli
|
|
42
37
|
```
|
|
43
38
|
|
|
44
39
|
|
|
45
|
-
CLI for Node.js is available from within any directory by running `
|
|
40
|
+
CLI for Node.js is available from within any directory by running `sdf`.
|
|
46
41
|
|
|
47
42
|
## Usage
|
|
48
43
|
CLI for Node.js uses the following syntax:
|
|
49
44
|
```
|
|
50
|
-
|
|
45
|
+
sdf <command> <option> <argument>
|
|
51
46
|
```
|
|
52
47
|
|
|
53
48
|
### Commands
|
|
@@ -71,7 +66,7 @@ suitecloud <command> <option> <argument>
|
|
|
71
66
|
|
|
72
67
|
To check the help for a specific command, run the following command:
|
|
73
68
|
```
|
|
74
|
-
|
|
69
|
+
sdf {command} -h
|
|
75
70
|
```
|
|
76
71
|
|
|
77
72
|
Read the detailed documentation for all the commands in [SuiteCloud CLI for Node.js Reference](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/chapter_155931263126.html).
|
|
@@ -84,12 +79,12 @@ Read the detailed documentation for all the commands in [SuiteCloud CLI for Node
|
|
|
84
79
|
|
|
85
80
|
Create a new project in an empty folder by running the following command:
|
|
86
81
|
```
|
|
87
|
-
|
|
82
|
+
sdf project:create -i
|
|
88
83
|
```
|
|
89
84
|
|
|
90
85
|
After you create a project, configure a NetSuite account, by running the following command within the project folder:
|
|
91
86
|
```
|
|
92
|
-
|
|
87
|
+
sdf account:setup
|
|
93
88
|
```
|
|
94
89
|
|
|
95
90
|
## Release Notes & Documentation
|
package/messages.json
CHANGED
|
@@ -259,7 +259,7 @@
|
|
|
259
259
|
"ERRORS_FILE": "There was an error in the file {0}: \n",
|
|
260
260
|
"ERRORS_FILE_NOT_EXIST": "The file {0} was not found in the project.",
|
|
261
261
|
"ERRORS_GENERAL_CONNECTION_PROBLEM": "There was an error when communicating with the server. Try again later.",
|
|
262
|
-
"ERRORS_INTERACTIVE_MODE_MORE_OPTIONS": "The '-i' option cannot be used in combination with
|
|
262
|
+
"ERRORS_INTERACTIVE_MODE_MORE_OPTIONS": "The '-i' option cannot be used in combination with certain options. Use either the '-i' option, or remove the non-interactive options you specified.",
|
|
263
263
|
"ERRORS_MISSING_DEFAULT_AUTH_ID": "The \"{0}\" property or \"{1}\" option is missing.",
|
|
264
264
|
"ERRORS_NO_OBJECTS": "There are no objects matching your search criteria. Select a different set of object types, and if applicable, check the specified application ID and script ID.",
|
|
265
265
|
"ERRORS_NOT_PROJECT_FOLDER": "No {0} file was found in {1}. Run \"{2}\" in a valid project folder.",
|
package/package.json
CHANGED
|
@@ -77,6 +77,7 @@ module.exports = {
|
|
|
77
77
|
SUITECLOUD_PROJECT_FOLDER: 'SUITECLOUD_PROJECT_FOLDER',
|
|
78
78
|
SUITECLOUD_PROJECT_PATH: 'SUITECLOUD_PROJECT_PATH',
|
|
79
79
|
SUITECLOUD_PROJECT_ROOT: 'SUITECLOUD_PROJECT_ROOT',
|
|
80
|
+
SUITECLOUD_EXE: 'SUITECLOUD_EXE'
|
|
80
81
|
},
|
|
81
82
|
HTTP_RESPONSE_CODE: {
|
|
82
83
|
UNAUTHORIZED: 401,
|
package/src/CLI.js
CHANGED
|
@@ -28,6 +28,87 @@ const HELP_COMMAND = 'help';
|
|
|
28
28
|
const HELP_OPTION = '--help';
|
|
29
29
|
const HELP_ALIAS = '-h';
|
|
30
30
|
const VERSION_OPTION = '--version';
|
|
31
|
+
const UBIQUITOUS_OPTIONS = {
|
|
32
|
+
"config": {
|
|
33
|
+
"name": "config",
|
|
34
|
+
"option": "config",
|
|
35
|
+
"description": "Specify a config file to use. Otherwise cli will discover closest config file",
|
|
36
|
+
"allowInteractive":true,
|
|
37
|
+
"mandatory": false,
|
|
38
|
+
"type": "SINGLE",
|
|
39
|
+
"usage": "\"./path/to/sdf.config.alt.js\"",
|
|
40
|
+
"defaultOption": false,
|
|
41
|
+
"disableInIntegrationMode": false,
|
|
42
|
+
"forceinclude": false,
|
|
43
|
+
"conflicts": ["noconfig"]
|
|
44
|
+
},
|
|
45
|
+
"noconfig": {
|
|
46
|
+
"name": "noconfig",
|
|
47
|
+
"option": "noconfig",
|
|
48
|
+
"description": "Do not use any config file",
|
|
49
|
+
"allowInteractive":true,
|
|
50
|
+
"mandatory": false,
|
|
51
|
+
"type": "FLAG",
|
|
52
|
+
"usage": "",
|
|
53
|
+
"forceinclude": true,
|
|
54
|
+
"defaultOption": false,
|
|
55
|
+
"disableInIntegrationMode": false,
|
|
56
|
+
"conflicts": ["config"]
|
|
57
|
+
},
|
|
58
|
+
"customflag": {
|
|
59
|
+
"name": "customflag",
|
|
60
|
+
"option": "customflag",
|
|
61
|
+
"description": "A custom boolean that will be passed into the hooks. Has no effect unless you implement the logic in a hook",
|
|
62
|
+
"allowInteractive":true,
|
|
63
|
+
"mandatory": false,
|
|
64
|
+
"type": "FLAG",
|
|
65
|
+
"usage": "",
|
|
66
|
+
"forceinclude": true,
|
|
67
|
+
"defaultOption": false,
|
|
68
|
+
"disableInIntegrationMode": false
|
|
69
|
+
},
|
|
70
|
+
"customoptions": {
|
|
71
|
+
"name": "customoptions",
|
|
72
|
+
"option": "customoptions",
|
|
73
|
+
"description": "Custom string values that will be passed into the hooks. Has no effect unless you implement the logic in a hook",
|
|
74
|
+
"allowInteractive":true,
|
|
75
|
+
"mandatory": false,
|
|
76
|
+
"type": "MULTIPLE",
|
|
77
|
+
"usage": "\"value1\" \"value2\"",
|
|
78
|
+
"forceinclude": true,
|
|
79
|
+
"defaultOption": undefined,
|
|
80
|
+
"disableInIntegrationMode": false
|
|
81
|
+
},
|
|
82
|
+
"debug": {
|
|
83
|
+
"name": "debug",
|
|
84
|
+
"option": "debug",
|
|
85
|
+
"description": "Directory to dump debug data for debugging. Creates a \"debug-{command}.json\" file in specified directory.\nUsage: \"--debug .\"",
|
|
86
|
+
"allowInteractive":true,
|
|
87
|
+
"mandatory": false,
|
|
88
|
+
"type": "SINGLE",
|
|
89
|
+
"usage": "--debug \"./tmpdir",
|
|
90
|
+
"forceinclude": true,
|
|
91
|
+
"defaultOption": false,
|
|
92
|
+
"disableInIntegrationMode": false
|
|
93
|
+
},
|
|
94
|
+
"skiphooks": {
|
|
95
|
+
"name": "skiphooks",
|
|
96
|
+
"option": "skiphooks",
|
|
97
|
+
"description": "Skip hook execution. Usage:\n" + [
|
|
98
|
+
'"--skiphooks all" (skip all)',
|
|
99
|
+
'"--skiphooks pre" (skip beforeExecuting)',
|
|
100
|
+
'"--skiphooks post" (skip onCompleted/onError)',
|
|
101
|
+
'"--skiphooks none" (skip nothing -- default)'
|
|
102
|
+
].join('\n'),
|
|
103
|
+
"allowInteractive":true,
|
|
104
|
+
"forceinclude": true,
|
|
105
|
+
"mandatory": false,
|
|
106
|
+
"type": "SINGLE",
|
|
107
|
+
"usage": "\"pre|post|all|none\"",
|
|
108
|
+
"defaultOption": "none",
|
|
109
|
+
"disableInIntegrationMode": false
|
|
110
|
+
}
|
|
111
|
+
};
|
|
31
112
|
|
|
32
113
|
module.exports = class CLI {
|
|
33
114
|
constructor(dependencies) {
|
|
@@ -76,7 +157,7 @@ module.exports = class CLI {
|
|
|
76
157
|
.option(
|
|
77
158
|
`${INTERACTIVE_ALIAS}, ${INTERACTIVE_OPTION}`,
|
|
78
159
|
NodeTranslationService.getMessage(INTERACTIVE_OPTION_DESCRIPTION),
|
|
79
|
-
this._validateInteractive
|
|
160
|
+
this._validateInteractive(commandMetadataList[thirdArgument].options)
|
|
80
161
|
)
|
|
81
162
|
.helpOption(`${HELP_ALIAS}, ${HELP_OPTION}`, NodeTranslationService.getMessage(COMMAND_OPTIONS.HELP))
|
|
82
163
|
.addHelpCommand(`${HELP_COMMAND} ${COMMAND_ALIAS}`, NodeTranslationService.getMessage(COMMAND_OPTIONS.HELP))
|
|
@@ -104,14 +185,26 @@ module.exports = class CLI {
|
|
|
104
185
|
return process.argv.includes(INTERACTIVE_ALIAS) || process.argv.includes(INTERACTIVE_OPTION);
|
|
105
186
|
}
|
|
106
187
|
|
|
107
|
-
_validateInteractive() {
|
|
188
|
+
_validateInteractive(additionalOptions) {
|
|
108
189
|
let additionalAllowed = 0;
|
|
190
|
+
const ubiquitousValuesThatAreInteractive = Object.values(UBIQUITOUS_OPTIONS)
|
|
191
|
+
.concat(Object.values(additionalOptions))
|
|
192
|
+
.filter((o)=>o.allowInteractive)
|
|
193
|
+
.map((o)=>({
|
|
194
|
+
name: o.name,
|
|
195
|
+
additionalAllowed: o.type === "SINGLE" ? 2 : 1
|
|
196
|
+
}))
|
|
109
197
|
process.argv.forEach((arg)=>{
|
|
110
|
-
|
|
198
|
+
const mactchingOption = ubiquitousValuesThatAreInteractive.find(
|
|
199
|
+
(o)=>(`--${o.name}` === arg)
|
|
200
|
+
);
|
|
201
|
+
additionalAllowed += mactchingOption?.additionalAllowed || 0;
|
|
111
202
|
});
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
203
|
+
return ()=> {
|
|
204
|
+
if (process.argv.length > (4 + additionalAllowed)) {
|
|
205
|
+
// There are more options apart from -i or --interactive
|
|
206
|
+
throw NodeTranslationService.getMessage(ERRORS.INTERACTIVE_MODE_MORE_OPTIONS);
|
|
207
|
+
}
|
|
115
208
|
}
|
|
116
209
|
}
|
|
117
210
|
|
|
@@ -121,70 +214,7 @@ module.exports = class CLI {
|
|
|
121
214
|
|
|
122
215
|
Object.assign(
|
|
123
216
|
commandMetadata.options,
|
|
124
|
-
|
|
125
|
-
"config": {
|
|
126
|
-
"name": "config",
|
|
127
|
-
"option": "config",
|
|
128
|
-
"description": "Specify a config file to use. Otherwise cli will discover closest config file",
|
|
129
|
-
"mandatory": false,
|
|
130
|
-
"type": "SINGLE",
|
|
131
|
-
"usage": "\"./path/to/sdf.config.alt.js\"",
|
|
132
|
-
"defaultOption": false,
|
|
133
|
-
"disableInIntegrationMode": false,
|
|
134
|
-
"conflicts": ["noconfig"]
|
|
135
|
-
},
|
|
136
|
-
"noconfig": {
|
|
137
|
-
"name": "noconfig",
|
|
138
|
-
"option": "noconfig",
|
|
139
|
-
"description": "Do not use any config file",
|
|
140
|
-
"mandatory": false,
|
|
141
|
-
"type": "FLAG",
|
|
142
|
-
"usage": "",
|
|
143
|
-
"defaultOption": false,
|
|
144
|
-
"disableInIntegrationMode": false,
|
|
145
|
-
"conflicts": ["config"]
|
|
146
|
-
},
|
|
147
|
-
"customflag": {
|
|
148
|
-
"name": "customflag",
|
|
149
|
-
"option": "customflag",
|
|
150
|
-
"description": "A custom boolean that will be passed into the hooks. Has no effect unless you implement the logic in a hook",
|
|
151
|
-
"mandatory": true,
|
|
152
|
-
"type": "FLAG",
|
|
153
|
-
"usage": "",
|
|
154
|
-
"defaultOption": false,
|
|
155
|
-
"disableInIntegrationMode": false
|
|
156
|
-
},
|
|
157
|
-
"customoptions": {
|
|
158
|
-
"name": "customoptions",
|
|
159
|
-
"option": "customoptions",
|
|
160
|
-
"description": "Custom string values that will be passed into the hooks. Has no effect unless you implement the logic in a hook",
|
|
161
|
-
"mandatory": false,
|
|
162
|
-
"type": "MULTIPLE",
|
|
163
|
-
"usage": "\"value1\" \"value2\"",
|
|
164
|
-
"defaultOption": false,
|
|
165
|
-
"disableInIntegrationMode": false
|
|
166
|
-
},
|
|
167
|
-
"debug": {
|
|
168
|
-
"name": "debug",
|
|
169
|
-
"option": "debug",
|
|
170
|
-
"description": "Directory to dump debug data for debugging. Creates a unique {command}.{datetime}.json file per run",
|
|
171
|
-
"mandatory": true,
|
|
172
|
-
"type": "SINGLE",
|
|
173
|
-
"usage": "\"./debug-output\"",
|
|
174
|
-
"defaultOption": false,
|
|
175
|
-
"disableInIntegrationMode": false
|
|
176
|
-
},
|
|
177
|
-
"skiphooks": {
|
|
178
|
-
"name": "skiphooks",
|
|
179
|
-
"option": "skiphooks",
|
|
180
|
-
"description": "Skip hook execution. Values: 'pre' (skip beforeExecuting), 'post' (skip onCompleted/onError), 'all' (skip all hooks)",
|
|
181
|
-
"mandatory": true,
|
|
182
|
-
"type": "SINGLE",
|
|
183
|
-
"usage": "\"pre|post|all|none\"",
|
|
184
|
-
"defaultOption": "none",
|
|
185
|
-
"disableInIntegrationMode": false
|
|
186
|
-
}
|
|
187
|
-
}
|
|
217
|
+
UBIQUITOUS_OPTIONS
|
|
188
218
|
);
|
|
189
219
|
});
|
|
190
220
|
}
|
|
@@ -32,6 +32,7 @@ module.exports = class CommandActionExecutor {
|
|
|
32
32
|
this._commandsMetadataService = dependencies.commandsMetadataService;
|
|
33
33
|
this._log = dependencies.log;
|
|
34
34
|
this._sdkPath = dependencies.sdkPath;
|
|
35
|
+
this._binaryName = dependencies.binaryName;
|
|
35
36
|
|
|
36
37
|
if (!dependencies.executionEnvironmentContext) {
|
|
37
38
|
this._executionEnvironmentContext = new ExecutionEnvironmentContext();
|
|
@@ -144,6 +145,7 @@ module.exports = class CommandActionExecutor {
|
|
|
144
145
|
process.env[ENV_VARS.SUITECLOUD_PROJECT_FOLDER] = projectFolder;
|
|
145
146
|
process.env[ENV_VARS.SUITECLOUD_PROJECT_PATH] = projectPath;
|
|
146
147
|
process.env[ENV_VARS.SUITECLOUD_PROJECT_ROOT] = this._executionPath;
|
|
148
|
+
process.env[ENV_VARS.SUITECLOUD_EXE] = this._binaryName;
|
|
147
149
|
// this might modified but we need the user's hooks to take advantage of their current values
|
|
148
150
|
process.env[ENV_VARS.SUITECLOUD_AUTHID] = authId;
|
|
149
151
|
const skipPre = skipHooks === 'pre' || skipHooks === 'all';
|
|
@@ -253,22 +255,10 @@ module.exports = class CommandActionExecutor {
|
|
|
253
255
|
const optionValues = {};
|
|
254
256
|
for (const optionId in options) {
|
|
255
257
|
const optionMeta = options[optionId];
|
|
256
|
-
// apply defaults first
|
|
257
258
|
if (options.hasOwnProperty(optionId)){
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
// don't set a value for boolean unless it is a FLAG type
|
|
262
|
-
break;
|
|
263
|
-
case (optionMeta?.type === "FLAG"):
|
|
264
|
-
optionValues[optionId] = Boolean(optionMeta.defaultOption)
|
|
265
|
-
break;
|
|
266
|
-
case !["undefined"].includes( typeof optionMeta?.defaultOption) && optionMeta?.type !== 'FLAG':
|
|
267
|
-
optionValues[optionId] = optionMeta.defaultOption;
|
|
268
|
-
break;
|
|
269
|
-
default:
|
|
270
|
-
break;
|
|
271
|
-
}
|
|
259
|
+
// apply defaults first when it is force include
|
|
260
|
+
if(optionMeta?.forceinclude) {
|
|
261
|
+
optionValues[optionId] = optionMeta.defaultOption
|
|
272
262
|
}
|
|
273
263
|
if(args.hasOwnProperty(optionId)) {
|
|
274
264
|
optionValues[optionId] = args[optionId];
|
|
@@ -323,7 +313,7 @@ module.exports = class CommandActionExecutor {
|
|
|
323
313
|
_getDebugFilePath(debugDir, commandName) {
|
|
324
314
|
if (!debugDir) return null;
|
|
325
315
|
const sanitizedCommandName = commandName.replace(/:/g, '-');
|
|
326
|
-
const filename =
|
|
316
|
+
const filename = `debug.${sanitizedCommandName}.json`;
|
|
327
317
|
return path.join(debugDir, filename);
|
|
328
318
|
}
|
|
329
319
|
|
|
@@ -65,7 +65,7 @@ module.exports = class CommandRegistrationService {
|
|
|
65
65
|
|
|
66
66
|
_addInteractiveCommandOptions(commandSetup,options){
|
|
67
67
|
const filteredOptions = Object.entries(options).filter(([key,o])=>{
|
|
68
|
-
|
|
68
|
+
if( o.allowInteractive ) return true;
|
|
69
69
|
});
|
|
70
70
|
filteredOptions.push(['interactive',{
|
|
71
71
|
"name": "interactive",
|
|
@@ -7,114 +7,137 @@
|
|
|
7
7
|
"isSetupRequired": false,
|
|
8
8
|
"forceInteractiveMode": false,
|
|
9
9
|
"options": {
|
|
10
|
+
"name": {
|
|
11
|
+
"name": "name",
|
|
12
|
+
"description": "The name of your hook for your own purposes.",
|
|
13
|
+
"allowInteractive": true,
|
|
14
|
+
"type": "SINGLE",
|
|
15
|
+
"mandatory": true,
|
|
16
|
+
"disableInIntegrationMode": false
|
|
17
|
+
},
|
|
10
18
|
"option1": {
|
|
11
19
|
"name": "option1",
|
|
12
|
-
|
|
20
|
+
"description": "Arbitrary value for your custom hook to recognize. Type is string",
|
|
21
|
+
"allowInteractive":true,
|
|
13
22
|
"type": "SINGLE",
|
|
14
23
|
"mandatory": false,
|
|
15
24
|
"disableInIntegrationMode": false
|
|
16
25
|
},
|
|
17
26
|
"option2": {
|
|
18
27
|
"name": "option2",
|
|
19
|
-
"description": "Arbitrary for your custom hook to recognize",
|
|
28
|
+
"description": "Arbitrary for your custom hook to recognize. Type is string",
|
|
29
|
+
"allowInteractive":true,
|
|
20
30
|
"type": "SINGLE",
|
|
21
31
|
"mandatory": false,
|
|
22
32
|
"disableInIntegrationMode": false
|
|
23
33
|
},
|
|
24
34
|
"option3": {
|
|
25
35
|
"name": "option3",
|
|
26
|
-
"description": "Arbitrary for your custom hook to recognize",
|
|
36
|
+
"description": "Arbitrary for your custom hook to recognize. Type is string",
|
|
37
|
+
"allowInteractive":true,
|
|
27
38
|
"type": "SINGLE",
|
|
28
39
|
"mandatory": false,
|
|
29
40
|
"disableInIntegrationMode": false
|
|
30
41
|
},
|
|
31
42
|
"option4": {
|
|
32
43
|
"name": "option4",
|
|
33
|
-
"description": "Arbitrary for your custom hook to recognize",
|
|
44
|
+
"description": "Arbitrary for your custom hook to recognize. Type is string",
|
|
45
|
+
"allowInteractive":true,
|
|
34
46
|
"type": "SINGLE",
|
|
35
47
|
"mandatory": false,
|
|
36
48
|
"disableInIntegrationMode": false
|
|
37
49
|
},
|
|
38
50
|
"option5": {
|
|
39
51
|
"name": "option5",
|
|
40
|
-
"description": "Arbitrary for your custom hook to recognize",
|
|
52
|
+
"description": "Arbitrary for your custom hook to recognize. Type is string",
|
|
53
|
+
"allowInteractive":true,
|
|
41
54
|
"type": "SINGLE",
|
|
42
55
|
"mandatory": false,
|
|
43
56
|
"disableInIntegrationMode": false
|
|
44
57
|
},
|
|
45
58
|
"multi1": {
|
|
46
59
|
"name": "multi1",
|
|
47
|
-
"description": "Arbitrary array for your custom hook to recognize",
|
|
60
|
+
"description": "Arbitrary array for your custom hook to recognize. Type is string[]",
|
|
48
61
|
"usage": "--multi1 a b c",
|
|
49
|
-
"type": "
|
|
62
|
+
"type": "MULTIPLE",
|
|
50
63
|
"mandatory": false,
|
|
51
64
|
"disableInIntegrationMode": false
|
|
52
65
|
},
|
|
53
66
|
"multi2": {
|
|
54
67
|
"name": "multi2",
|
|
55
|
-
"description": "Arbitrary array for your custom hook to recognize",
|
|
68
|
+
"description": "Arbitrary array for your custom hook to recognize. Type is string[]",
|
|
56
69
|
"usage": "--multi2 a b c",
|
|
57
|
-
"type": "
|
|
70
|
+
"type": "MULTIPLE",
|
|
58
71
|
"mandatory": false,
|
|
59
72
|
"disableInIntegrationMode": false
|
|
60
73
|
},
|
|
61
74
|
"multi3": {
|
|
62
75
|
"name": "multi3",
|
|
63
|
-
"description": "Arbitrary array for your custom hook to recognize",
|
|
76
|
+
"description": "Arbitrary array for your custom hook to recognize. Type is string[]",
|
|
64
77
|
"usage": "--multi3 a b c",
|
|
65
|
-
"type": "
|
|
78
|
+
"type": "MULTIPLE",
|
|
66
79
|
"mandatory": false,
|
|
67
80
|
"disableInIntegrationMode": false
|
|
68
81
|
},
|
|
69
82
|
"multi4": {
|
|
70
83
|
"name": "multi4",
|
|
71
|
-
"description": "Arbitrary array for your custom hook to recognize",
|
|
84
|
+
"description": "Arbitrary array for your custom hook to recognize. Type is string[]",
|
|
72
85
|
"usage": "--multi4 a b c",
|
|
73
|
-
"type": "
|
|
86
|
+
"type": "MULTIPLE",
|
|
74
87
|
"mandatory": false,
|
|
75
88
|
"disableInIntegrationMode": false
|
|
76
89
|
},
|
|
77
90
|
"multi5": {
|
|
78
91
|
"name": "multi5",
|
|
79
|
-
"description": "Arbitrary array for your custom hook to recognize",
|
|
92
|
+
"description": "Arbitrary array for your custom hook to recognize. Type is string[]",
|
|
80
93
|
"usage": "--multi5 a b c",
|
|
81
|
-
"type": "
|
|
94
|
+
"type": "MULTIPLE",
|
|
82
95
|
"mandatory": false,
|
|
83
96
|
"disableInIntegrationMode": false
|
|
84
97
|
},
|
|
85
98
|
"flag1": {
|
|
86
99
|
"name": "flag1",
|
|
87
|
-
"description": "Arbitrary on/off flag for your custom hook to use",
|
|
100
|
+
"description": "Arbitrary on/off flag for your custom hook to use. Type is boolean",
|
|
101
|
+
"allowInteractive":true,
|
|
88
102
|
"type": "FLAG",
|
|
89
103
|
"mandatory": false,
|
|
104
|
+
"defaultOption": false,
|
|
90
105
|
"disableInIntegrationMode": false
|
|
91
106
|
},
|
|
92
107
|
"flag2": {
|
|
93
108
|
"name": "flag2",
|
|
94
|
-
"description": "Arbitrary on/off flag for your custom hook to use",
|
|
109
|
+
"description": "Arbitrary on/off flag for your custom hook to use. Type is boolean",
|
|
110
|
+
"allowInteractive":true,
|
|
95
111
|
"type": "FLAG",
|
|
96
112
|
"mandatory": false,
|
|
113
|
+
"defaultOption": false,
|
|
97
114
|
"disableInIntegrationMode": false
|
|
98
115
|
},
|
|
99
116
|
"flag3": {
|
|
100
117
|
"name": "flag3",
|
|
101
|
-
"description": "Arbitrary on/off flag for your custom hook to use",
|
|
118
|
+
"description": "Arbitrary on/off flag for your custom hook to use. Type is boolean",
|
|
119
|
+
"allowInteractive":true,
|
|
102
120
|
"type": "FLAG",
|
|
103
121
|
"mandatory": false,
|
|
122
|
+
"defaultOption": false,
|
|
104
123
|
"disableInIntegrationMode": false
|
|
105
124
|
},
|
|
106
125
|
"flag4": {
|
|
107
126
|
"name": "flag4",
|
|
108
|
-
"description": "Arbitrary on/off flag for your custom hook to use",
|
|
127
|
+
"description": "Arbitrary on/off flag for your custom hook to use. Type is boolean",
|
|
128
|
+
"allowInteractive":true,
|
|
109
129
|
"type": "FLAG",
|
|
110
130
|
"mandatory": false,
|
|
131
|
+
"defaultOption": false,
|
|
111
132
|
"disableInIntegrationMode": false
|
|
112
133
|
},
|
|
113
134
|
"flag5": {
|
|
114
135
|
"name": "flag5",
|
|
115
|
-
"description": "Arbitrary on/off flag for your custom hook to use",
|
|
136
|
+
"description": "Arbitrary on/off flag for your custom hook to use. Type is boolean",
|
|
137
|
+
"allowInteractive":true,
|
|
116
138
|
"type": "FLAG",
|
|
117
139
|
"mandatory": false,
|
|
140
|
+
"defaultOption": false,
|
|
118
141
|
"disableInIntegrationMode": false
|
|
119
142
|
}
|
|
120
143
|
}
|
|
@@ -533,6 +533,7 @@
|
|
|
533
533
|
"option": "folder",
|
|
534
534
|
"description": "Specifies the File Cabinet path, for example, \"\/SuiteScripts\". All files within subfolders are included.",
|
|
535
535
|
"mandatory": true,
|
|
536
|
+
"allowInteractive": true,
|
|
536
537
|
"type": "SINGLE",
|
|
537
538
|
"usage": "\"\/SuiteScripts\"",
|
|
538
539
|
"defaultOption": true,
|
package/src/suitecloud.js
CHANGED
|
@@ -13,9 +13,16 @@ const CommandOptionsValidator = require('./core/CommandOptionsValidator');
|
|
|
13
13
|
const CLIConfigurationService = require('./core/extensibility/CLIConfigurationService');
|
|
14
14
|
const sdkPath = require('./core/sdksetup/SdkProperties').getSdkPath();
|
|
15
15
|
const NodeConsoleLogger = require('./loggers/NodeConsoleLogger');
|
|
16
|
+
const PACKAGE_FILE = `../package.json`;
|
|
16
17
|
|
|
17
18
|
const executionPath = process.cwd();
|
|
18
19
|
const commandsMetadataServiceSingleton = new CommandsMetadataService();
|
|
20
|
+
const getBinaryName = ()=>{
|
|
21
|
+
const configFile = require(PACKAGE_FILE);
|
|
22
|
+
return Object.entries(configFile.bin || {}).flatMap(
|
|
23
|
+
(k,v)=>(String(v).endsWith('suitecloud.js')? [k]: [])
|
|
24
|
+
).shift() || process.argv[1];
|
|
25
|
+
}
|
|
19
26
|
|
|
20
27
|
const cliInstance = new CLI({
|
|
21
28
|
commandsMetadataService: commandsMetadataServiceSingleton,
|
|
@@ -26,7 +33,8 @@ const cliInstance = new CLI({
|
|
|
26
33
|
cliConfigurationService: new CLIConfigurationService(),
|
|
27
34
|
commandsMetadataService: commandsMetadataServiceSingleton,
|
|
28
35
|
log: NodeConsoleLogger,
|
|
29
|
-
sdkPath: sdkPath
|
|
36
|
+
sdkPath: sdkPath,
|
|
37
|
+
binaryName: getBinaryName()
|
|
30
38
|
}),
|
|
31
39
|
});
|
|
32
40
|
|