mushroom-cli 1.0.14 → 1.1.0-alpha.1

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
@@ -24,7 +24,7 @@ Config gen database docs
24
24
 
25
25
  Config gen javascript driver
26
26
 
27
- npx mr config gen projectName js-driver ./src/api/mushroom.api.js [alias aliasName] [roles Admin,User-Contributor]
27
+ npx mr config gen projectName js-driver ./src/api/mushroom.api.js [alias aliasName] [roles Admin,User-Contributor] [tarball tarballName]
28
28
 
29
29
  Config gen entities for Mushroom project in CSharp and using MongoDb
30
30
 
package/config.js CHANGED
@@ -153,7 +153,6 @@ function configGenDatabaseDocs(args, mushroomConfig, projectName){
153
153
  }
154
154
 
155
155
  function configGenJavascriptDriver(args, mushroomConfig, projectName){
156
- console.log("a");
157
156
  const path = args[4];
158
157
  if (!path) {
159
158
  help(args);
@@ -166,6 +165,7 @@ function configGenJavascriptDriver(args, mushroomConfig, projectName){
166
165
  denyRoles: []
167
166
  };
168
167
  let alias = "default";
168
+ let tarball = undefined;
169
169
  while (index < args.length) {
170
170
  switch (args[index]) {
171
171
  case "roles":
@@ -188,6 +188,12 @@ function configGenJavascriptDriver(args, mushroomConfig, projectName){
188
188
  if (strAlias)
189
189
  alias = strAlias;
190
190
  break;
191
+ case "tarball":
192
+ index++;
193
+ const strTarball = args[index];
194
+ if (strTarball)
195
+ tarball = strTarball;
196
+ break;
191
197
  }
192
198
  index++;
193
199
  }
@@ -202,6 +208,60 @@ function configGenJavascriptDriver(args, mushroomConfig, projectName){
202
208
  projectAlias[key] = value;
203
209
  }
204
210
  }
211
+ projectAlias.tarballName = tarball;
212
+ projectAlias.output = path;
213
+ saveConfig(mushroomConfig, () => console.log(`Saved configuration of gen javascript driver for ${projectName}@${alias}`));
214
+ }
215
+
216
+ function configGenTypescriptDriver(args, mushroomConfig, projectName){
217
+ const path = args[4];
218
+ if (!path) {
219
+ help(args);
220
+ return;
221
+ }
222
+
223
+ let index = 5;
224
+ let parameters = {
225
+ allowRoles: ["*"],
226
+ denyRoles: []
227
+ };
228
+ let alias = "default";
229
+ while (index < args.length) {
230
+ switch (args[index]) {
231
+ case "roles":
232
+ index++;
233
+ const strRoles = args[index];
234
+ if (strRoles) {
235
+ const minusIndex = strRoles.indexOf("-");
236
+ let grantedRoles = minusIndex == -1 ? strRoles : strRoles.substr(0, minusIndex);
237
+ const deniedRoles = minusIndex == -1 ? "" : strRoles.substr(minusIndex + 1);
238
+ if (!grantedRoles)
239
+ grantedRoles = "*";
240
+ parameters.allowRoles = grantedRoles.split(",");
241
+ if (deniedRoles)
242
+ parameters.denyRoles = deniedRoles.split(",");
243
+ }
244
+ break;
245
+ case "alias":
246
+ index++;
247
+ const strAlias = args[index];
248
+ if (strAlias)
249
+ alias = strAlias;
250
+ break;
251
+ }
252
+ index++;
253
+ }
254
+
255
+ const project = mushroomConfig.projects[projectName];
256
+ project.tsDriver = project.tsDriver || {};
257
+ project.tsDriver.alias = project.tsDriver.alias || {};
258
+ const projectAlias = project.tsDriver.alias[alias] = project.tsDriver.alias[alias] || {};
259
+ for (const key in parameters) {
260
+ if (parameters.hasOwnProperty(key)) {
261
+ const value = parameters[key];
262
+ projectAlias[key] = value;
263
+ }
264
+ }
205
265
  projectAlias.output = path;
206
266
  saveConfig(mushroomConfig, () => console.log(`Saved configuration of gen javascript driver for ${projectName}@${alias}`));
207
267
  }
@@ -338,6 +398,9 @@ function configGen(args) {
338
398
  case "js-driver":
339
399
  configGenJavascriptDriver(args, mushroomConfig, projectName);
340
400
  break;
401
+ case "ts-driver":
402
+ configGenTypescriptDriver(args, mushroomConfig, projectName);
403
+ break;
341
404
  case "c#-mongo":
342
405
  configGenCSharpMongo(args, mushroomConfig, projectName);
343
406
  break;
@@ -97,6 +97,16 @@ async function genDocs(args, projectName, project, alias, source) {
97
97
 
98
98
  const entities = common.getEntities(source, aliasProject.allowRoles);
99
99
 
100
+ if (Array.isArray(aliasProject.entities)) {
101
+ for (const entityName in entities) {
102
+ if (Object.hasOwnProperty.call(entities, entityName)) {
103
+ if (aliasProject.entities.every(re => !new RegExp(re).test(entityName))){
104
+ delete entities[entityName];
105
+ }
106
+ }
107
+ }
108
+ }
109
+
100
110
  console.log('Fetching https://api.siten.vn/gen/docs.html');
101
111
  const html = await fetch('https://api.siten.vn/gen/docs.html').then(res => res.text());
102
112
  await processGenDocs(aliasProject, entities, source, html, args, projectName, alias);
package/gen/gen-csharp.js CHANGED
@@ -1,5 +1,6 @@
1
1
  const fs = require("fs");
2
2
  const common = require("../common.js");
3
+ const package = require("./../package.json");
3
4
 
4
5
  //#region shared function
5
6
  function singleLine(str) {
@@ -145,8 +146,17 @@ function generateCSharpClassMongoDb(source, className, fields, isRoot, descripti
145
146
  /// </summary>\r\n`;
146
147
  }
147
148
  var supperClass = "";
148
- if (isRoot)
149
- supperClass = " : Resource<" + getCSharpTypeFromMushroomType(source, fields.id ? fields.id.type : "AutoId", true) + ">";
149
+ if (isRoot) {
150
+ // thêm cho trường hợp không khai báo id hoặc id.type
151
+ if (!fields.id) {
152
+ fields.id = {
153
+ type: "AutoId"
154
+ };
155
+ }
156
+ if (!fields.id.type) fields.id.type = "AutoId";
157
+
158
+ supperClass = " : Mushroom.Models.IResource<" + getCSharpTypeFromMushroomType(source, fields.id.type, true) + ">";
159
+ }
150
160
  content += ` public class ${className}${supperClass}
151
161
  {
152
162
  `;
@@ -385,9 +395,9 @@ function genCSharpMongoDbClasses(args, projectName, project, alias, source) {
385
395
  .join("\r\n")
386
396
  : "";
387
397
 
388
- const code = `// This file was generated by Mushroom CLI (https://www.npmjs.com/package/mushroom-cli), please do not modify
398
+ const code = `// This file was generated by Mushroom CLI ${package.version} (https://www.npmjs.com/package/mushroom-cli), please do not modify
389
399
 
390
- // NOTE: Compatible with Mushroom Server version 0.2.15 or higher
400
+ // NOTE: Compatible with Mushroom Server version 0.2.18 or higher
391
401
 
392
402
  // ReSharper disable RedundantUsingDirective
393
403
  // ReSharper disable InconsistentNaming
@@ -413,17 +423,17 @@ namespace ${namespace}
413
423
  ${collectionNames}
414
424
  public static IMongoDatabase GetDatabase() => Mushroom.MushroomDaoFactory.GetDbAdapter() as IMongoDatabase;
415
425
 
416
- public static async System.Threading.Tasks.Task<T> FindByIdAsync<T, TId>(this IMongoCollection<T> collection, TId id) where T : Resource<TId>
426
+ public static async System.Threading.Tasks.Task<T> FindByIdAsync<T, TId>(this IMongoCollection<T> collection, TId id) where T : Mushroom.Models.IResource<TId>
417
427
  {
418
428
  return await (await collection.FindAsync(Builders<T>.Filter.Eq(doc => doc.Id, id))).FirstOrDefaultAsync();
419
429
  }
420
430
 
421
- public static async System.Threading.Tasks.Task<T> FindByIdAsync<T, TId>(this IMongoCollection<T> collection, TId id, FindOptions<T> findOptions) where T : Resource<TId>
431
+ public static async System.Threading.Tasks.Task<T> FindByIdAsync<T, TId>(this IMongoCollection<T> collection, TId id, FindOptions<T> findOptions) where T : Mushroom.Models.IResource<TId>
422
432
  {
423
433
  return await (await collection.FindAsync(Builders<T>.Filter.Eq(doc => doc.Id, id), findOptions)).FirstOrDefaultAsync();
424
434
  }
425
435
 
426
- public static async System.Threading.Tasks.Task<T> FindByIdAsync<T, TId>(this IMongoCollection<T> collection, TId id, ProjectionDefinition<T> projection) where T : Resource<TId>
436
+ public static async System.Threading.Tasks.Task<T> FindByIdAsync<T, TId>(this IMongoCollection<T> collection, TId id, ProjectionDefinition<T> projection) where T : Mushroom.Models.IResource<TId>
427
437
  {
428
438
  return await (await collection.FindAsync(Builders<T>.Filter.Eq(doc => doc.Id, id), new FindOptions<T> { Projection = projection })).FirstOrDefaultAsync();
429
439
  }
@@ -433,11 +443,6 @@ ${collectionNames}
433
443
  {
434
444
  ${resourceNames}
435
445
  }
436
-
437
- public interface Resource<T>
438
- {
439
- public T Id { get; set; }
440
- }
441
446
  }
442
447
 
443
448
  namespace ${namespace}.Resources
@@ -905,11 +910,8 @@ ${strEnumClasses}
905
910
 
906
911
  common.ensureFolder(aliasProject.output);
907
912
 
908
- fs.writeFile(aliasProject.output, code, err => {
909
- if (err)
910
- throw err;
911
- console.log(`Generated CSharp Driver for ${projectName}@${alias} to ${aliasProject.output}`);
912
- });
913
+ fs.writeFileSync(aliasProject.output, code);
914
+ console.log(`Generated CSharp Driver for ${projectName}@${alias} to ${aliasProject.output}`);
913
915
  }
914
916
  //#endregion
915
917
 
@@ -19,7 +19,7 @@ function getConstrains(valField) {
19
19
  const constraints = [];
20
20
 
21
21
  if (valField.reference)
22
- constraints.push(`Ref to ${valField.reference}`);
22
+ constraints.push(`Ref to <a href="#${valField.reference}">${encodeHtml(valField.reference)}</a>`);
23
23
 
24
24
  if (valField.validation) {
25
25
  if (valField.validation.required)
@@ -35,13 +35,13 @@ function getConstrains(valField) {
35
35
  if (valField.validation.maxLength !== undefined)
36
36
  constraints.push(`Max length: ${valField.validation.maxLength}`);
37
37
  if (valField.validation.gt !== undefined)
38
- constraints.push(`GT: ${valField.validation.gt}`);
38
+ constraints.push(`GT: ${encodeHtml(valField.validation.gt)}`);
39
39
  if (valField.validation.lt !== undefined)
40
- constraints.push(`LT: ${valField.validation.lt}`);
40
+ constraints.push(`LT: ${encodeHtml(valField.validation.lt)}`);
41
41
  if (valField.validation.min !== undefined)
42
- constraints.push(`Min: ${valField.validation.min}`);
42
+ constraints.push(`Min: ${encodeHtml(valField.validation.min)}`);
43
43
  if (valField.validation.max !== undefined)
44
- constraints.push(`Max: ${valField.validation.max}`);
44
+ constraints.push(`Max: ${encodeHtml(valField.validation.max)}`);
45
45
  if (valField.validation.pattern)
46
46
  constraints.push(`Pattern: ${encodeHtml(valField.validation.pattern)}`);
47
47
  }
@@ -83,7 +83,7 @@ function getMongoTableDocs(valTable) {
83
83
  <tr>
84
84
  <td valign="top">${keyField}</td>
85
85
  <td valign="top">${isArray ? "array of " + valField.items.type : valField.type}</td>
86
- <td valign="top">${getConstrains(valField)}</td>
86
+ <td valign="top">${getConstrains(valField)}${isArray ? "<hr/>Array items:<br/>" + getConstrains(valField.items) : ""}</td>
87
87
  <td valign="top" style="word-break: break-word">${encodeHtml(valField.description)}</td>
88
88
  </tr>`;
89
89
  }
@@ -103,7 +103,7 @@ function getMongoDbDocs(entities, source) {
103
103
  <div>${des}</div>
104
104
  ${getMongoTableDocs(valTable.fields)}
105
105
  <br>`;
106
- toc += `<li><a href="#${keyTable}"><b>${keyTable}</b></a> - ${des}</li>`;
106
+ toc += `<li><a href="#${keyTable}">${keyTable}</a> <span class="des">- ${des}</span></li>`;
107
107
  }
108
108
 
109
109
  return `
@@ -114,18 +114,57 @@ function getMongoDbDocs(entities, source) {
114
114
  <style>
115
115
  * {box-sizing: border-box}
116
116
  html, body {margin: 0 0; padding: 0 0; font-family: Calibri, 'helvetica neue', Arial, serifs}
117
+ h2{background-color: #ccc;margin: 30px -20px 0;padding: 5px 10px;}
118
+ hr{border-width: 0; border-top: 1px solid #ccc;}
117
119
  table {border-collapse: collapse;margin-top: 5px;}
118
- th{background-color: #ccc}
120
+ th{background-color: #d7d7d7}
119
121
  a{color: #000; text-decoration: none}
120
122
  a:hover{color: blue; text-decoration: underline}
121
- .paper{max-width: 11.69in; margin: 0 auto}
123
+
124
+ .nav{position: fixed; top: 0; left: 0; bottom: 0; width: 200px; z-index: 100; overflow: auto;border-right: 1px solid #bbb;background-color: #eee}
125
+ ul#nav-toc{padding: 0;margin: 0}
126
+ ul#nav-toc li{list-style: none;padding: 0;margin: 0;}
127
+ ul#nav-toc a{display: block;padding: 5px 10px;}
128
+ ul#nav-toc a:hover{background-color: #aaa; color: #fff; text-decoration: none}
129
+ ul#nav-toc .des{display: none}
130
+
131
+ :target {
132
+ -webkit-animation: target-fade 2s 1;
133
+ -moz-animation: target-fade 2s 1;
134
+ }
135
+
136
+ @-webkit-keyframes target-fade {
137
+ 0% { background-color: #ff0; }
138
+ 100% { background-color: #ccc; }
139
+ }
140
+ @-moz-keyframes target-fade {
141
+ 0% { background-color: #ff0; }
142
+ 100% { background-color: #ccc; }
143
+ }
144
+
145
+ body{padding-left: 200px}
146
+ .paper{padding: 0 20px}
147
+
148
+ ul#main-toc a{font-weight: bold}
149
+
150
+ @media print {
151
+ body{padding-left: 0}
152
+ .nav{display: none}
153
+ }
154
+ @media only screen and (max-width: 768px) {
155
+ body{padding-left: 0}
156
+ .nav{display: none}
157
+ }
122
158
  </style>
123
159
  <head>
124
160
  <body>
161
+ <div class="nav">
162
+ <ul id="nav-toc">${toc}</ul>
163
+ </div>
125
164
  <div class="paper">
126
165
  <h1 style="text-align: center">Đặc tả Cơ sở dữ liệu</h1>
127
166
  Hệ quản trị cơ sở dữ liệu: <b>${source.db}</b>
128
- <ul>${toc}</ul>
167
+ <ul id="main-toc">${toc}</ul>
129
168
  ${htmlStr}
130
169
  </div>
131
170
  </body>
@@ -176,11 +215,8 @@ function genDatabaseDocs(args, projectName, project, alias, source) {
176
215
 
177
216
  common.ensureFolder(aliasProject.output);
178
217
 
179
- fs.writeFile(aliasProject.output, code, err => {
180
- if (err)
181
- throw err;
182
- console.log(`Generated Database docs for ${projectName}@${alias} to ${aliasProject.output}`);
183
- });
218
+ fs.writeFileSync(aliasProject.output, code);
219
+ console.log(`Generated Database docs for ${projectName}@${alias} to ${aliasProject.output}`);
184
220
  }
185
221
 
186
222
  module.exports = genDatabaseDocs;
@@ -0,0 +1,89 @@
1
+ const fs = require("fs");
2
+ const path = require('path');
3
+ var targz = require('targz');
4
+ const javascriptDriverGenerator = require("./gen-js-driver");
5
+ const typescriptDriverGenerator = require("./gen-ts-driver");
6
+
7
+ function compressAsync(src, dest, folderName) {
8
+ return new Promise((resolve, reject) => {
9
+ const options = {
10
+ src: src,
11
+ dest: dest
12
+ };
13
+ if (folderName) {
14
+ options.tar = {
15
+ map: (header) => {
16
+ if (header.name === ".") return header;
17
+ header.name = folderName + '/' + header.name;
18
+ return header;
19
+ }
20
+ };
21
+ }
22
+
23
+ targz.compress(options, function(err){
24
+ if(err) {
25
+ reject(err);
26
+ return;
27
+ }
28
+ resolve();
29
+ });
30
+ });
31
+ }
32
+
33
+ async function genJavascriptDriverTarball(args, projectName, project, alias, source) {
34
+ const aliasProject = ((project.jsDriver || {}).alias || {})[alias];
35
+
36
+ let tarballName = aliasProject.tarballName ? aliasProject.tarballName : projectName;
37
+ tarballName = tarballName.toLowerCase().replace(/[^a-z-]/g, "-");
38
+
39
+ const dirPath = path.join(path.dirname(aliasProject.output), tarballName);
40
+ //const mainFileName = path.basename(aliasProject.output);
41
+ //const dtsFileName = mainFileName.replace(/\.js$/i, ".d.ts");
42
+
43
+ const packageContent = `{
44
+ "version": "1.0.${new Date().getTime()}",
45
+ "name": "${tarballName}",
46
+ "private": true,
47
+ "main": "${tarballName}.js",
48
+ "types": "${tarballName}.d.ts",
49
+ "dependencies": {
50
+ "mushroomjs": "^1.1.0-alpha.5"${Array.isArray(aliasProject.features) && aliasProject.features.includes("auth") ? ',\n "mushroomjs-auth": "^1.1.0-alpha.4"' : ""}${Array.isArray(aliasProject.features) && aliasProject.features.includes("file") ? ',\n "mushroomjs-file": "^1.1.0-alpha.1"' : ""}
51
+ }
52
+ }`;
53
+
54
+ if (fs.existsSync(dirPath)) {
55
+ console.log("Clean up tarball folder");
56
+ fs.rmdirSync(dirPath, { recursive: true });
57
+ }
58
+
59
+ const tarballFileName = path.join(path.dirname(aliasProject.output), tarballName + ".tar.gz");
60
+
61
+ if (fs.existsSync(tarballFileName)) {
62
+ console.log("Clean up old tarball file");
63
+ fs.unlinkSync(tarballFileName);
64
+ }
65
+
66
+ console.log("Creating tarball folder");
67
+
68
+ fs.mkdirSync(dirPath, { recursive: true, mode: 0755 });
69
+
70
+ console.log("Generating main file: " + tarballName + ".js");
71
+ let code = javascriptDriverGenerator.genJavascriptDriverString(aliasProject, source);
72
+ fs.writeFileSync(path.join(dirPath, tarballName + ".js"), code);
73
+
74
+ console.log("Generating types file: " + tarballName + ".d.ts");
75
+ code = typescriptDriverGenerator.genDtsString(aliasProject, source);
76
+ fs.writeFileSync(path.join(dirPath, tarballName + ".d.ts"), code);
77
+
78
+ console.log("Generating package file: package.json");
79
+ fs.writeFileSync(path.join(dirPath, "package.json"), packageContent);
80
+
81
+ console.log("Generating tarball file: " + tarballFileName);
82
+ await compressAsync(dirPath, tarballFileName, tarballName);
83
+
84
+ console.log("Generated tarball file");
85
+ fs.rmdirSync(dirPath, { recursive: true });
86
+ console.log("Cleaned up tarball folder");
87
+ }
88
+
89
+ module.exports = genJavascriptDriverTarball;
@@ -1,5 +1,6 @@
1
1
  const fs = require("fs");
2
2
  const common = require("../common.js");
3
+ const typescriptDriverGenerator = require("./gen-ts-driver");
3
4
 
4
5
  function isAllowCache(actions, defaultValue) {
5
6
  let result = defaultValue;
@@ -22,11 +23,9 @@ function isAllowCache(actions, defaultValue) {
22
23
  return result;
23
24
  }
24
25
 
25
- function genJavascriptDriver(args, projectName, project, alias, source) {
26
- const aliasProject = ((project.jsDriver || {}).alias || {})[alias];
27
-
26
+ function genJavascriptDriverString(aliasProject, source) {
28
27
  if (!aliasProject) {
29
- throw new Error(`Not found gen js-driver configuration. Please run 'npx mr config ${projectName} gen js-driver OUTPUT_FILE.js${alias === "default" ? "" : " alias " + alias}' first`);
28
+ return "";
30
29
  }
31
30
 
32
31
  const entities = common.getEntities(source, aliasProject.allowRoles);
@@ -66,15 +65,35 @@ const rootApiUrl = ${JSON.stringify(common.getRootUrl(source))};
66
65
  `;
67
66
  }
68
67
  code += `
69
- mushroom.$using(rootApiUrl);`;
68
+ mushroom.$using(rootApiUrl);
69
+
70
+ export default mushroom;`;
71
+
72
+ return code;
73
+ }
74
+
75
+ function genJavascriptDriver(args, projectName, project, alias, source) {
76
+ const aliasProject = ((project.jsDriver || {}).alias || {})[alias];
77
+
78
+ if (!aliasProject) {
79
+ throw new Error(`Not found gen js-driver configuration. Please run 'npx mr config gen ${projectName} js-driver OUTPUT_FILE.js${alias === "default" ? "" : " alias " + alias}' first`);
80
+ }
81
+
82
+ let code = genJavascriptDriverString(aliasProject, source);
70
83
 
71
84
  common.ensureFolder(aliasProject.output);
72
85
 
73
- fs.writeFile(aliasProject.output, code, err => {
74
- if (err)
75
- throw err;
76
- console.log(`Generated Javascript driver for ${projectName}@${alias} to ${aliasProject.output}`);
77
- });
86
+ fs.writeFileSync(aliasProject.output, code);
87
+ console.log(`Generated ${aliasProject.output}`);
88
+
89
+ code = typescriptDriverGenerator.genDtsString(aliasProject, source);
90
+ const dtsFilePath = aliasProject.output.replace(/\.js$/i, ".d.ts");
91
+ fs.writeFileSync(dtsFilePath, code);
92
+ console.log(`Generated ${dtsFilePath}`);
93
+ console.log(`Generated Javascript driver for ${projectName}@${alias}`);
78
94
  }
79
95
 
80
- module.exports = genJavascriptDriver;
96
+ module.exports = {
97
+ genJavascriptDriver,
98
+ genJavascriptDriverString
99
+ };
@@ -0,0 +1,405 @@
1
+ const fs = require("fs");
2
+ const common = require("../common.js");
3
+
4
+ function isAllowCache(actions, defaultValue) {
5
+ let result = defaultValue;
6
+ for (let i = 0; i < actions.length; i++) {
7
+ const action = actions[i];
8
+
9
+ if (!action ||
10
+ !action.cache ||
11
+ !action.cache.client ||
12
+ !action.cache.client.policy ||
13
+ action.cache.client.policy === "unset")
14
+ continue;
15
+
16
+ if (action.cache.client.policy === "disabled")
17
+ return false;
18
+
19
+ if (action.cache.client.policy === "allow" || action.cache.client.policy === "required")
20
+ result = true;
21
+ }
22
+ return result;
23
+ }
24
+
25
+ function toVietnameseNonTongue(str) {
26
+ const signText = "ăâđêôơưàảãạáằẳẵặắầẩẫậấèẻẽẹéềểễệếìỉĩịíòỏõọóồổỗộốờởỡợớùủũụúừửữựứỳỷỹỵýĂÂĐÐÊÔƠƯÀẢÃẠÁẰẲẴẶẮẦẨẪẬẤÈẺẼẸÉỀỂỄỆẾÌỈĨỊÍÒỎÕỌÓỒỔỖỘỐỜỞỠỢỚÙỦŨỤÚỪỬỮỰỨỲỶỸỴÝ";
27
+ const unsignedText = "aadeoouaaaaaaaaaaaaaaaeeeeeeeeeeiiiiiooooooooooooooouuuuuuuuuuyyyyyAADDEOOUAAAAAAAAAAAAAAAEEEEEEEEEEIIIIIOOOOOOOOOOOOOOOUUUUUUUUUUYYYYY";
28
+ var returnValue = "";
29
+ for (let i = 0; i < str.length; i++) {
30
+ const index = signText.indexOf(str.charAt(i));
31
+ returnValue += index !== -1 ? unsignedText.charAt(index) : str.charAt(i);
32
+ }
33
+ return returnValue;
34
+ }
35
+
36
+ function toTypeScriptClassName(str) {
37
+ if (!str)
38
+ return "_";
39
+ const name = toVietnameseNonTongue(str).replace(/\W/g, "_");
40
+ const c = name.charAt(0);
41
+ return ('0' <= c && c <= '9' ? '_' : "") + c.toUpperCase() + name.substr(1);
42
+ }
43
+
44
+ function getCSharpTypeFromMushroomType(type) {
45
+ switch (type) {
46
+ case "string":
47
+ return "string";
48
+ case "object":
49
+ case "array":
50
+ return "";
51
+ case "boolean":
52
+ return "boolean";
53
+ case "integer":
54
+ case "long":
55
+ case "double":
56
+ return "number";
57
+ case "datetime":
58
+ return "ISODateValue";
59
+ case "IdRef":
60
+ case "AutoId":
61
+ return "IdValue";
62
+ }
63
+ return "UNKNOWN_TYPE_" + type;
64
+ }
65
+
66
+ function generateTypescriptClass(objectDefination, indent) {
67
+ if (!indent) indent = "";
68
+ let code = "{\n";
69
+ for (let fieldName in objectDefination) {
70
+ if (objectDefination[fieldName].type == "object") {
71
+ code += `${indent} ${fieldName}?: ${generateTypescriptClass(objectDefination[fieldName].fields, indent + " ")},
72
+ `;
73
+ }
74
+ else if (objectDefination[fieldName].type == "array") {
75
+ if (objectDefination[fieldName].items.type == "object") {
76
+ code += `${indent} ${fieldName}?: ${generateTypescriptClass(objectDefination[fieldName].items.fields, indent + " ")}[],
77
+ `;
78
+ }
79
+ else {
80
+ code += `${indent} ${fieldName}?: ${getCSharpTypeFromMushroomType(objectDefination[fieldName].items.type)}[],
81
+ `;
82
+ }
83
+ }
84
+ else {
85
+ code += `${indent} ${fieldName}?: ${getCSharpTypeFromMushroomType(objectDefination[fieldName].type)},
86
+ `;
87
+ }
88
+ }
89
+ code += indent + "}";
90
+ return code;
91
+ }
92
+
93
+ function generateTypescriptClassFromViewParameters(parameters) {
94
+ if (Array.isArray(parameters)){
95
+ return '{\n' + parameters.map(p => ` ${p.field}?: ${getCSharpTypeFromMushroomType(p.type || "string")}${p.isArray ? "[]" : ""}`).join(',\n') + '\n}';
96
+ }
97
+ return '{}';
98
+ }
99
+
100
+ function genTypescriptDriverString(aliasProject, source) {
101
+ if (!aliasProject) {
102
+ return "";
103
+ }
104
+
105
+ const entities = common.getEntities(source, aliasProject.allowRoles);
106
+
107
+ let code = `import mushroom, { defineAsyncResource, defineAsyncView, fireEvent, createRestfulAsyncFunction, IdType, IMushroom, Mushroom, MushroomRequest, MushroomRequestSetting, MushroomRestfulRequest, MushroomResponse, MushroomResourceBase, MushroomListResource, MushroomFindByIdResource, MushroomCreateResource, MushroomBatchCreateResource, MushroomUpdateResource, MushroomBatchUpdateResource, MushroomPartialUpdateResource, MushroomDeleteResource, MushroomBatchDeleteResource, MushroomExtensibleResource, MushroomViewFunction, MushroomError } from "mushroomjs";
108
+ ${Array.isArray(aliasProject.features) && aliasProject.features.includes("auth") ? 'import { IMushroomAuth, useAuth, AuthLocalStorage } from "mushroomjs-auth";' : ""}
109
+ ${Array.isArray(aliasProject.features) && aliasProject.features.includes("file") ? 'import { IMushroomFile, useFile } from "mushroomjs-file";' : ""}
110
+
111
+ export type ISODateValue = string | Date;
112
+ export type IdValue = ${source.idType == "AutoIncInt" || source.idType == "AutoIncLong" ? "number" : "string"};
113
+
114
+ `;
115
+ let iApiClassBody = "";
116
+ for (let entityName in entities) {
117
+ if (!entities.hasOwnProperty(entityName))
118
+ continue;
119
+
120
+ const entity = entities[entityName];
121
+ const typescriptClassName = toTypeScriptClassName(entityName);
122
+ code += `interface ${typescriptClassName} ${generateTypescriptClass(entity.fields)};
123
+ `;
124
+
125
+
126
+ const actions = {};
127
+ iApiClassBody += ` ${entityName}: MushroomResourceBase`;
128
+ let customMethodCode = "";
129
+ for (const actionName in entity.actions) {
130
+ if (!entity.actions.hasOwnProperty(actionName))
131
+ continue;
132
+
133
+ actions[actionName] = {
134
+ clientCache: (actionName === "findById" || actionName === "findMany") && isAllowCache(entity.actions[actionName], true) ? true : undefined
135
+ };
136
+
137
+ switch (actionName) {
138
+ case "findMany": {
139
+ iApiClassBody += ` & MushroomListResource<${typescriptClassName}>`;
140
+ break;
141
+ }
142
+ case "findById": {
143
+ iApiClassBody += ` & MushroomFindByIdResource<${typescriptClassName}>`;
144
+ break;
145
+ }
146
+ case "createOne": {
147
+ iApiClassBody += ` & MushroomCreateResource<${typescriptClassName}>`;
148
+ break;
149
+ }
150
+ case "createMany": {
151
+ iApiClassBody += ` & MushroomBatchCreateResource<${typescriptClassName}>`;
152
+ break;
153
+ }
154
+ case "updateOne": {
155
+ iApiClassBody += ` & MushroomUpdateResource<${typescriptClassName}>`;
156
+ break;
157
+ }
158
+ case "updateMany": {
159
+ iApiClassBody += ` & MushroomBatchUpdateResource<${typescriptClassName}>`;
160
+ break;
161
+ }
162
+ case "updatePartially": {
163
+ iApiClassBody += ` & MushroomPartialUpdateResource<${typescriptClassName}>`;
164
+ break;
165
+ }
166
+ case "deleteOne": {
167
+ iApiClassBody += " & MushroomDeleteResource";
168
+ break;
169
+ }
170
+ case "deleteMany": {
171
+ iApiClassBody += " & MushroomBatchDeleteResource";
172
+ break;
173
+ }
174
+ default: {
175
+ if (actionName.indexOf("_raw_http_method_") === 0) {
176
+ customMethodCode += ` ${actionName.substr("_raw_http_method_".length)}Async: (rawRequest: MushroomRequest) => Promise<MushroomResponse<any>>,
177
+ `;
178
+ break;
179
+ }
180
+ else {
181
+ console.warn(`Unknown action name: ${entityName}.${actionName}`);
182
+ break;
183
+ }
184
+ }
185
+ }
186
+ }
187
+
188
+ if (customMethodCode) {
189
+ code += `interface ${typescriptClassName}$CustomMethodResource {
190
+ ${customMethodCode}}
191
+ `;
192
+ iApiClassBody += ` & ${typescriptClassName}$CustomMethodResource`;
193
+ }
194
+
195
+ const views = {};
196
+ let viewCode = "";
197
+ for (const viewName in entity.views) {
198
+ if (!entity.views.hasOwnProperty(viewName)) continue;
199
+
200
+ const viewRoles = entity.views[viewName];
201
+ if (!Array.isArray(viewRoles) || !viewRoles.length) continue;
202
+
203
+ views[viewName] = { clientCache: true };
204
+
205
+ const viewParameterTypes = viewRoles.map(view => {
206
+ const type = `${typescriptClassName}$ViewsResource_${viewName}View_${view.grant === "*" ? "" : toTypeScriptClassName(view.grant)}Parameters`;
207
+ code += `interface ${type} ${generateTypescriptClassFromViewParameters(view.parameters)};
208
+ `;
209
+ return `MushroomViewFunction<any, ${type}>`;
210
+ });
211
+ viewCode += `
212
+ ${viewName}Async: ${viewParameterTypes.join(' & ')},`;
213
+ }
214
+
215
+ if (viewCode) {
216
+ code += `interface ${typescriptClassName}$ViewsResource {
217
+ views: {${viewCode}
218
+ }
219
+ }
220
+ `;
221
+ iApiClassBody += ` & ${typescriptClassName}$ViewsResource`;
222
+ }
223
+
224
+ iApiClassBody +=`,
225
+ `;
226
+
227
+ code += `defineAsyncResource<${typescriptClassName}>(${JSON.stringify({ name: entityName, actions: actions, views: views })});
228
+
229
+ `;
230
+ }
231
+
232
+ code += `
233
+ ${Array.isArray(aliasProject.features) && aliasProject.features.includes("auth") ? "useAuth(AuthLocalStorage);" : ""}
234
+ ${Array.isArray(aliasProject.features) && aliasProject.features.includes("auth") ? "useFile();" : ""}
235
+ mushroom.$using(${JSON.stringify(common.getRootUrl(source))});
236
+
237
+ interface IApi extends IMushroom {
238
+ ${iApiClassBody}};
239
+
240
+ type Api = ${Array.isArray(aliasProject.features) && aliasProject.features.includes("auth") ? "IMushroomAuth & " : ""}${Array.isArray(aliasProject.features) && aliasProject.features.includes("file") ? "IMushroomFile & " : ""}IApi;
241
+
242
+ export default mushroom as Api;`;
243
+
244
+ return code;
245
+ }
246
+
247
+ function genDtsString(aliasProject, source) {
248
+ if (!aliasProject) {
249
+ return "";
250
+ }
251
+
252
+ const entities = common.getEntities(source, aliasProject.allowRoles);
253
+
254
+ let code = `import { IdType, IMushroom, Mushroom, MushroomRequest, MushroomRequestSetting, MushroomRestfulRequest, MushroomResponse, MushroomResourceBase, MushroomListResource, MushroomFindByIdResource, MushroomCreateResource, MushroomBatchCreateResource, MushroomUpdateResource, MushroomBatchUpdateResource, MushroomPartialUpdateResource, MushroomDeleteResource, MushroomBatchDeleteResource, MushroomExtensibleResource, MushroomViewFunction, MushroomError } from "mushroomjs";
255
+ ${Array.isArray(aliasProject.features) && aliasProject.features.includes("auth") ? 'import { IMushroomAuth } from "mushroomjs-auth";' : ""}
256
+ ${Array.isArray(aliasProject.features) && aliasProject.features.includes("file") ? 'import { IMushroomFile } from "mushroomjs-file";' : ""}
257
+
258
+ export declare type ISODateValue = string | Date;
259
+ export declare type IdValue = ${source.idType == "AutoIncInt" || source.idType == "AutoIncLong" ? "number" : "string"};
260
+
261
+ `;
262
+ let iApiClassBody = "";
263
+ for (let entityName in entities) {
264
+ if (!entities.hasOwnProperty(entityName))
265
+ continue;
266
+
267
+ const entity = entities[entityName];
268
+ const typescriptClassName = toTypeScriptClassName(entityName);
269
+ code += `interface ${typescriptClassName} ${generateTypescriptClass(entity.fields)};
270
+ `;
271
+
272
+
273
+ const actions = {};
274
+ iApiClassBody += ` ${entityName}: MushroomResourceBase`;
275
+ let customMethodCode = "";
276
+ for (const actionName in entity.actions) {
277
+ if (!entity.actions.hasOwnProperty(actionName))
278
+ continue;
279
+
280
+ actions[actionName] = {
281
+ clientCache: (actionName === "findById" || actionName === "findMany") && isAllowCache(entity.actions[actionName], true) ? true : undefined
282
+ };
283
+
284
+ switch (actionName) {
285
+ case "findMany": {
286
+ iApiClassBody += ` & MushroomListResource<${typescriptClassName}>`;
287
+ break;
288
+ }
289
+ case "findById": {
290
+ iApiClassBody += ` & MushroomFindByIdResource<${typescriptClassName}>`;
291
+ break;
292
+ }
293
+ case "createOne": {
294
+ iApiClassBody += ` & MushroomCreateResource<${typescriptClassName}>`;
295
+ break;
296
+ }
297
+ case "createMany": {
298
+ iApiClassBody += ` & MushroomBatchCreateResource<${typescriptClassName}>`;
299
+ break;
300
+ }
301
+ case "updateOne": {
302
+ iApiClassBody += ` & MushroomUpdateResource<${typescriptClassName}>`;
303
+ break;
304
+ }
305
+ case "updateMany": {
306
+ iApiClassBody += ` & MushroomBatchUpdateResource<${typescriptClassName}>`;
307
+ break;
308
+ }
309
+ case "updatePartially": {
310
+ iApiClassBody += ` & MushroomPartialUpdateResource<${typescriptClassName}>`;
311
+ break;
312
+ }
313
+ case "deleteOne": {
314
+ iApiClassBody += " & MushroomDeleteResource";
315
+ break;
316
+ }
317
+ case "deleteMany": {
318
+ iApiClassBody += " & MushroomBatchDeleteResource";
319
+ break;
320
+ }
321
+ default: {
322
+ if (actionName.indexOf("_raw_http_method_") === 0) {
323
+ customMethodCode += ` ${actionName.substr("_raw_http_method_".length)}Async: (rawRequest: MushroomRequest) => Promise<MushroomResponse<any>>,
324
+ `;
325
+ break;
326
+ }
327
+ else {
328
+ console.warn(`Unknown action name: ${entityName}.${actionName}`);
329
+ break;
330
+ }
331
+ }
332
+ }
333
+ }
334
+
335
+ if (customMethodCode) {
336
+ code += `interface ${typescriptClassName}$CustomMethodResource {
337
+ ${customMethodCode}}
338
+ `;
339
+ iApiClassBody += ` & ${typescriptClassName}$CustomMethodResource`;
340
+ }
341
+
342
+ const views = {};
343
+ let viewCode = "";
344
+ for (const viewName in entity.views) {
345
+ if (!entity.views.hasOwnProperty(viewName)) continue;
346
+
347
+ const viewRoles = entity.views[viewName];
348
+ if (!Array.isArray(viewRoles) || !viewRoles.length) continue;
349
+
350
+ views[viewName] = { clientCache: true };
351
+
352
+ const viewParameterTypes = viewRoles.map(view => {
353
+ const type = `${typescriptClassName}$ViewsResource_${viewName}View_${view.grant === "*" ? "" : toTypeScriptClassName(view.grant)}Parameters`;
354
+ code += `interface ${type} ${generateTypescriptClassFromViewParameters(view.parameters)};
355
+ `;
356
+ return `MushroomViewFunction<any, ${type}>`;
357
+ });
358
+ viewCode += `
359
+ ${viewName}Async: ${viewParameterTypes.join(' & ')},`;
360
+ }
361
+
362
+ if (viewCode) {
363
+ code += `interface ${typescriptClassName}$ViewsResource {
364
+ views: {${viewCode}
365
+ }
366
+ }
367
+ `;
368
+ iApiClassBody += ` & ${typescriptClassName}$ViewsResource`;
369
+ }
370
+
371
+ iApiClassBody +=`,
372
+ `;
373
+ }
374
+
375
+ code += `
376
+ interface IApi extends IMushroom {
377
+ ${iApiClassBody}};
378
+
379
+ declare type Api = ${Array.isArray(aliasProject.features) && aliasProject.features.includes("auth") ? "IMushroomAuth & " : ""}${Array.isArray(aliasProject.features) && aliasProject.features.includes("file") ? "IMushroomFile & " : ""}IApi;
380
+ declare const _default: Api;
381
+ export default _default;`;
382
+
383
+ return code;
384
+ }
385
+
386
+ function genTypescriptDriver(args, projectName, project, alias, source) {
387
+ const aliasProject = ((project.tsDriver || {}).alias || {})[alias];
388
+
389
+ if (!aliasProject) {
390
+ throw new Error(`Not found gen ts-driver configuration. Please run 'npx mr config gen ${projectName} ts-driver OUTPUT_FILE.ts${alias === "default" ? "" : " alias " + alias}' first`);
391
+ }
392
+
393
+ const code = genTypescriptDriverString(aliasProject, source);
394
+
395
+ common.ensureFolder(aliasProject.output);
396
+
397
+ fs.writeFileSync(aliasProject.output, code);
398
+ console.log(`Generated Typescript driver for ${projectName}@${alias} to ${aliasProject.output}`);
399
+ }
400
+
401
+ module.exports = {
402
+ genTypescriptDriver,
403
+ genTypescriptDriverString,
404
+ genDtsString
405
+ };
package/gen.js CHANGED
@@ -7,7 +7,9 @@ const masterFile = require("./master-file/master-file");
7
7
 
8
8
  const genApiDocs = require("./gen/gen-api-docs");
9
9
  const genDatabaseDocs = require("./gen/gen-db-docs");
10
- const genJavascriptDriver = require("./gen/gen-js-driver");
10
+ const javascriptDriverGenerator = require("./gen/gen-js-driver");
11
+ const genJavascriptDriverTarball = require("./gen/gen-js-driver-tarball");
12
+ const typescriptDriverGenerator = require("./gen/gen-ts-driver");
11
13
  const csharp = require("./gen/gen-csharp");
12
14
 
13
15
 
@@ -86,16 +88,22 @@ async function gen(args) {
86
88
  await genApiDocs(args, projectName, project, alias, source);
87
89
  break;
88
90
  case "db-docs":
89
- await genDatabaseDocs(args, projectName, project, alias, source);
91
+ genDatabaseDocs(args, projectName, project, alias, source);
90
92
  break;
91
93
  case "js-driver":
92
- await genJavascriptDriver(args, projectName, project, alias, source);
94
+ javascriptDriverGenerator.genJavascriptDriver(args, projectName, project, alias, source);
95
+ break;
96
+ case "js-driver-tarball":
97
+ await genJavascriptDriverTarball(args, projectName, project, alias, source);
98
+ break;
99
+ case "ts-driver":
100
+ typescriptDriverGenerator.genTypescriptDriver(args, projectName, project, alias, source);
93
101
  break;
94
102
  case "c#-mongo":
95
- await csharp.genCSharpMongoDbClasses(args, projectName, project, alias, source);
103
+ csharp.genCSharpMongoDbClasses(args, projectName, project, alias, source);
96
104
  break;
97
105
  case "c#-driver":
98
- await csharp.genCSharpDriver(args, projectName, project, alias, source);
106
+ csharp.genCSharpDriver(args, projectName, project, alias, source);
99
107
  break;
100
108
  case "":
101
109
  case undefined:
package/help.js CHANGED
@@ -31,7 +31,7 @@ Generate database docs (html format)
31
31
  npx mr gen projectName[@aliasName] db-docs [tmp]
32
32
 
33
33
  Config gen javascript driver
34
- npx mr config gen projectName js-driver ./src/api/mushroom.api.js [alias aliasName] [roles Admin,User-Contributor]
34
+ npx mr config gen projectName js-driver ./src/api/mushroom.api.js [alias aliasName] [roles Admin,User-Contributor] [tarball tarballName]
35
35
 
36
36
  Generate javascript driver
37
37
  npx mr gen projectName[@aliasName] js-driver
package/mr.js CHANGED
File without changes
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "mushroom-cli",
3
- "version": "1.0.14",
3
+ "version": "1.1.0-alpha.1",
4
4
  "description": "Mushroom CLI",
5
5
  "main": "mr.js",
6
6
  "scripts": {
7
- "publish": "npm publish --access public"
7
+ "release": "npm publish --access public --tag alpha"
8
8
  },
9
9
  "keywords": [
10
10
  "Mushroom",
@@ -21,6 +21,7 @@
21
21
  "json5": "^2.1.2",
22
22
  "node-fetch": "^2.6.0",
23
23
  "open": "^7.0.3",
24
- "readline-sync": "^1.4.10"
24
+ "readline-sync": "^1.4.10",
25
+ "targz": "^1.0.1"
25
26
  }
26
- }
27
+ }