mushroom-cli 1.0.15 → 1.1.0-alpha.10

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,11 @@ 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
+
29
+ Config gen typescript driver
30
+
31
+ npx mr config gen projectName ts-driver ./src/api/mushroom.api.ts [alias aliasName] [roles Admin,User-Contributor]
28
32
 
29
33
  Config gen entities for Mushroom project in CSharp and using MongoDb
30
34
 
@@ -44,10 +48,18 @@ Generate database docs (html format)
44
48
 
45
49
  npx mr gen projectName[@aliasName] db-docs [tmp]
46
50
 
51
+ Generate npm package (tarball file)
52
+
53
+ npx mr gen projectName[@aliasName] js-driver-tarball
54
+
47
55
  Generate javascript driver
48
56
 
49
57
  npx mr gen projectName[@aliasName] js-driver
50
58
 
59
+ Generate typescript driver
60
+
61
+ npx mr gen projectName[@aliasName] ts-driver
62
+
51
63
  Generate entities for Mushroom project in CSharp and using MongoDb
52
64
 
53
65
  npx mr gen projectName[@aliasName] c#-mongo
package/check-update.js CHANGED
@@ -2,7 +2,7 @@ const fetch = require('node-fetch');
2
2
 
3
3
 
4
4
  function checkUpdate() {
5
- return fetch('https://registry.npmjs.org/mushroom-cli/latest')
5
+ return fetch('https://registry.npmjs.org/mushroom-cli/')
6
6
  .then(res => res.json());
7
7
  }
8
8
 
package/config.js CHANGED
@@ -165,6 +165,7 @@ function configGenJavascriptDriver(args, mushroomConfig, projectName){
165
165
  denyRoles: []
166
166
  };
167
167
  let alias = "default";
168
+ let tarball = undefined;
168
169
  while (index < args.length) {
169
170
  switch (args[index]) {
170
171
  case "roles":
@@ -187,6 +188,12 @@ function configGenJavascriptDriver(args, mushroomConfig, projectName){
187
188
  if (strAlias)
188
189
  alias = strAlias;
189
190
  break;
191
+ case "tarball":
192
+ index++;
193
+ const strTarball = args[index];
194
+ if (strTarball)
195
+ tarball = strTarball;
196
+ break;
190
197
  }
191
198
  index++;
192
199
  }
@@ -201,6 +208,7 @@ function configGenJavascriptDriver(args, mushroomConfig, projectName){
201
208
  projectAlias[key] = value;
202
209
  }
203
210
  }
211
+ projectAlias.tarballName = tarball;
204
212
  projectAlias.output = path;
205
213
  saveConfig(mushroomConfig, () => console.log(`Saved configuration of gen javascript driver for ${projectName}@${alias}`));
206
214
  }
@@ -9,6 +9,8 @@ function processGenDocs(aliasProject, entities, source, html, args, projectName,
9
9
  console.log('Received html');
10
10
  console.log("Parsing html");
11
11
 
12
+ const roles = aliasProject.allowRoles.includes("*") ? source.roles : source.roles?.filter(r => aliasProject.allowRoles.includes(r.name));
13
+
12
14
  html = html.replace(/^\uFEFF/, '');
13
15
  html = html.replace(/<script src=(["'])\/\//g, "<script src=$1http://");
14
16
  html = html.replace("</body>", `<script data-mt-cond='{"x": 1}'>
@@ -16,9 +18,11 @@ function processGenDocs(aliasProject, entities, source, html, args, projectName,
16
18
  window.data.description = ${JSON.stringify(source.description)};
17
19
  window.data.rootUrl = ${JSON.stringify(common.getRootUrl(source))};
18
20
  window.data.environmentVariables = ${JSON.stringify(source.environmentVariables)};
21
+ window.data.roles = ${JSON.stringify(roles)};
19
22
  window.data.entities = ${JSON.stringify(entities)};
20
23
  window.data.features = ${JSON.stringify(aliasProject.features)};
21
- try{
24
+ try {
25
+ console.info("MUSHROOM-CLI: START");
22
26
  window.generateDocument();
23
27
  console.info("MUSHROOM-CLI: FINISH");
24
28
  }
@@ -31,6 +35,12 @@ function processGenDocs(aliasProject, entities, source, html, args, projectName,
31
35
  return new Promise((resolve, reject) => {
32
36
  const virtualConsole = new jsdom.VirtualConsole();
33
37
  virtualConsole.on("info", function(msg, err) {
38
+ if (typeof msg != "string") return;
39
+
40
+ if (msg.indexOf("MUSHROOM-CLI:") === 0) {
41
+ console.log("GenDocEngine:" + msg.substr("MUSHROOM-CLI:".length));
42
+ }
43
+
34
44
  if (msg === "MUSHROOM-CLI: FAIL"){
35
45
  dom = null;
36
46
  reject(err);
@@ -97,6 +107,16 @@ async function genDocs(args, projectName, project, alias, source) {
97
107
 
98
108
  const entities = common.getEntities(source, aliasProject.allowRoles);
99
109
 
110
+ if (Array.isArray(aliasProject.entities)) {
111
+ for (const entityName in entities) {
112
+ if (Object.hasOwnProperty.call(entities, entityName)) {
113
+ if (aliasProject.entities.every(re => !new RegExp(re).test(entityName))){
114
+ delete entities[entityName];
115
+ }
116
+ }
117
+ }
118
+ }
119
+
100
120
  console.log('Fetching https://api.siten.vn/gen/docs.html');
101
121
  const html = await fetch('https://api.siten.vn/gen/docs.html').then(res => res.text());
102
122
  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
 
@@ -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
  }
@@ -115,6 +115,7 @@ function getMongoDbDocs(entities, source) {
115
115
  * {box-sizing: border-box}
116
116
  html, body {margin: 0 0; padding: 0 0; font-family: Calibri, 'helvetica neue', Arial, serifs}
117
117
  h2{background-color: #ccc;margin: 30px -20px 0;padding: 5px 10px;}
118
+ hr{border-width: 0; border-top: 1px solid #ccc;}
118
119
  table {border-collapse: collapse;margin-top: 5px;}
119
120
  th{background-color: #d7d7d7}
120
121
  a{color: #000; text-decoration: none}
@@ -214,11 +215,8 @@ function genDatabaseDocs(args, projectName, project, alias, source) {
214
215
 
215
216
  common.ensureFolder(aliasProject.output);
216
217
 
217
- fs.writeFile(aliasProject.output, code, err => {
218
- if (err)
219
- throw err;
220
- console.log(`Generated Database docs for ${projectName}@${alias} to ${aliasProject.output}`);
221
- });
218
+ fs.writeFileSync(aliasProject.output, code);
219
+ console.log(`Generated Database docs for ${projectName}@${alias} to ${aliasProject.output}`);
222
220
  }
223
221
 
224
222
  module.exports = genDatabaseDocs;
@@ -0,0 +1,99 @@
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
+ const package = require("./../package.json");
7
+
8
+ function compressAsync(src, dest, folderName) {
9
+ return new Promise((resolve, reject) => {
10
+ const options = {
11
+ src: src,
12
+ dest: dest
13
+ };
14
+ if (folderName) {
15
+ options.tar = {
16
+ map: (header) => {
17
+ if (header.name === ".") return header;
18
+ header.name = folderName + '/' + header.name;
19
+ return header;
20
+ }
21
+ };
22
+ }
23
+
24
+ targz.compress(options, function(err){
25
+ if(err) {
26
+ reject(err);
27
+ return;
28
+ }
29
+ resolve();
30
+ });
31
+ });
32
+ }
33
+
34
+ async function genJavascriptDriverTarball(args, projectName, project, alias, source) {
35
+ const aliasProject = ((project.jsDriver || {}).alias || {})[alias];
36
+
37
+ let tarballName = aliasProject.tarballName ? aliasProject.tarballName : projectName;
38
+ tarballName = tarballName.toLowerCase().replace(/[^a-z-]/g, "-");
39
+
40
+ const dirPath = path.join(path.dirname(aliasProject.output), tarballName);
41
+
42
+ const versionGroup = package.version.match(/([^-]+)(-(\w+).*)?/);
43
+ const currentDistTag = versionGroup[3] ? versionGroup[3] : "latest";
44
+
45
+ const dependencies = [`"mushroomjs": "${currentDistTag}"`];
46
+ if (Array.isArray(aliasProject.features) && aliasProject.features.includes("auth")) {
47
+ dependencies.push(`"mushroomjs-auth": "${currentDistTag}"`);
48
+ }
49
+ if (Array.isArray(aliasProject.features) && aliasProject.features.includes("file")) {
50
+ dependencies.push(`"mushroomjs-file": "${currentDistTag}"`);
51
+ }
52
+
53
+ const packageContent = `{
54
+ "version": "1.0.${new Date().getTime()}",
55
+ "name": "${tarballName}",
56
+ "private": true,
57
+ "main": "${tarballName}.js",
58
+ "types": "${tarballName}.d.ts",
59
+ "dependencies": {
60
+ ${dependencies.join(',\n ')}
61
+ }
62
+ }`;
63
+
64
+ if (fs.existsSync(dirPath)) {
65
+ console.log("Clean up tarball folder");
66
+ fs.rmdirSync(dirPath, { recursive: true });
67
+ }
68
+
69
+ const tarballFileName = path.join(path.dirname(aliasProject.output), tarballName + ".tar.gz");
70
+
71
+ if (fs.existsSync(tarballFileName)) {
72
+ console.log("Clean up old tarball file");
73
+ fs.unlinkSync(tarballFileName);
74
+ }
75
+
76
+ console.log("Creating tarball folder");
77
+
78
+ fs.mkdirSync(dirPath, { recursive: true, mode: 0755 });
79
+
80
+ console.log("Generating main file: " + tarballName + ".js");
81
+ let code = javascriptDriverGenerator.genJavascriptDriverString(aliasProject, source);
82
+ fs.writeFileSync(path.join(dirPath, tarballName + ".js"), code);
83
+
84
+ console.log("Generating types file: " + tarballName + ".d.ts");
85
+ code = typescriptDriverGenerator.genDtsString(aliasProject, source);
86
+ fs.writeFileSync(path.join(dirPath, tarballName + ".d.ts"), code);
87
+
88
+ console.log("Generating package file: package.json");
89
+ fs.writeFileSync(path.join(dirPath, "package.json"), packageContent);
90
+
91
+ console.log("Generating tarball file: " + tarballFileName);
92
+ await compressAsync(dirPath, tarballFileName, tarballName);
93
+
94
+ console.log("Generated tarball file");
95
+ fs.rmdirSync(dirPath, { recursive: true });
96
+ console.log("Cleaned up tarball folder");
97
+ }
98
+
99
+ 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,21 +23,38 @@ 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 gen ${projectName} 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);
33
32
 
34
- let code = `import mushroom from "mushroomjs";
33
+ let extensionsImportLines = [];
34
+ let extensionsExportLines = [];
35
+ let extensionsCodeLines = [];
35
36
 
36
- "use strict";
37
+ if (Array.isArray(aliasProject.features)) {
38
+ if (aliasProject.features.includes("auth")) {
39
+ extensionsImportLines.push('import * as AuthExtension from "mushroomjs-auth";');
40
+ extensionsExportLines.push('Auth: AuthExtension');
41
+ extensionsCodeLines.push("AuthExtension.useAuth(AuthExtension.AuthLocalStorage);");
42
+ }
43
+ if (aliasProject.features.includes("file")) {
44
+ extensionsImportLines.push('import * as FileExtension from "mushroomjs-file";');
45
+ extensionsExportLines.push('File: FileExtension');
46
+ extensionsCodeLines.push("FileExtension.useFile();");
47
+ }
48
+ }
37
49
 
50
+ let code = `import mushroom, {defineAsyncResource} from "mushroomjs";
51
+ export * from "mushroomjs";
52
+ ${extensionsImportLines.join("\n")}
53
+ export const extensions = {
54
+ ${extensionsExportLines.join(",\n ")}
55
+ };
38
56
 
39
- const rootApiUrl = ${JSON.stringify(common.getRootUrl(source))};
57
+ "use strict";
40
58
 
41
59
  `;
42
60
  for (let entityName in entities) {
@@ -62,19 +80,41 @@ const rootApiUrl = ${JSON.stringify(common.getRootUrl(source))};
62
80
 
63
81
  views[viewName] = {};
64
82
  }
65
- code += `mushroom._defineAsyncResource({name:${JSON.stringify(entityName)},actions:${JSON.stringify(actions)},views:${JSON.stringify(views)}});
83
+ code += `defineAsyncResource({name:${JSON.stringify(entityName)},actions:${JSON.stringify(actions)},views:${JSON.stringify(views)}});
66
84
  `;
67
85
  }
68
86
  code += `
69
- mushroom.$using(rootApiUrl);`;
87
+ mushroom.$using(${JSON.stringify(common.getRootUrl(source))});
88
+
89
+ ${extensionsCodeLines.join('\n')}
90
+
91
+ export default mushroom;`;
92
+
93
+ return code;
94
+ }
95
+
96
+ function genJavascriptDriver(args, projectName, project, alias, source) {
97
+ const aliasProject = ((project.jsDriver || {}).alias || {})[alias];
98
+
99
+ if (!aliasProject) {
100
+ 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`);
101
+ }
102
+
103
+ let code = genJavascriptDriverString(aliasProject, source);
70
104
 
71
105
  common.ensureFolder(aliasProject.output);
72
106
 
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
- });
107
+ fs.writeFileSync(aliasProject.output, code);
108
+ console.log(`Generated ${aliasProject.output}`);
109
+
110
+ code = typescriptDriverGenerator.genDtsString(aliasProject, source);
111
+ const dtsFilePath = aliasProject.output.replace(/\.js$/i, ".d.ts");
112
+ fs.writeFileSync(dtsFilePath, code);
113
+ console.log(`Generated ${dtsFilePath}`);
114
+ console.log(`Generated Javascript driver for ${projectName}@${alias}`);
78
115
  }
79
116
 
80
- module.exports = genJavascriptDriver;
117
+ module.exports = {
118
+ genJavascriptDriver,
119
+ genJavascriptDriverString
120
+ };
@@ -90,32 +90,65 @@ function generateTypescriptClass(objectDefination, indent) {
90
90
  return code;
91
91
  }
92
92
 
93
- function genTypescriptDriver(args, projectName, project, alias, source) {
94
- const aliasProject = ((project.tsDriver || {}).alias || {})[alias];
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
+ }
95
99
 
100
+ function genTypescriptDriverString(aliasProject, source) {
96
101
  if (!aliasProject) {
97
- 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`);
102
+ return "";
98
103
  }
99
104
 
100
105
  const entities = common.getEntities(source, aliasProject.allowRoles);
101
106
 
102
- 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, MushroomError } from "mushroomjs";
107
+ let extensionsImportLines = [];
108
+ let extensionsExportLines = [];
109
+ let extensionsTypes = [];
110
+ let extensionsCodeLines = [];
111
+
112
+ if (Array.isArray(aliasProject.features)) {
113
+ if (aliasProject.features.includes("auth")) {
114
+ extensionsImportLines.push('import * as AuthExtension from "mushroomjs-auth";');
115
+ extensionsExportLines.push('File: FileExtension');
116
+ extensionsTypes.push("AuthExtension.IMushroomAuth & ");
117
+ extensionsCodeLines.push("AuthExtension.useAuth(AuthExtension.AuthLocalStorage);");
118
+ }
119
+ if (aliasProject.features.includes("file")) {
120
+ extensionsImportLines.push('import * as FileExtension from "mushroomjs-file";');
121
+ extensionsExportLines.push('Auth: AuthExtension');
122
+ extensionsTypes.push("FileExtension.IMushroomFile & ");
123
+ extensionsCodeLines.push("FileExtension.useFile();");
124
+ }
125
+ }
126
+
127
+ 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";
128
+ export * from "mushroomjs";
129
+ ${extensionsImportLines.join("\n")}
130
+ export const extensions = {
131
+ ${extensionsExportLines.join(",\n ")}
132
+ };
103
133
 
104
134
  export type ISODateValue = string | Date;
105
135
  export type IdValue = ${source.idType == "AutoIncInt" || source.idType == "AutoIncLong" ? "number" : "string"};
106
136
 
107
137
  `;
138
+ let iApiClassBody = "";
108
139
  for (let entityName in entities) {
109
140
  if (!entities.hasOwnProperty(entityName))
110
141
  continue;
111
142
 
112
143
  const entity = entities[entityName];
113
-
114
- code += `interface ${toTypeScriptClassName(entityName)} ${generateTypescriptClass(entity.fields)}
144
+ const typescriptClassName = toTypeScriptClassName(entityName);
145
+ code += `export interface ${typescriptClassName} ${generateTypescriptClass(entity.fields)};
115
146
  `;
116
147
 
117
148
 
118
149
  const actions = {};
150
+ iApiClassBody += ` ${entityName}: MushroomResourceBase`;
151
+ let customMethodCode = "";
119
152
  for (const actionName in entity.actions) {
120
153
  if (!entity.actions.hasOwnProperty(actionName))
121
154
  continue;
@@ -123,29 +156,293 @@ export type IdValue = ${source.idType == "AutoIncInt" || source.idType == "AutoI
123
156
  actions[actionName] = {
124
157
  clientCache: (actionName === "findById" || actionName === "findMany") && isAllowCache(entity.actions[actionName], true) ? true : undefined
125
158
  };
159
+
160
+ switch (actionName) {
161
+ case "findMany": {
162
+ iApiClassBody += ` & MushroomListResource<${typescriptClassName}>`;
163
+ break;
164
+ }
165
+ case "findById": {
166
+ iApiClassBody += ` & MushroomFindByIdResource<${typescriptClassName}>`;
167
+ break;
168
+ }
169
+ case "createOne": {
170
+ iApiClassBody += ` & MushroomCreateResource<${typescriptClassName}>`;
171
+ break;
172
+ }
173
+ case "createMany": {
174
+ iApiClassBody += ` & MushroomBatchCreateResource<${typescriptClassName}>`;
175
+ break;
176
+ }
177
+ case "updateOne": {
178
+ iApiClassBody += ` & MushroomUpdateResource<${typescriptClassName}>`;
179
+ break;
180
+ }
181
+ case "updateMany": {
182
+ iApiClassBody += ` & MushroomBatchUpdateResource<${typescriptClassName}>`;
183
+ break;
184
+ }
185
+ case "updatePartially": {
186
+ iApiClassBody += ` & MushroomPartialUpdateResource<${typescriptClassName}>`;
187
+ break;
188
+ }
189
+ case "deleteOne": {
190
+ iApiClassBody += " & MushroomDeleteResource";
191
+ break;
192
+ }
193
+ case "deleteMany": {
194
+ iApiClassBody += " & MushroomBatchDeleteResource";
195
+ break;
196
+ }
197
+ default: {
198
+ if (actionName.indexOf("_raw_http_method_") === 0) {
199
+ customMethodCode += ` ${actionName.substr("_raw_http_method_".length)}Async: (rawRequest: MushroomRequest) => Promise<MushroomResponse<any>>,
200
+ `;
201
+ break;
202
+ }
203
+ else {
204
+ console.warn(`Unknown action name: ${entityName}.${actionName}`);
205
+ break;
206
+ }
207
+ }
208
+ }
209
+ }
210
+
211
+ if (customMethodCode) {
212
+ code += `export interface ${typescriptClassName}$CustomMethodResource {
213
+ ${customMethodCode}}
214
+ `;
215
+ iApiClassBody += ` & ${typescriptClassName}$CustomMethodResource`;
126
216
  }
127
217
 
128
218
  const views = {};
219
+ let viewCode = "";
129
220
  for (const viewName in entity.views) {
130
- if (!entity.views.hasOwnProperty(viewName))
221
+ if (!entity.views.hasOwnProperty(viewName)) continue;
222
+
223
+ const viewRoles = entity.views[viewName];
224
+ if (!Array.isArray(viewRoles) || !viewRoles.length) continue;
225
+
226
+ views[viewName] = { clientCache: true };
227
+
228
+ const viewParameterTypes = viewRoles.map(view => {
229
+ const type = `${typescriptClassName}$ViewsResource_${viewName}View_${view.grant === "*" ? "" : toTypeScriptClassName(view.grant)}Parameters`;
230
+ code += `export interface ${type} ${generateTypescriptClassFromViewParameters(view.parameters)};
231
+ `;
232
+ return `MushroomViewFunction<any, ${type}>`;
233
+ });
234
+ viewCode += `
235
+ ${viewName}Async: ${viewParameterTypes.join(' & ')},`;
236
+ }
237
+
238
+ if (viewCode) {
239
+ code += `export interface ${typescriptClassName}$ViewsResource {
240
+ views: {${viewCode}
241
+ }
242
+ }
243
+ `;
244
+ iApiClassBody += ` & ${typescriptClassName}$ViewsResource`;
245
+ }
246
+
247
+ iApiClassBody +=`,
248
+ `;
249
+
250
+ code += `defineAsyncResource<${typescriptClassName}>(${JSON.stringify({ name: entityName, actions: actions, views: views })});
251
+
252
+ `;
253
+ }
254
+
255
+ code += `
256
+ mushroom.$using(${JSON.stringify(common.getRootUrl(source))});
257
+
258
+ ${extensionsCodeLines.join('\n')}
259
+
260
+ export interface IApi extends IMushroom {
261
+ ${iApiClassBody}};
262
+
263
+ export type Api = ${extensionsTypes.join('')}IApi;
264
+
265
+ export default mushroom as Api;`;
266
+
267
+ return code;
268
+ }
269
+
270
+ function genDtsString(aliasProject, source) {
271
+ if (!aliasProject) {
272
+ return "";
273
+ }
274
+
275
+ const entities = common.getEntities(source, aliasProject.allowRoles);
276
+
277
+ let extensionsImportLines = [];
278
+ let extensionsExportLines = [];
279
+ let extensionsTypes = [];
280
+
281
+ if (Array.isArray(aliasProject.features)) {
282
+ if (aliasProject.features.includes("auth")) {
283
+ extensionsImportLines.push('import * as AuthExtension from "mushroomjs-auth";');
284
+ extensionsExportLines.push('Auth: AuthExtension');
285
+ extensionsTypes.push("AuthExtension.IMushroomAuth & ");
286
+ }
287
+ if (aliasProject.features.includes("file")) {
288
+ extensionsImportLines.push('import * as FileExtension from "mushroomjs-file";');
289
+ extensionsExportLines.push('File: FileExtension');
290
+ extensionsTypes.push("FileExtension.IMushroomFile & ");
291
+ }
292
+ }
293
+
294
+ 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";
295
+ export * from "mushroomjs";
296
+ ${extensionsImportLines.join("\n")}
297
+ export declare const extensions = {
298
+ ${extensionsExportLines.join(",\n ")}
299
+ };
300
+
301
+ export declare type ISODateValue = string | Date;
302
+ export declare type IdValue = ${source.idType == "AutoIncInt" || source.idType == "AutoIncLong" ? "number" : "string"};
303
+
304
+ `;
305
+ let iApiClassBody = "";
306
+ for (let entityName in entities) {
307
+ if (!entities.hasOwnProperty(entityName))
308
+ continue;
309
+
310
+ const entity = entities[entityName];
311
+ const typescriptClassName = toTypeScriptClassName(entityName);
312
+ code += `export interface ${typescriptClassName} ${generateTypescriptClass(entity.fields)};
313
+ `;
314
+
315
+
316
+ const actions = {};
317
+ iApiClassBody += ` ${entityName}: MushroomResourceBase`;
318
+ let customMethodCode = "";
319
+ for (const actionName in entity.actions) {
320
+ if (!entity.actions.hasOwnProperty(actionName))
131
321
  continue;
132
322
 
323
+ actions[actionName] = {
324
+ clientCache: (actionName === "findById" || actionName === "findMany") && isAllowCache(entity.actions[actionName], true) ? true : undefined
325
+ };
326
+
327
+ switch (actionName) {
328
+ case "findMany": {
329
+ iApiClassBody += ` & MushroomListResource<${typescriptClassName}>`;
330
+ break;
331
+ }
332
+ case "findById": {
333
+ iApiClassBody += ` & MushroomFindByIdResource<${typescriptClassName}>`;
334
+ break;
335
+ }
336
+ case "createOne": {
337
+ iApiClassBody += ` & MushroomCreateResource<${typescriptClassName}>`;
338
+ break;
339
+ }
340
+ case "createMany": {
341
+ iApiClassBody += ` & MushroomBatchCreateResource<${typescriptClassName}>`;
342
+ break;
343
+ }
344
+ case "updateOne": {
345
+ iApiClassBody += ` & MushroomUpdateResource<${typescriptClassName}>`;
346
+ break;
347
+ }
348
+ case "updateMany": {
349
+ iApiClassBody += ` & MushroomBatchUpdateResource<${typescriptClassName}>`;
350
+ break;
351
+ }
352
+ case "updatePartially": {
353
+ iApiClassBody += ` & MushroomPartialUpdateResource<${typescriptClassName}>`;
354
+ break;
355
+ }
356
+ case "deleteOne": {
357
+ iApiClassBody += " & MushroomDeleteResource";
358
+ break;
359
+ }
360
+ case "deleteMany": {
361
+ iApiClassBody += " & MushroomBatchDeleteResource";
362
+ break;
363
+ }
364
+ default: {
365
+ if (actionName.indexOf("_raw_http_method_") === 0) {
366
+ customMethodCode += ` ${actionName.substr("_raw_http_method_".length)}Async: (rawRequest: MushroomRequest) => Promise<MushroomResponse<any>>,
367
+ `;
368
+ break;
369
+ }
370
+ else {
371
+ console.warn(`Unknown action name: ${entityName}.${actionName}`);
372
+ break;
373
+ }
374
+ }
375
+ }
376
+ }
377
+
378
+ if (customMethodCode) {
379
+ code += `export interface ${typescriptClassName}$CustomMethodResource {
380
+ ${customMethodCode}}
381
+ `;
382
+ iApiClassBody += ` & ${typescriptClassName}$CustomMethodResource`;
383
+ }
384
+
385
+ const views = {};
386
+ let viewCode = "";
387
+ for (const viewName in entity.views) {
388
+ if (!entity.views.hasOwnProperty(viewName)) continue;
389
+
390
+ const viewRoles = entity.views[viewName];
391
+ if (!Array.isArray(viewRoles) || !viewRoles.length) continue;
392
+
133
393
  views[viewName] = { clientCache: true };
394
+
395
+ const viewParameterTypes = viewRoles.map(view => {
396
+ const type = `${typescriptClassName}$ViewsResource_${viewName}View_${view.grant === "*" ? "" : toTypeScriptClassName(view.grant)}Parameters`;
397
+ code += `export interface ${type} ${generateTypescriptClassFromViewParameters(view.parameters)};
398
+ `;
399
+ return `MushroomViewFunction<any, ${type}>`;
400
+ });
401
+ viewCode += `
402
+ ${viewName}Async: ${viewParameterTypes.join(' & ')},`;
403
+ }
404
+
405
+ if (viewCode) {
406
+ code += `export interface ${typescriptClassName}$ViewsResource {
407
+ views: {${viewCode}
408
+ }
409
+ }
410
+ `;
411
+ iApiClassBody += ` & ${typescriptClassName}$ViewsResource`;
134
412
  }
135
- code += `defineAsyncResource<${toTypeScriptClassName(entityName)}>(${JSON.stringify({ name: entityName, actions: actions, views: views })});
136
413
 
414
+ iApiClassBody +=`,
137
415
  `;
138
416
  }
417
+
139
418
  code += `
140
- mushroom.$using(${JSON.stringify(common.getRootUrl(source))});`;
419
+ export interface IApi extends IMushroom {
420
+ ${iApiClassBody}};
421
+
422
+ declare type Api = ${extensionsTypes.join('')}IApi;
423
+ declare const _default: Api;
424
+ export default _default;`;
425
+
426
+ return code;
427
+ }
428
+
429
+ function genTypescriptDriver(args, projectName, project, alias, source) {
430
+ const aliasProject = ((project.tsDriver || {}).alias || {})[alias];
431
+
432
+ if (!aliasProject) {
433
+ 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`);
434
+ }
435
+
436
+ const code = genTypescriptDriverString(aliasProject, source);
141
437
 
142
438
  common.ensureFolder(aliasProject.output);
143
439
 
144
- fs.writeFile(aliasProject.output, code, err => {
145
- if (err)
146
- throw err;
147
- console.log(`Generated Typescript driver for ${projectName}@${alias} to ${aliasProject.output}`);
148
- });
440
+ fs.writeFileSync(aliasProject.output, code);
441
+ console.log(`Generated Typescript driver for ${projectName}@${alias} to ${aliasProject.output}`);
149
442
  }
150
443
 
151
- module.exports = genTypescriptDriver;
444
+ module.exports = {
445
+ genTypescriptDriver,
446
+ genTypescriptDriverString,
447
+ genDtsString
448
+ };
package/gen.js CHANGED
@@ -7,8 +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");
11
- const genTypescriptDriver = require("./gen/gen-ts-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");
12
13
  const csharp = require("./gen/gen-csharp");
13
14
 
14
15
 
@@ -87,19 +88,22 @@ async function gen(args) {
87
88
  await genApiDocs(args, projectName, project, alias, source);
88
89
  break;
89
90
  case "db-docs":
90
- await genDatabaseDocs(args, projectName, project, alias, source);
91
+ genDatabaseDocs(args, projectName, project, alias, source);
91
92
  break;
92
93
  case "js-driver":
93
- 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);
94
98
  break;
95
99
  case "ts-driver":
96
- await genTypescriptDriver(args, projectName, project, alias, source);
100
+ typescriptDriverGenerator.genTypescriptDriver(args, projectName, project, alias, source);
97
101
  break;
98
102
  case "c#-mongo":
99
- await csharp.genCSharpMongoDbClasses(args, projectName, project, alias, source);
103
+ csharp.genCSharpMongoDbClasses(args, projectName, project, alias, source);
100
104
  break;
101
105
  case "c#-driver":
102
- await csharp.genCSharpDriver(args, projectName, project, alias, source);
106
+ csharp.genCSharpDriver(args, projectName, project, alias, source);
103
107
  break;
104
108
  case "":
105
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
@@ -8,6 +8,10 @@ const help = require("./help.js");
8
8
  const package = require("./package.json");
9
9
  const checkUpdate = require("./check-update");
10
10
 
11
+ const versionGroup = package.version.match(/([^-]+)(-(\w+).*)?/);
12
+ const currentDistTag = versionGroup[3] ? versionGroup[3] : "latest";
13
+ console.log("Mushroom CLI version " + package.version);
14
+
11
15
  async function run(args) {
12
16
  let debugMode = false;
13
17
  if (args.indexOf("--debug") !== -1) {
@@ -59,8 +63,8 @@ async function run(args) {
59
63
  if (checkUpdateTask !== null)
60
64
  try {
61
65
  var data = await checkUpdateTask;
62
- if (data.version && data.version !== package.version) {
63
- console.warn("YOUR mushroom-cli VERSION IS NOT LATEST. PLEASE RUN: npm i mushroom-cli@" + data.version);
66
+ if (data["dist-tags"] && data["dist-tags"][currentDistTag] && data["dist-tags"][currentDistTag] !== package.version) {
67
+ console.warn(`YOUR mushroom-cli VERSION IS NOT LATEST (dist-tags: ${currentDistTag}). PLEASE RUN: npm i mushroom-cli@${data["dist-tags"][currentDistTag]}`);
64
68
  }
65
69
  }
66
70
  catch(e) {
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "mushroom-cli",
3
- "version": "1.0.15",
3
+ "version": "1.1.0-alpha.10",
4
4
  "description": "Mushroom CLI",
5
5
  "main": "mr.js",
6
6
  "scripts": {
7
- "release": "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
+ }