mushroom-cli 1.2.0-alpha.19 → 1.2.0-alpha.20

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/README.md CHANGED
@@ -132,6 +132,20 @@ npx mushroom-cli parameters --no-check-update
132
132
 
133
133
  ## Version
134
134
 
135
+ ### 1.2.0-alpha.20
136
+
137
+ Improvement:
138
+
139
+ - gen-ts:
140
+ - generate description for fields in view
141
+ - gen-docs
142
+ - curl of custom method is missing header X-HTTP-Method-Override
143
+
144
+ Fixed bugs:
145
+
146
+ - gen csharp:
147
+ - wrong version in Info.cs
148
+
135
149
  ### 1.2.0-alpha.19
136
150
 
137
151
  Improvement:
package/dist/common.js CHANGED
@@ -1,6 +1,19 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
+ import { fileURLToPath } from 'url';
3
4
  import readlineSync from 'readline-sync';
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = path.dirname(__filename);
7
+ export function getPackageVersion() {
8
+ try {
9
+ const content = fs.readFileSync(path.join(__dirname, '../package.json')).toString();
10
+ const pkg = JSON.parse(content);
11
+ return pkg.version;
12
+ }
13
+ catch {
14
+ return '<!unable to get package version>';
15
+ }
16
+ }
4
17
  export function ensureFolder(path, isFolder) {
5
18
  const index = path.lastIndexOf('/');
6
19
  if (!isFolder && index <= 0) {
@@ -4427,6 +4427,7 @@ catch (Exception ex)
4427
4427
  <pre data-language="http">{{httpMethod}} {{rootUrlPath}}{{entityName}}s/{{httpMethod}}<span class="place-holder">?param1=value1&amp;param2=value2</span> HTTP/1.1
4428
4428
  Host: <span class="domain">{{domain}}</span>
4429
4429
  Content-Type: application/json<span style="display: {{tokenDisplay}}">
4430
+ X-HTTP-Method-Override: {{httpMethod}}
4430
4431
  Token: your token</span>
4431
4432
 
4432
4433
  <span class="place-holder">BODY DATA</span></pre>
@@ -4444,8 +4445,7 @@ GET {{rootUrlPath}}{{entityName}}s/{{httpMethod}}<span class="place-holder">?par
4444
4445
  Host: <span class="domain">{{domain}}</span>
4445
4446
  Content-Type: application/json
4446
4447
  X-HTTP-Method-Override: {{httpMethod}}<span style="display: {{tokenDisplay}}">
4447
- Token: your token</span></span>
4448
- </pre>
4448
+ Token: your token</span></span></pre>
4449
4449
  </div>
4450
4450
  </script>
4451
4451
  <script type="text/mushroom-docs-template" class="mushroom-docs-template" id="template-codeSnippets-generalAction-cURL">
@@ -4453,13 +4453,15 @@ Token: your token</span></span>
4453
4453
  cURL
4454
4454
  <pre data-language="cURL">curl -X {{httpMethod}} \
4455
4455
  '<span class="root-url">{{rootUrl}}</span>{{entityName}}s/{{httpMethod}}<span class="place-holder">?param1=value1&amp;param2=value2</span>' \
4456
- -H 'Content-Type: application/json' \ <span style="display: {{tokenDisplay}}">
4456
+ -H 'Content-Type: application/json' \
4457
+ -H 'X-HTTP-Method-Override: {{httpMethod}}' \<span style="display: {{tokenDisplay}}">
4457
4458
  -H 'Token: {<span>{</span>TOKEN}}' \</span>
4458
4459
  -d 'BODY DATA IF ANY'
4459
4460
  </pre>
4460
4461
  Shell
4461
4462
  <pre data-language="cURL">curl --request {{httpMethod}} \
4462
- --url '<span class="root-url">{{rootUrl}}</span>{{entityName}}s/{{httpMethod}}<span class="place-holder">?param1=value1&amp;param2=value2</span>' \<span style="display: {{tokenDisplay}}">
4463
+ --url '<span class="root-url">{{rootUrl}}</span>{{entityName}}s/{{httpMethod}}<span class="place-holder">?param1=value1&amp;param2=value2</span>' \
4464
+ --header 'X-HTTP-Method-Override: {{httpMethod}}' \<span style="display: {{tokenDisplay}}">
4463
4465
  --header 'Token: {<span>{</span>TOKEN}}' \</span>
4464
4466
  --data 'BODY DATA IF ANY'</pre>
4465
4467
  </div>
@@ -1,20 +1,6 @@
1
1
  import fs from 'fs';
2
- import path from 'path';
3
- import { fileURLToPath } from 'url';
4
2
  import * as common from '../common.js';
5
- const __filename = fileURLToPath(import.meta.url);
6
- const __dirname = path.dirname(__filename);
7
- function getPackageVersion() {
8
- try {
9
- const content = fs.readFileSync(path.join(__dirname, '../package.json')).toString();
10
- const pkg = JSON.parse(content);
11
- return pkg.version;
12
- }
13
- catch {
14
- return '<!unable to get package version>';
15
- }
16
- }
17
- const packageVersion = getPackageVersion();
3
+ const packageVersion = common.getPackageVersion();
18
4
  const newLine = '\n';
19
5
  const header = `// NOTE: Please do not modify this file
20
6
  // NOTE: Version and compatibility information: please see in Info.cs file
@@ -1,23 +1,10 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
- import { fileURLToPath } from 'url';
4
3
  import targz from 'targz';
5
4
  import * as common from '../common.js';
6
5
  import * as javascriptDriverGenerator from './gen-js-driver.js';
7
6
  import * as typescriptDriverGenerator from './gen-ts-driver.js';
8
- const __filename = fileURLToPath(import.meta.url);
9
- const __dirname = path.dirname(__filename);
10
- function getPackageVersion() {
11
- try {
12
- const content = fs.readFileSync(path.join(__dirname, '../package.json')).toString();
13
- const pkg = JSON.parse(content);
14
- return pkg.version;
15
- }
16
- catch {
17
- return '<!unable to get package version>';
18
- }
19
- }
20
- const packageVersion = getPackageVersion();
7
+ const packageVersion = common.getPackageVersion();
21
8
  function compressAsync(src, dest, folderName) {
22
9
  return new Promise((resolve, reject) => {
23
10
  const options = {
@@ -53,6 +53,15 @@ function getCSharpTypeFromMushroomType(type) {
53
53
  return 'any';
54
54
  }
55
55
  }
56
+ function generateDescription(description, ident = ' ') {
57
+ if (!description)
58
+ return '';
59
+ return `${ident}/**\n${ident} * ${description
60
+ .replace(/\r/g, '')
61
+ .split('\n')
62
+ .map((line) => (line.includes('*/') ? line.replace(/\*\//g, '* /') : line))
63
+ .join('\n' + ident + ' * ')}\n${ident} */\n`;
64
+ }
56
65
  function generateTypescriptClass(objectDefination, className, options) {
57
66
  let childrenCode = '';
58
67
  let code = `export interface ${className} {\n`;
@@ -60,10 +69,11 @@ function generateTypescriptClass(objectDefination, className, options) {
60
69
  const field = objectDefination[fieldName];
61
70
  if (!field)
62
71
  continue;
63
- if (field.description) {
64
- code += ` /**\n * ${field.description.replace(/\r/, '').split('\n').map(line => line.includes('*/') ? line.replace(/\*\//g, "* /") : line).join('\n * ')}\n */\n`;
65
- }
66
- const optionalMark = options?.checkRequired && (field.required || field.validation?.required) ? '' : '?';
72
+ code += generateDescription(field.description);
73
+ const optionalMark = options?.checkRequired &&
74
+ (field.required || field.validation?.required)
75
+ ? ''
76
+ : '?';
67
77
  const nullType = optionalMark ? ' | null' : '';
68
78
  if (field.type == 'object') {
69
79
  const fieldClassName = className + '_' + toTypeScriptClassName(fieldName);
@@ -71,14 +81,21 @@ function generateTypescriptClass(objectDefination, className, options) {
71
81
  childrenCode += generateTypescriptClass(field.fields ?? {}, fieldClassName, options);
72
82
  }
73
83
  else if (field.type == 'keyValue') {
74
- const valueNullType = options?.checkRequired && (field.values.required || field.values.validation?.required) ? '' : ' | null | undefined';
84
+ const valueNullType = options?.checkRequired &&
85
+ (field.values.required || field.values.validation?.required)
86
+ ? ''
87
+ : ' | null | undefined';
75
88
  if (field.values?.type == 'object') {
76
89
  const fieldClassName = className + '_' + toTypeScriptClassName(fieldName);
77
90
  code += ` ${fieldName}${optionalMark}: Record<string, ${fieldClassName}${valueNullType}>${nullType};\n`;
78
91
  childrenCode += generateTypescriptClass(field.values.fields ?? {}, fieldClassName, options);
79
92
  }
80
93
  else if (field.values?.type == 'array') {
81
- const itemNullType = options?.checkRequired && (field.values.items?.required || field.values.items?.validation?.required) ? '' : ' | null | undefined';
94
+ const itemNullType = options?.checkRequired &&
95
+ (field.values.items?.required ||
96
+ field.values.items?.validation?.required)
97
+ ? ''
98
+ : ' | null | undefined';
82
99
  if (field.values.items?.type == 'object') {
83
100
  const fieldClassName = className + '_' + toTypeScriptClassName(fieldName);
84
101
  code += ` ${fieldName}${optionalMark}: Record<string, Array<${fieldClassName}${itemNullType}>${valueNullType}>${nullType};\n`;
@@ -93,14 +110,21 @@ function generateTypescriptClass(objectDefination, className, options) {
93
110
  }
94
111
  }
95
112
  else if (field.type == 'array') {
96
- const itemNullType = options?.checkRequired && (field.items.required || field.items.validation?.required) ? '' : ' | null | undefined';
113
+ const itemNullType = options?.checkRequired &&
114
+ (field.items.required || field.items.validation?.required)
115
+ ? ''
116
+ : ' | null | undefined';
97
117
  if (field.items?.type == 'object') {
98
118
  const fieldClassName = className + '_' + toTypeScriptClassName(fieldName);
99
119
  code += ` ${fieldName}${optionalMark}: Array<${fieldClassName}${itemNullType}>${nullType};\n`;
100
120
  childrenCode += generateTypescriptClass(field.items.fields ?? {}, fieldClassName, options);
101
121
  }
102
122
  else if (field.items?.type == 'keyValue') {
103
- const valueNullType = options?.checkRequired && (field.items.values?.required || field.items.values?.validation?.required) ? '' : ' | null | undefined';
123
+ const valueNullType = options?.checkRequired &&
124
+ (field.items.values?.required ||
125
+ field.items.values?.validation?.required)
126
+ ? ''
127
+ : ' | null | undefined';
104
128
  if (field.items.values?.type == 'object') {
105
129
  const fieldClassName = className + '_' + toTypeScriptClassName(fieldName);
106
130
  code += ` ${fieldName}${optionalMark}: Array<Record<string, ${fieldClassName}${valueNullType}>${itemNullType}>${nullType};\n`;
@@ -125,7 +149,7 @@ function generateTypescriptClassFromViewParameters(parameters) {
125
149
  if (Array.isArray(parameters)) {
126
150
  return ('{\n' +
127
151
  parameters
128
- .map((p) => ` ${p.field}${p.validation?.required && p.defaultValue === undefined ? '' : '?'}: ${getCSharpTypeFromMushroomType(p.type || 'string')}${p.isArray ? '[]' : ''}${p.validation?.required && p.defaultValue === undefined ? '' : ' | null'};`)
152
+ .map((p) => `${generateDescription(p.description)} ${p.field}${p.validation?.required && p.defaultValue === undefined ? '' : '?'}: ${getCSharpTypeFromMushroomType(p.type || 'string')}${p.isArray ? '[]' : ''}${p.validation?.required && p.defaultValue === undefined ? '' : ' | null'};`)
129
153
  .join('\n') +
130
154
  '\n}');
131
155
  }
@@ -134,15 +158,27 @@ function generateTypescriptClassFromViewParameters(parameters) {
134
158
  function generateTopCustomClass(config, entityName, methodName, grantRole, postfix, code) {
135
159
  const isKeyValue = config.type == 'keyValue';
136
160
  const isArray = isKeyValue ? config.values?.type == 'array' : config.type == 'array';
137
- const fields = isKeyValue ? (isArray ? config.values?.items?.fields : config.values?.fields) : (isArray ? config.items?.fields : config.fields);
138
- const type = (isKeyValue ? (isArray ? config.values?.items?.type : config.values?.type) : (isArray ? config.items?.type : config.type)) ?? 'string';
161
+ const fields = isKeyValue
162
+ ? isArray
163
+ ? config.values?.items?.fields
164
+ : config.values?.fields
165
+ : isArray
166
+ ? config.items?.fields
167
+ : config.fields;
168
+ const type = (isKeyValue
169
+ ? isArray
170
+ ? config.values?.items?.type
171
+ : config.values?.type
172
+ : isArray
173
+ ? config.items?.type
174
+ : config.type) ?? 'string';
139
175
  let inputClassName;
140
176
  if (type == 'object') {
141
177
  if (fields) {
142
178
  const roleIndicator = grantRole ? '_' + toTypeScriptClassName(grantRole) + '_' : '';
143
179
  inputClassName = `${toTypeScriptClassName(entityName)}_${toTypeScriptClassName(methodName)}${roleIndicator}${postfix}`;
144
180
  code.classesCode += generateTypescriptClass(fields, inputClassName, {
145
- checkRequired: true
181
+ checkRequired: true,
146
182
  });
147
183
  }
148
184
  else {
@@ -151,19 +187,25 @@ function generateTopCustomClass(config, entityName, methodName, grantRole, postf
151
187
  }
152
188
  else
153
189
  inputClassName = getCSharpTypeFromMushroomType(type);
154
- return isKeyValue ? (isArray ? 'Record<string, ' + inputClassName + '[]>' : 'Record<string, ' + inputClassName + '>') : (isArray ? inputClassName + '[]' : inputClassName);
190
+ return isKeyValue
191
+ ? isArray
192
+ ? 'Record<string, ' + inputClassName + '[]>'
193
+ : 'Record<string, ' + inputClassName + '>'
194
+ : isArray
195
+ ? inputClassName + '[]'
196
+ : inputClassName;
155
197
  }
156
198
  function generateCustomMethodCode(entityName, actionName, actions) {
157
199
  const result = { classesCode: '', methodCode: '' };
158
200
  if (!actionName || !actionName.startsWith('_raw_http_method_') || !actions || !actions.length)
159
201
  return result;
160
- actions = actions.filter(action => action.enabled);
202
+ actions = actions.filter((action) => action.enabled);
161
203
  if (!actions.length)
162
204
  return result;
163
205
  const methodName = actionName.substring('_raw_http_method_'.length);
164
- let inputTypes = new Set();
165
- let outputTypes = new Set();
166
- actions.forEach(action => {
206
+ const inputTypes = new Set();
207
+ const outputTypes = new Set();
208
+ actions.forEach((action) => {
167
209
  const codeHintDelegator = action?.codeHint?.delegator;
168
210
  if (!codeHintDelegator)
169
211
  return;
@@ -175,7 +217,7 @@ function generateCustomMethodCode(entityName, actionName, actions) {
175
217
  outputTypes.add('any');
176
218
  }
177
219
  if (codeHintDelegator.param && codeHintDelegator.requestBody) {
178
- let paramClassName = generateTopCustomClass(codeHintDelegator.param, entityName, methodName, actions.length > 1 ? action.grant : '', 'ParamRequest', result);
220
+ const paramClassName = generateTopCustomClass(codeHintDelegator.param, entityName, methodName, actions.length > 1 ? action.grant : '', 'ParamRequest', result);
179
221
  const bodyClassName = generateTopCustomClass(codeHintDelegator.requestBody, entityName, methodName, actions.length > 1 ? action.grant : '', 'Request', result);
180
222
  inputTypes.add(`CustomMethodRequest<${paramClassName}, ${bodyClassName}>`);
181
223
  }
@@ -247,9 +289,7 @@ export interface CustomMethodBodyRequest<TBody> extends MushroomRequest {
247
289
  const typescriptClassName = toTypeScriptClassName(entityName);
248
290
  code += generateTypescriptClass(entity.fields, typescriptClassName);
249
291
  const actions = {};
250
- if (entity.description) {
251
- iApiClassBody += ` /**\n * ${entity.description.replace(/\r/, '').split('\n').map(line => line.includes('*/') ? line.replace(/\*\//g, "* /") : line).join('\n * ')}\n */\n`;
252
- }
292
+ iApiClassBody += generateDescription(entity.description);
253
293
  iApiClassBody += ` ${entityName}: MushroomResourceBase`;
254
294
  let customMethodCode = '';
255
295
  for (const actionName in entity.actions) {
package/dist/mr.js CHANGED
@@ -1,7 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import fs from 'fs';
3
- import path from 'path';
4
- import { fileURLToPath } from 'url';
5
2
  import * as common from './common.js';
6
3
  import init from './init.js';
7
4
  import config from './config.js';
@@ -10,19 +7,7 @@ import merge from './merge.js';
10
7
  import update from './update.js';
11
8
  import help from './help.js';
12
9
  import checkUpdate from './check-update.js';
13
- const __filename = fileURLToPath(import.meta.url);
14
- const __dirname = path.dirname(__filename);
15
- function getPackageVersion() {
16
- try {
17
- const content = fs.readFileSync(path.join(__dirname, '../package.json')).toString();
18
- const pkg = JSON.parse(content);
19
- return pkg.version;
20
- }
21
- catch {
22
- return '<!unable to get package version>';
23
- }
24
- }
25
- const packageVersion = getPackageVersion();
10
+ const packageVersion = common.getPackageVersion();
26
11
  const versionGroup = packageVersion.match(/([^-]+)(-(\w+).*)?/);
27
12
  const currentDistTag = versionGroup?.[3] ? versionGroup[3] : 'latest';
28
13
  common.logInfo('Mushroom CLI version', packageVersion);
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "mushroom-cli",
3
- "version": "1.2.0-alpha.19",
3
+ "version": "1.2.0-alpha.20",
4
4
  "description": "Mushroom CLI",
5
5
  "main": "dist/mr.js",
6
6
  "type": "module",
7
7
  "scripts": {
8
8
  "build": "tsc && copyfiles -u 2 ./src/docs/* ./dist/docs/",
9
- "format": "prettier --write **/*",
9
+ "format": "prettier --write --ignore-unknown **/*",
10
10
  "lint": "eslint ./src/**/*.ts",
11
11
  "release": "npm run build && npm publish --access public --tag alpha",
12
12
  "preinstall": "npx only-allow npm",