mushroom-cli 1.1.0-alpha.9 → 1.2.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/gen/gen-csharp.js CHANGED
@@ -3,6 +3,25 @@ const common = require("../common.js");
3
3
  const package = require("./../package.json");
4
4
 
5
5
  //#region shared function
6
+ const newLine = `
7
+ `;
8
+ const header = `// NOTE: Please do not modify this file
9
+ // NOTE: Version and compatibility information: please see in Info.cs file
10
+
11
+ // ReSharper disable CheckNamespace
12
+ // ReSharper disable CommentTypo
13
+ // ReSharper disable EmptyNamespace
14
+ // ReSharper disable IdentifierTypo
15
+ // ReSharper disable InconsistentNaming
16
+ // ReSharper disable PartialTypeWithSinglePart
17
+ // ReSharper disable RedundantUsingDirective
18
+ // ReSharper disable StringLiteralTypo
19
+ // ReSharper disable UnusedMember.Global
20
+ // ReSharper disable UnusedMember.Local
21
+ // ReSharper disable UnusedParameter.Local
22
+ // ReSharper disable UnusedTypeParameter
23
+ `;
24
+
6
25
  function singleLine(str) {
7
26
  if (!str)
8
27
  return "";
@@ -25,7 +44,7 @@ function toCSharpName(str) {
25
44
  return "_";
26
45
  const name = toVietnameseNonTongue(str).replace(/\W/g, "_");
27
46
  const c = name.charAt(0);
28
- return ('0' <= c && c <= '9' ? '_' : "") + c.toUpperCase() + name.substr(1);
47
+ return ('0' <= c && c <= '9' ? '_' : "") + c.toUpperCase() + name.substring(1);
29
48
  }
30
49
 
31
50
  function getCSharpTypeFromMushroomType(source, type, required) {
@@ -115,8 +134,10 @@ function generateEnumClass(source, out, field, defaultClassName) {
115
134
  strEnumClasses += ` /// <summary>
116
135
  /// ${singleLine(validation.codeHint.validValues.description || field.description)}
117
136
  /// </summary>
118
- public static class ${enumClassName}
137
+ public class ${enumClassName}
119
138
  {
139
+ private ${enumClassName}() { }
140
+
120
141
  `;
121
142
  const enumProperties = validation.codeHint.validValues.nameMap || validation.validValues;
122
143
  for (let i = 0; i < enumProperties.length && i < validation.validValues.length; i++) {
@@ -143,7 +164,8 @@ function generateCSharpClassMongoDb(source, className, fields, isRoot, descripti
143
164
  content +=
144
165
  ` /// <summary>
145
166
  /// ${singleLine(description)}
146
- /// </summary>\r\n`;
167
+ /// </summary>
168
+ `;
147
169
  }
148
170
  var supperClass = "";
149
171
  if (isRoot) {
@@ -171,12 +193,12 @@ function generateCSharpClassMongoDb(source, className, fields, isRoot, descripti
171
193
  type = field.codeHint.type.csharp;
172
194
  }
173
195
  else if (field.type === "object") {
174
- strClasses += generateCSharpClassMongoDb(source, className + "_" + propertyName, field.fields, false, null, out) + "\r\n";
196
+ strClasses += generateCSharpClassMongoDb(source, className + "_" + propertyName, field.fields, false, null, out) + newLine;
175
197
  type = className + "_" + propertyName;
176
198
  }
177
199
  else if (field.type === "array") {
178
200
  if (field.items.type === "object") {
179
- strClasses += generateCSharpClassMongoDb(source, className + "_" + propertyName, field.items.fields, false, null, out) + "\r\n";
201
+ strClasses += generateCSharpClassMongoDb(source, className + "_" + propertyName, field.items.fields, false, null, out) + newLine;
180
202
  type = `System.Collections.Generic.List<${className}_${propertyName}>`;
181
203
  } else {
182
204
  type = `System.Collections.Generic.List<${getCSharpTypeFromMushroomType(source, field.items.type, field.items.validation && field.items.validation.required)}>`;
@@ -190,38 +212,38 @@ function generateCSharpClassMongoDb(source, className, fields, isRoot, descripti
190
212
  `;
191
213
 
192
214
  if (isRoot && fieldName === "id") {
193
- content += ` [BsonId${field.type === "AutoId" && source.idType === "GUID" ? "(IdGenerator = typeof(MongoDB.Bson.Serialization.IdGenerators.GuidGenerator))" : ""}]\r\n`;
215
+ content += ` [MongoDB.Bson.Serialization.Attributes.BsonId${field.type === "AutoId" && source.idType === "GUID" ? "(IdGenerator = typeof(MongoDB.Bson.Serialization.IdGenerators.GuidGenerator))" : ""}]${newLine}`;
194
216
  }
195
- content += ` [BsonElement("${isRoot && fieldName === "id" ? "_id" : fieldName}")]
196
- [BsonIgnoreIfNull]
197
- [JsonProperty(PropertyName = "${fieldName}", NullValueHandling = NullValueHandling.Ignore)]
217
+ content += ` [MongoDB.Bson.Serialization.Attributes.BsonElement("${isRoot && fieldName === "id" ? "_id" : fieldName}")]
218
+ [MongoDB.Bson.Serialization.Attributes.BsonIgnoreIfNull]
219
+ [Newtonsoft.Json.JsonProperty(PropertyName = "${fieldName}", NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore${type === "System.DateTime" ? ", DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore" : ""})]
198
220
  `;
199
221
  if ((field.type === "AutoId" || field.type === "IdRef") && source.idType === "ObjectId") {
200
- content += " [BsonRepresentation(BsonType.ObjectId)]\r\n";
222
+ content += " [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)]" + newLine;
201
223
  }
202
224
  if (field.type === "AutoId" && source.idType === "GUID") {
203
- content += " [BsonRepresentation(BsonType.String)]\r\n";
225
+ content += " [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.String)]" + newLine;
204
226
  }
205
227
  if (field.type === "datetime") {
206
- content += " [BsonDateTimeOptions(Kind = System.DateTimeKind.Local)]\r\n";
228
+ content += " [MongoDB.Bson.Serialization.Attributes.BsonDateTimeOptions(Kind = System.DateTimeKind.Local)]" + newLine;
207
229
  }
208
230
  if (field.type === "array") {
209
231
  if ((field.items.type === "AutoId" || field.items.type === "IdRef") && source.idType === "ObjectId") {
210
- content += " [BsonRepresentation(BsonType.ObjectId)]\r\n";
232
+ content += " [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)]" + newLine;
211
233
  }
212
234
  if (field.items.type === "AutoId" && source.idType === "GUID") {
213
- content += " [BsonRepresentation(BsonType.String)]\r\n";
235
+ content += " [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.String)]" + newLine;
214
236
  }
215
237
  if (field.items.type === "datetime") {
216
- content += " [BsonDateTimeOptions(Kind = System.DateTimeKind.Local)]\r\n";
238
+ content += " [MongoDB.Bson.Serialization.Attributes.BsonDateTimeOptions(Kind = System.DateTimeKind.Local)]" + newLine;
217
239
  }
218
240
  }
219
241
 
220
- content += ` public ${type} ${propertyName} { get; set; }\r\n\r\n`;
242
+ content += ` public ${type} ${propertyName} { get; set; }${newLine}${newLine}`;
221
243
 
222
244
  strEnumClasses += generateEnumClass(source, out, field, `${className.toUpperCase()}_${propertyName.toUpperCase()}_ENUM`);
223
245
  }
224
- content += ` [BsonExtraElements]
246
+ content += ` [MongoDB.Bson.Serialization.Attributes.BsonExtraElements]
225
247
  public System.Collections.Generic.Dictionary<string, object> Mushroom_ExtraProperties { get; set; }
226
248
 
227
249
  }
@@ -233,21 +255,26 @@ function generateCSharpClassMongoDb(source, className, fields, isRoot, descripti
233
255
  //console.log("strEnumClasses("+typeof(strEnumClasses)+"):" + strEnumClasses);
234
256
  }
235
257
 
236
- return strClasses + "\r\n" + content;
258
+ return strClasses + newLine + content;
237
259
  }
238
260
 
239
261
  function getCSharpFunc(methodName, methodType) {
240
262
  if (methodType === "static") return methodName;
241
263
  const idx = methodName.lastIndexOf('.');
242
264
  if (idx === -1) return methodName;
243
- return `new ${methodName.substr(0, idx)}()${methodName.substr(idx)}`;
265
+ return `new ${methodName.substring(0, idx)}()${methodName.substring(idx)}`;
244
266
  }
245
267
 
246
268
  function genCSharpMongoDbClasses(args, projectName, project, alias, source) {
247
269
  const aliasProject = ((project.csharpMongo || {}).alias || {})[alias];
248
270
 
249
271
  if (!aliasProject) {
250
- throw new Error(`Not found gen c#-mongo configuration. Please run 'npx mr config ${projectName} gen c#-mongo OUTPUT_FILE.cs${alias === "default" ? "" : " alias " + alias}' first`);
272
+ throw new Error(`Not found gen c#-mongo configuration. Please run 'npx mushroom-cli config ${projectName} gen c#-mongo OUTPUT_FILE.cs${alias === "default" ? "" : " alias " + alias}' first`);
273
+ }
274
+
275
+ if (aliasProject.outputToFolder) {
276
+ genCSharpMongoDbClassesToFolder(projectName, alias, source, aliasProject);
277
+ return;
251
278
  }
252
279
 
253
280
  const entities = common.getEntities(source, aliasProject.allowRoles, true);
@@ -258,6 +285,17 @@ function genCSharpMongoDbClasses(args, projectName, project, alias, source) {
258
285
  let strEnumClasses = "";
259
286
  let collectionNames = "";
260
287
  let resourceNames = "";
288
+ let roleNames = "";
289
+
290
+ source.roles?.forEach(role => {
291
+ if (!role.name) return;
292
+ roleNames += `
293
+ /// <summary>
294
+ /// ${role.description ?? ""}
295
+ /// </summary>
296
+ public static string ${toCSharpName(role.name)} => "${role.name}";
297
+ `;
298
+ });
261
299
 
262
300
  const out = {};
263
301
  for (let entityName in entities) {
@@ -268,7 +306,7 @@ function genCSharpMongoDbClasses(args, projectName, project, alias, source) {
268
306
  collectionNames += ` public static string ${className}CollectionName => "${entities[entityName].storageName}";
269
307
  public static IMongoCollection<Resources.${className}> ${className}Collection => GetDatabase().GetCollection<Resources.${className}>(${className}CollectionName);
270
308
  `;
271
- resourceNames += ` public static string ${className} => "${entityName}";\r\n`;
309
+ resourceNames += ` public static string ${className} => "${entityName}";${newLine}`;
272
310
  strClasses += generateCSharpClassMongoDb(source, className, entities[entityName].fields, true, entities[entityName].description, out);
273
311
 
274
312
  const actions = entities[entityName].actions || {};
@@ -344,6 +382,25 @@ function genCSharpMongoDbClasses(args, projectName, project, alias, source) {
344
382
  }
345
383
  });
346
384
  }
385
+
386
+ const channels = entities[entityName].features?.vn_text?.channels;
387
+ if (channels != null) {
388
+ channels.forEach(channel => {
389
+ if (!channel.nativeBuilder || typeof channel.nativeBuilder !== "string" || channel.nativeBuilder.indexOf("lib:") !== 0) return;
390
+
391
+ out.vnTextChannels = out.vnTextChannels || [];
392
+ const method = channel.nativeBuilder.substr(4, channel.nativeBuilder.length - 4);
393
+ let type = channel.codeHint && channel.codeHint.nativeBuilder && channel.codeHint.nativeBuilder.csharp
394
+ ? channel.codeHint.nativeBuilder.csharp.methodType
395
+ : null;
396
+ if (type !== "non-static") type = "static";
397
+ out.vnTextChannels.push({
398
+ method: method,
399
+ source: `entity: ${entityName}, feature: vn_text, channel: ${channel.name}`,
400
+ type: type
401
+ });
402
+ });
403
+ }
347
404
  }
348
405
 
349
406
  if (out.strEnumClasses)
@@ -360,7 +417,7 @@ function genCSharpMongoDbClasses(args, projectName, project, alias, source) {
360
417
  }
361
418
  return prev;
362
419
  }, {});
363
- const strDelegatorReferences = Object.keys(delegators).map(method => delegators[method].map(ev => ` // ${ev.source}`).join("\r\n") + "\r\n" + ` RegisterCustomMethod(${getCSharpFunc(method, delegators[method][0].type)});`).join("\r\n");
420
+ const strDelegatorReferences = Object.keys(delegators).map(method => delegators[method].map(ev => ` // ${ev.source}`).join(newLine) + newLine + ` RegisterCustomMethod(${getCSharpFunc(method, delegators[method][0].type)});`).join(newLine);
364
421
 
365
422
  const viewHandlers = (out.viewHandlers || []).reduce((prev, cur) => {
366
423
  if (cur.method in prev) {
@@ -373,7 +430,20 @@ function genCSharpMongoDbClasses(args, projectName, project, alias, source) {
373
430
  }
374
431
  return prev;
375
432
  }, {});
376
- const strViewHandlerReferences = Object.keys(viewHandlers).map(method => viewHandlers[method].map(ev => ` // ${ev.source}`).join("\r\n") + "\r\n" + ` RegisterCustomViewMethod(${getCSharpFunc(method, viewHandlers[method][0].type)});`).join("\r\n");
433
+ const strViewHandlerReferences = Object.keys(viewHandlers).map(method => viewHandlers[method].map(ev => ` // ${ev.source}`).join(newLine) + newLine + ` RegisterCustomViewMethod(${getCSharpFunc(method, viewHandlers[method][0].type)});`).join(newLine);
434
+
435
+ const vnTextChannels = (out.vnTextChannels || []).reduce((prev, cur) => {
436
+ if (cur.method in prev) {
437
+ if (prev[cur.method].indexOf(cur.source) === -1) {
438
+ prev[cur.method].push(cur);
439
+ }
440
+ }
441
+ else {
442
+ prev[cur.method] = [cur];
443
+ }
444
+ return prev;
445
+ }, {});
446
+ const strVnTextChannels = Object.keys(vnTextChannels).map(method => vnTextChannels[method].map(channel => ` // ${channel.source}`).join(newLine) + newLine + ` RegisterCustomVnTextBuilderMethod(${getCSharpFunc(method, vnTextChannels[method][0].type)});`).join(newLine);
377
447
 
378
448
  const eventHandlers = (out.eventHandlers || []).reduce((prev, cur) => {
379
449
  if (cur.method in prev) {
@@ -386,18 +456,18 @@ function genCSharpMongoDbClasses(args, projectName, project, alias, source) {
386
456
  }
387
457
  return prev;
388
458
  }, {});
389
- const strEventHandlerReferences = Object.keys(eventHandlers).map(method => eventHandlers[method].map(ev => ` // ${ev.source}`).join("\r\n") + "\r\n" + ` RegisterEvent(${getCSharpFunc(method, eventHandlers[method][0].type)});`).join("\r\n");
459
+ const strEventHandlerReferences = Object.keys(eventHandlers).map(method => eventHandlers[method].map(ev => ` // ${ev.source}`).join(newLine) + newLine + ` RegisterEvent(${getCSharpFunc(method, eventHandlers[method][0].type)});`).join(newLine);
390
460
 
391
461
  const strJobReferences = Array.isArray(source.jobs)
392
462
  ? source.jobs
393
463
  .filter(job => job !== null && typeof(job) === "object" && job.action && typeof (job.action) === "string" && job.action.indexOf("lib:") === 0)
394
- .map(job => ` RegisterJob<${job.action.substr(4).split(',')[0]}>();`)
395
- .join("\r\n")
464
+ .map(job => ` RegisterJob<${job.action.substring(4).split(',')[0]}>();`)
465
+ .join(newLine)
396
466
  : "";
397
467
 
398
468
  const code = `// This file was generated by Mushroom CLI ${package.version} (https://www.npmjs.com/package/mushroom-cli), please do not modify
399
469
 
400
- // NOTE: Compatible with Mushroom Server version 0.2.18 or higher
470
+ // NOTE: Compatible with Mushroom Server version 0.2.18 or higher (https://www.nuget.org/packages/Mushroom/)
401
471
 
402
472
  // ReSharper disable RedundantUsingDirective
403
473
  // ReSharper disable InconsistentNaming
@@ -410,14 +480,10 @@ function genCSharpMongoDbClasses(args, projectName, project, alias, source) {
410
480
  // ReSharper disable CommentTypo
411
481
  // ReSharper disable EmptyNamespace
412
482
 
413
- using MongoDB.Bson;
414
- using MongoDB.Bson.Serialization.Attributes;
415
- using MongoDB.Driver;
416
- using JsonPropertyAttribute = Newtonsoft.Json.JsonPropertyAttribute;
417
- using NullValueHandling = Newtonsoft.Json.NullValueHandling;
418
-
419
483
  namespace ${namespace}
420
484
  {
485
+ using MongoDB.Driver;
486
+
421
487
  public static class DbConnector
422
488
  {
423
489
  ${collectionNames}
@@ -439,10 +505,18 @@ ${collectionNames}
439
505
  }
440
506
  }
441
507
 
442
- public static class ResourceNames
508
+ public class ResourceNames
443
509
  {
510
+ private ResourceNames() { }
511
+
444
512
  ${resourceNames}
445
513
  }
514
+
515
+ public class RoleNames {
516
+ private RoleNames() { }
517
+
518
+ ${roleNames}
519
+ }
446
520
  }
447
521
 
448
522
  namespace ${namespace}.Resources
@@ -465,6 +539,7 @@ namespace ${namespace}.CodeHelper
465
539
  private void RegisterCustomMethod(System.Action<Mushroom.ActionArguments> fn) { }
466
540
  private void RegisterCustomViewMethod(System.Func<Mushroom.ViewArguments, System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<object>>> fn) { }
467
541
  private void RegisterCustomViewMethod(System.Action<Mushroom.ViewArguments> fn) { }
542
+ private void RegisterCustomVnTextBuilderMethod(System.Func<System.Collections.Generic.IEnumerable<string>, System.Collections.Generic.IEnumerable<string>> fn) { }
468
543
  private void RegisterEvent(System.Func<object, Mushroom.ActionArguments, System.Threading.Tasks.Task> fn) { }
469
544
  private void RegisterEvent(System.Action<object, Mushroom.ActionArguments> fn) { }
470
545
  private void RegisterJob<T>() where T : Mushroom.Job.JobBase { }
@@ -472,6 +547,7 @@ namespace ${namespace}.CodeHelper
472
547
  {
473
548
  ${strDelegatorReferences}
474
549
  ${strViewHandlerReferences}
550
+ ${strVnTextChannels}
475
551
  ${strEventHandlerReferences}
476
552
  ${strJobReferences}
477
553
  }
@@ -488,6 +564,423 @@ ${strJobReferences}
488
564
  console.log(`Generated CSharp MongoDb Classes for ${projectName}@${alias} to ${aliasProject.output}`);
489
565
  });
490
566
  }
567
+
568
+ function generateCSharpClassMongoDbToFolder(source, className, fields, isRoot, description, out, aliasProject) {
569
+ var content = "";
570
+ const namespace = toCSharpName(source.name);
571
+ if (description) {
572
+ content +=
573
+ ` /// <summary>
574
+ /// ${singleLine(description)}
575
+ /// </summary>
576
+ `;
577
+ }
578
+ var supperClass = "";
579
+ if (isRoot) {
580
+ // thêm cho trường hợp không khai báo id hoặc id.type
581
+ if (!fields.id) {
582
+ fields.id = {
583
+ type: "AutoId"
584
+ };
585
+ }
586
+ if (!fields.id.type) fields.id.type = "AutoId";
587
+
588
+ supperClass = " : Mushroom.Models.IResource<" + getCSharpTypeFromMushroomType(source, fields.id.type, true) + ">";
589
+ }
590
+ content += ` public class ${className}${supperClass}
591
+ {
592
+ `;
593
+ for (var fieldName in fields) {
594
+ if (!fields.hasOwnProperty(fieldName))
595
+ continue;
596
+
597
+ var field = fields[fieldName];
598
+ var type;
599
+ var propertyName = toCSharpName(fieldName);
600
+ if (field.codeHint && field.codeHint.type && field.codeHint.type.csharp) {
601
+ type = field.codeHint.type.csharp;
602
+ }
603
+ else if (field.type === "object") {
604
+ generateCSharpClassMongoDbToFolder(source, className + "_" + propertyName, field.fields, false, null, out, aliasProject) + newLine;
605
+ type = className + "_" + propertyName;
606
+ }
607
+ else if (field.type === "array") {
608
+ if (field.items.type === "object") {
609
+ generateCSharpClassMongoDbToFolder(source, className + "_" + propertyName, field.items.fields, false, null, out, aliasProject) + newLine;
610
+ type = `System.Collections.Generic.List<${className}_${propertyName}>`;
611
+ } else {
612
+ type = `System.Collections.Generic.List<${getCSharpTypeFromMushroomType(source, field.items.type, field.items.validation && field.items.validation.required)}>`;
613
+ }
614
+ } else
615
+ type = getCSharpTypeFromMushroomType(source, field.type, field.validation && field.validation.required);
616
+ content +=
617
+ ` /// <summary>
618
+ /// ${singleLine(field.description)}
619
+ /// </summary>
620
+ `;
621
+
622
+ if (isRoot && fieldName === "id") {
623
+ content += ` [MongoDB.Bson.Serialization.Attributes.BsonId${field.type === "AutoId" && source.idType === "GUID" ? "(IdGenerator = typeof(MongoDB.Bson.Serialization.IdGenerators.GuidGenerator))" : ""}]${newLine}`;
624
+ }
625
+ content += ` [MongoDB.Bson.Serialization.Attributes.BsonElement("${isRoot && fieldName === "id" ? "_id" : fieldName}")]
626
+ [MongoDB.Bson.Serialization.Attributes.BsonIgnoreIfNull]
627
+ [Newtonsoft.Json.JsonProperty(PropertyName = "${fieldName}", NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore${type === "System.DateTime" ? ", DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore" : ""})]
628
+ `;
629
+ if ((field.type === "AutoId" || field.type === "IdRef") && source.idType === "ObjectId") {
630
+ content += " [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)]" + newLine;
631
+ }
632
+ if (field.type === "AutoId" && source.idType === "GUID") {
633
+ content += " [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.String)]" + newLine;
634
+ }
635
+ if (field.type === "datetime") {
636
+ content += " [MongoDB.Bson.Serialization.Attributes.BsonDateTimeOptions(Kind = System.DateTimeKind.Local)]" + newLine;
637
+ }
638
+ if (field.type === "array") {
639
+ if ((field.items.type === "AutoId" || field.items.type === "IdRef") && source.idType === "ObjectId") {
640
+ content += " [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)]" + newLine;
641
+ }
642
+ if (field.items.type === "AutoId" && source.idType === "GUID") {
643
+ content += " [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.String)]" + newLine;
644
+ }
645
+ if (field.items.type === "datetime") {
646
+ content += " [MongoDB.Bson.Serialization.Attributes.BsonDateTimeOptions(Kind = System.DateTimeKind.Local)]" + newLine;
647
+ }
648
+ }
649
+
650
+ content += ` public ${type} ${propertyName} { get; set; }
651
+
652
+ `;
653
+
654
+ let strEnumClasses = generateEnumClass(source, {}, field, `${className.toUpperCase()}_${propertyName.toUpperCase()}_ENUM`);
655
+
656
+ const match = strEnumClasses.match(/public class\s+(\w+)/);
657
+ if (!match) continue;
658
+ common.ensureFolder(aliasProject.output + "/Enums", true);
659
+ strEnumClasses = `${header}
660
+
661
+ namespace ${namespace}.Enums
662
+ {
663
+ ${strEnumClasses}
664
+ }
665
+ `;
666
+
667
+ fs.writeFileSync(aliasProject.output + "/Enums/" + match[1] + ".cs", strEnumClasses);
668
+ }
669
+
670
+ content += ` [MongoDB.Bson.Serialization.Attributes.BsonExtraElements]
671
+ [Newtonsoft.Json.JsonIgnore]
672
+ public System.Collections.Generic.Dictionary<string, object> Mushroom_ExtraProperties { get; set; }
673
+
674
+ }
675
+ `;
676
+
677
+ //return strClasses + newLine + content;
678
+ common.ensureFolder(aliasProject.output + "/Resources", true);
679
+
680
+ content = `${header}
681
+
682
+ namespace ${namespace}.Resources
683
+ {
684
+ ${content}
685
+ }
686
+ `;
687
+
688
+ out.allClasses = out.allClasses || [];
689
+
690
+ const normalizedName = className.toLowerCase();
691
+ const duplicate = out.allClasses.find(c => c.normalizedName == normalizedName);
692
+ if (duplicate) {
693
+ fs.appendFileSync(aliasProject.output + "/Resources/" + duplicate.className + ".cs", content);
694
+ }
695
+ else {
696
+ out.allClasses.push({
697
+ className,
698
+ normalizedName
699
+ });
700
+ fs.writeFileSync(aliasProject.output + "/Resources/" + className + ".cs", content);
701
+ }
702
+ }
703
+
704
+ function genCSharpMongoDbClassesToFolder(projectName, alias, source, aliasProject) {
705
+
706
+ if (fs.existsSync(aliasProject.output)) {
707
+ try {
708
+ fs.unlinkSync(aliasProject.output); // xóa file nếu có
709
+ } catch(e) {}
710
+ try {
711
+ // fs.rmdirSync(aliasProject.output, { recursive: true, force: true }); // xóa thư mục nếu có
712
+ fs.rmSync(aliasProject.output, { recursive: true, force: true }); // xóa thư mục nếu có
713
+ } catch(e) {}
714
+ }
715
+ fs.mkdirSync(aliasProject.output, { recursive: true, mode: 0755 });
716
+
717
+ const entities = common.getEntities(source, aliasProject.allowRoles, true);
718
+
719
+ const namespace = toCSharpName(source.name);
720
+
721
+ let collectionNames = "";
722
+ let resourceNames = "";
723
+ let roleNames = "";
724
+
725
+ source.roles?.forEach(role => {
726
+ if (!role.name) return;
727
+ roleNames += `
728
+ /// <summary>
729
+ /// ${role.description ?? ""}
730
+ /// </summary>
731
+ public static string ${toCSharpName(role.name)} => "${role.name}";
732
+ `;
733
+ });
734
+
735
+ const out = {};
736
+ for (let entityName in entities) {
737
+ if (!entities.hasOwnProperty(entityName))
738
+ continue;
739
+
740
+ const className = toCSharpName(entityName);
741
+ collectionNames += ` public static string ${className}CollectionName => "${entities[entityName].storageName}";
742
+ public static IMongoCollection<Resources.${className}> ${className}Collection => GetDatabase().GetCollection<Resources.${className}>(${className}CollectionName);
743
+ `;
744
+ resourceNames += ` public static string ${className} => "${entityName}";
745
+ `;
746
+ //strClasses += generateCSharpClassMongoDbToFolder(source, className, entities[entityName].fields, true, entities[entityName].description, out);
747
+
748
+ generateCSharpClassMongoDbToFolder(source, className, entities[entityName].fields, true, entities[entityName].description, out, aliasProject);
749
+
750
+ const actions = entities[entityName].actions || {};
751
+ for (let actionName in actions) {
752
+ const action = actions[actionName];
753
+ if (!Array.isArray(action))
754
+ continue;
755
+
756
+ action.forEach(a => {
757
+ if (!a)
758
+ return;
759
+ if (typeof a.delegator === "string" && a.delegator.indexOf("lib:") === 0) {
760
+ out.delegators = out.delegators || [];
761
+ const method = a.delegator.substr(4, a.delegator.length - 4);
762
+ let type = a.codeHint && a.codeHint.delegator && a.codeHint.delegator.csharp
763
+ ? a.codeHint.delegator.csharp.methodType
764
+ : null;
765
+ if (type !== "non-static") type = "static";
766
+ out.delegators.push({
767
+ method: method,
768
+ source: `entity: ${entityName}, action: ${actionName}, grant: ${a.grant}`,
769
+ type: type
770
+ });
771
+ }
772
+
773
+ if (!a.events && !(typeof a.events === "object")) return;
774
+
775
+ for (let eventName in a.events) {
776
+ if (!Array.isArray(a.events[eventName])) return;
777
+
778
+ out.eventHandlers = out.eventHandlers || [];
779
+ a.events[eventName].forEach((ev, i) => {
780
+ if (typeof ev !== "string" || ev.indexOf("lib:") !== 0) return;
781
+ const method = ev.substr(4, ev.length - 4);
782
+ let type = a.codeHint && a.codeHint.events
783
+ && Array.isArray(a.codeHint.events[eventName])
784
+ && a.codeHint.events[eventName][i]
785
+ && a.codeHint.events[eventName][i].csharp
786
+ ? a.codeHint.events[eventName][i].csharp.methodType
787
+ : null;
788
+ if (type !== "non-static") type = "static";
789
+ out.eventHandlers.push({
790
+ method: method,
791
+ source: `entity: ${entityName}, action: ${actionName}, grant: ${a.grant}, event: ${eventName}`,
792
+ type: type
793
+ });
794
+ });
795
+ }
796
+ });
797
+ }
798
+
799
+ const views = entities[entityName].views || {};
800
+ for (let viewName in views) {
801
+ const view = views[viewName];
802
+ if (!Array.isArray(view))
803
+ continue;
804
+
805
+ view.forEach(v => {
806
+ if (!v) return;
807
+
808
+ if (typeof v.query === "string" && v.query.indexOf("lib:") === 0) {
809
+ out.viewHandlers = out.viewHandlers || [];
810
+ const method = v.query.substr(4, v.query.length - 4);
811
+ let type = v.codeHint && v.codeHint.query && v.codeHint.query.csharp
812
+ ? v.codeHint.query.csharp.methodType
813
+ : null;
814
+ if (type !== "non-static") type = "static";
815
+ out.viewHandlers.push({
816
+ method: method,
817
+ source: `entity: ${entityName}, view: ${viewName}, grant: ${v.grant}`,
818
+ type: type
819
+ });
820
+ }
821
+ });
822
+ }
823
+
824
+ const channels = entities[entityName].features?.vn_text?.channels;
825
+ if (channels != null) {
826
+ channels.forEach(channel => {
827
+ if (!channel.nativeBuilder || typeof channel.nativeBuilder !== "string" || channel.nativeBuilder.indexOf("lib:") !== 0) return;
828
+
829
+ out.vnTextChannels = out.vnTextChannels || [];
830
+ const method = channel.nativeBuilder.substr(4, channel.nativeBuilder.length - 4);
831
+ let type = channel.codeHint && channel.codeHint.nativeBuilder && channel.codeHint.nativeBuilder.csharp
832
+ ? channel.codeHint.nativeBuilder.csharp.methodType
833
+ : null;
834
+ if (type !== "non-static") type = "static";
835
+ out.vnTextChannels.push({
836
+ method: method,
837
+ source: `entity: ${entityName}, feature: vn_text, channel: ${channel.name}`,
838
+ type: type
839
+ });
840
+ });
841
+ }
842
+ }
843
+
844
+
845
+ const delegators = (out.delegators || []).reduce((prev, cur) => {
846
+ if (cur.method in prev) {
847
+ if (prev[cur.method].indexOf(cur.source) === -1) {
848
+ prev[cur.method].push(cur);
849
+ }
850
+ }
851
+ else {
852
+ prev[cur.method] = [cur];
853
+ }
854
+ return prev;
855
+ }, {});
856
+ const strDelegatorReferences = Object.keys(delegators).map(method => delegators[method].map(ev => ` // ${ev.source}`).join(newLine) + newLine + ` RegisterCustomMethod(${getCSharpFunc(method, delegators[method][0].type)});`).join(newLine);
857
+
858
+ const viewHandlers = (out.viewHandlers || []).reduce((prev, cur) => {
859
+ if (cur.method in prev) {
860
+ if (prev[cur.method].indexOf(cur.source) === -1) {
861
+ prev[cur.method].push(cur);
862
+ }
863
+ }
864
+ else {
865
+ prev[cur.method] = [cur];
866
+ }
867
+ return prev;
868
+ }, {});
869
+ const strViewHandlerReferences = Object.keys(viewHandlers).map(method => viewHandlers[method].map(ev => ` // ${ev.source}`).join(newLine) + newLine + ` RegisterCustomViewMethod(${getCSharpFunc(method, viewHandlers[method][0].type)});`).join(newLine);
870
+
871
+ const vnTextChannels = (out.vnTextChannels || []).reduce((prev, cur) => {
872
+ if (cur.method in prev) {
873
+ if (prev[cur.method].indexOf(cur.source) === -1) {
874
+ prev[cur.method].push(cur);
875
+ }
876
+ }
877
+ else {
878
+ prev[cur.method] = [cur];
879
+ }
880
+ return prev;
881
+ }, {});
882
+ const strVnTextChannels = Object.keys(vnTextChannels).map(method => vnTextChannels[method].map(channel => ` // ${channel.source}`).join(newLine) + newLine + ` RegisterCustomVnTextBuilderMethod(${getCSharpFunc(method, vnTextChannels[method][0].type)});`).join(newLine);
883
+
884
+ const eventHandlers = (out.eventHandlers || []).reduce((prev, cur) => {
885
+ if (cur.method in prev) {
886
+ if (prev[cur.method].indexOf(cur.source) === -1) {
887
+ prev[cur.method].push(cur);
888
+ }
889
+ }
890
+ else {
891
+ prev[cur.method] = [cur];
892
+ }
893
+ return prev;
894
+ }, {});
895
+ const strEventHandlerReferences = Object.keys(eventHandlers).map(method => eventHandlers[method].map(ev => ` // ${ev.source}`).join(newLine) + newLine + ` RegisterEvent(${getCSharpFunc(method, eventHandlers[method][0].type)});`).join(newLine);
896
+
897
+ const strJobReferences = Array.isArray(source.jobs)
898
+ ? source.jobs
899
+ .filter(job => job !== null && typeof(job) === "object" && job.action && typeof (job.action) === "string" && job.action.indexOf("lib:") === 0)
900
+ .map(job => ` RegisterJob<${job.action.substring(4).split(',')[0]}>();`)
901
+ .join(newLine)
902
+ : "";
903
+
904
+ const dbConnectorFileContent = `${header}
905
+ using MongoDB.Driver;
906
+
907
+ namespace ${namespace}
908
+ {
909
+ public static class DbConnector
910
+ {
911
+ ${collectionNames}
912
+ public static IMongoDatabase GetDatabase() => Mushroom.MushroomDaoFactory.GetDbAdapter() as IMongoDatabase;
913
+ }
914
+ }
915
+ `;
916
+
917
+ const resourceNamesFileContent = `${header}
918
+
919
+ namespace ${namespace}
920
+ {
921
+ public class ResourceNames
922
+ {
923
+ private ResourceNames() { }
924
+
925
+ ${resourceNames}
926
+ }
927
+ }
928
+ `;
929
+
930
+ const roleNamesFileContent = `${header}
931
+
932
+ namespace ${namespace}
933
+ {
934
+ public class RoleNames
935
+ {
936
+ private RoleNames() { }
937
+
938
+ ${roleNames}
939
+ }
940
+ }
941
+ `;
942
+
943
+
944
+ const refactorHelperFileContent = `${header}
945
+
946
+ #if DEBUG
947
+ namespace ${namespace}
948
+ {
949
+ class RefactorHelper
950
+ {
951
+ private RefactorHelper() { }
952
+ private void RegisterCustomMethod(System.Func<Mushroom.ActionArguments, System.Threading.Tasks.Task> fn) { }
953
+ private void RegisterCustomMethod(System.Action<Mushroom.ActionArguments> fn) { }
954
+ private void RegisterCustomViewMethod(System.Func<Mushroom.ViewArguments, System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<object>>> fn) { }
955
+ private void RegisterCustomViewMethod(System.Action<Mushroom.ViewArguments> fn) { }
956
+ private void RegisterCustomVnTextBuilderMethod(System.Func<System.Collections.Generic.IEnumerable<string>, System.Collections.Generic.IEnumerable<string>> fn) { }
957
+ private void RegisterEvent(System.Func<object, Mushroom.ActionArguments, System.Threading.Tasks.Task> fn) { }
958
+ private void RegisterEvent(System.Action<object, Mushroom.ActionArguments> fn) { }
959
+ private void RegisterJob<T>() where T : Mushroom.Job.JobBase { }
960
+ private void Help()
961
+ {
962
+ ${strDelegatorReferences}
963
+ ${strViewHandlerReferences}
964
+ ${strVnTextChannels}
965
+ ${strEventHandlerReferences}
966
+ ${strJobReferences}
967
+ }
968
+ }
969
+ }
970
+ #endif
971
+ `;
972
+
973
+ const infoFileContent = `// Mushroom CLI version: ${package.version}${newLine}// Compatible with Mushroom Server version: 0.2.25.4 or higher (https://www.nuget.org/packages/Mushroom/)
974
+ // For Mushroom Server 0.2.18 to 0.2.25.4: Please remove all FindById methods in DbConnector.cs`
975
+
976
+ fs.writeFileSync(aliasProject.output + "/DbConnector.cs", dbConnectorFileContent);
977
+ fs.writeFileSync(aliasProject.output + "/ResourceNames.cs", resourceNamesFileContent);
978
+ fs.writeFileSync(aliasProject.output + "/RoleNames.cs", roleNamesFileContent);
979
+ fs.writeFileSync(aliasProject.output + "/RefactorHelper.cs", refactorHelperFileContent);
980
+ fs.writeFileSync(aliasProject.output + "/Info.cs", infoFileContent);
981
+
982
+ console.log(`Generated CSharp MongoDb Classes for ${projectName}@${alias} to folder ${aliasProject.output}`);
983
+ }
491
984
  //#endregion
492
985
 
493
986
  //#region CSharp Driver
@@ -515,12 +1008,12 @@ function generateCSharpClassDriver(source, className, fields, description, out)
515
1008
  const propertyName = toCSharpName(fieldName);
516
1009
  let type;
517
1010
  if (field.type === "object") {
518
- strClasses += generateCSharpClassDriver(source, className + "_" + propertyName, field.fields, null, out) + "\r\n";
1011
+ strClasses += generateCSharpClassDriver(source, className + "_" + propertyName, field.fields, null, out) + newLine;
519
1012
  type = className + "_" + propertyName;
520
1013
  }
521
1014
  else if (field.type === "array") {
522
1015
  if (field.items.type === "object") {
523
- strClasses += generateCSharpClassDriver(source, className + "_" + propertyName, field.items.fields, null, out) + "\r\n";
1016
+ strClasses += generateCSharpClassDriver(source, className + "_" + propertyName, field.items.fields, null, out) + newLine;
524
1017
  type = `System.Collections.Generic.List<${className}_${propertyName}>`;
525
1018
  } else {
526
1019
  type = `System.Collections.Generic.List<${getCSharpTypeFromMushroomType(source, field.items.type, field.items.validation && field.items.validation.required)}>`;
@@ -531,7 +1024,7 @@ function generateCSharpClassDriver(source, className, fields, description, out)
531
1024
  ` /// <summary>
532
1025
  /// ${singleLine(field.description)}
533
1026
  /// </summary>
534
- [JsonProperty(PropertyName ="${fieldName}", NullValueHandling = NullValueHandling.Ignore)]
1027
+ [Newtonsoft.Json.JsonProperty(PropertyName ="${fieldName}", NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore${type === "System.Datetime" ? ", DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore" : ""})]
535
1028
  public ${type} ${propertyName} { get; set; }
536
1029
 
537
1030
  `;
@@ -545,15 +1038,15 @@ function generateCSharpClassDriver(source, className, fields, description, out)
545
1038
  }
546
1039
 
547
1040
 
548
- content += " }\r\n";
549
- return strClasses + "\r\n" + content;
1041
+ content += " }" + newLine;
1042
+ return strClasses + newLine + content;
550
1043
  }
551
1044
 
552
1045
  function genCSharpDriver(args, projectName, project, alias, source) {
553
1046
  const aliasProject = ((project.csharpDriver || {}).alias || {})[alias];
554
1047
 
555
1048
  if (!aliasProject) {
556
- throw new Error(`Not found gen c#-driver configuration. Please run 'npx mr config ${projectName} gen c#-driver OUTPUT_FILE.cs${alias === "default" ? "" : " alias " + alias}' first`);
1049
+ throw new Error(`Not found gen c#-driver configuration. Please run 'npx mushroom-cli config ${projectName} gen c#-driver OUTPUT_FILE.cs${alias === "default" ? "" : " alias " + alias}' first`);
557
1050
  }
558
1051
 
559
1052
  const entities = common.getEntities(source, aliasProject.allowRoles);
@@ -578,8 +1071,8 @@ function genCSharpDriver(args, projectName, project, alias, source) {
578
1071
  var className = toCSharpName(entityName);
579
1072
 
580
1073
  strClasses += generateCSharpClassDriver(source, className, entities[entityName].fields, entities[entityName].description, out);
581
- codeStaticCtor += ` ${className} = new ${className}Connector(client);\r\n`;
582
- codeStaticProperties += ` public static ${className}Connector ${className} { get; }\r\n\r\n`;
1074
+ codeStaticCtor += ` ${className} = new ${className}Connector(client);${newLine}`;
1075
+ codeStaticProperties += ` public static ${className}Connector ${className} { get; }${newLine}${newLine}`;
583
1076
 
584
1077
  var entity = entities[entityName];
585
1078
 
@@ -689,7 +1182,7 @@ function genCSharpDriver(args, projectName, project, alias, source) {
689
1182
  if (actionName.indexOf("_raw_http_method_"))
690
1183
  break;
691
1184
 
692
- var customMethod = toCSharpName(actionName.substr("_raw_http_method_".length));
1185
+ var customMethod = toCSharpName(actionName.substring("_raw_http_method_".length));
693
1186
 
694
1187
  codeConnectors += ` public async System.Threading.Tasks.Task<${className}${customMethod}Result> ${customMethod}(${className}${customMethod}Arg arg)
695
1188
  {
@@ -738,11 +1231,11 @@ function genCSharpDriver(args, projectName, project, alias, source) {
738
1231
 
739
1232
  partial void BuildCustomUrl();
740
1233
 
741
- private string OriginUrl => "${entityName}s/${actionName.substr("_raw_http_method_".length)}";
1234
+ private string OriginUrl => "${entityName}s/${actionName.substring("_raw_http_method_".length)}";
742
1235
 
743
- private string CustomUrl { get; set; } = "${entityName}s/${actionName.substr("_raw_http_method_".length)}";
1236
+ private string CustomUrl { get; set; } = "${entityName}s/${actionName.substring("_raw_http_method_".length)}";
744
1237
 
745
- public override string Method { get; } = "${actionName.substr("_raw_http_method_".length)}";
1238
+ public override string Method { get; } = "${actionName.substring("_raw_http_method_".length)}";
746
1239
 
747
1240
  public ${className}${customMethod}Body Data { get; set; }
748
1241
 
@@ -797,7 +1290,7 @@ function genCSharpDriver(args, projectName, project, alias, source) {
797
1290
  var type = getCSharpTypeFromMushroomType(source, p.type, p.validation && p.validation.required);
798
1291
  if (p.isArray)
799
1292
  type = `System.Collections.Generic.List<${type}>`;
800
- viewExtraClass += ` [JsonProperty(PropertyName = "${p.field}")]
1293
+ viewExtraClass += ` [Newtonsoft.Json.JsonProperty(PropertyName = "${p.field}")]
801
1294
  public ${type} ${toCSharpName(p.field)} { get; set; }
802
1295
 
803
1296
  `;
@@ -833,15 +1326,15 @@ function genCSharpDriver(args, projectName, project, alias, source) {
833
1326
  ${viewExtraClass}`;
834
1327
  }
835
1328
 
836
- codeConnectors += " }\r\n\r\n";
1329
+ codeConnectors += " }" + newLine + newLine;
837
1330
  }
838
1331
 
839
1332
  if (out.strEnumClasses)
840
1333
  strEnumClasses += out.strEnumClasses;
841
1334
 
842
- const code = `// This file was generated by Mushroom CLI (https://www.npmjs.com/package/mushroom-cli), please do not modify
1335
+ const code = `// This file was generated by Mushroom CLI ${package.version} (https://www.npmjs.com/package/mushroom-cli), please do not modify
843
1336
 
844
- // Require package: Mushroom.Driver version 1.4.0 or later https://www.nuget.org/packages/Mushroom.Driver/
1337
+ // Require package: Mushroom.Driver version 1.4.0 or later (https://www.nuget.org/packages/Mushroom.Driver/)
845
1338
 
846
1339
  // ReSharper disable InconsistentNaming
847
1340
  // ReSharper disable PartialTypeWithSinglePart