mushroom-cli 1.1.0-alpha.2 → 1.1.0-alpha.21

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,437 @@ ${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
+ public static async System.Threading.Tasks.Task<T> FindByIdAsync<T, TId>(this IMongoCollection<T> collection, TId id) where T : Mushroom.Models.IResource<TId>
915
+ {
916
+ return await (await collection.FindAsync(Builders<T>.Filter.Eq(doc => doc.Id, id))).FirstOrDefaultAsync();
917
+ }
918
+
919
+ 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>
920
+ {
921
+ return await (await collection.FindAsync(Builders<T>.Filter.Eq(doc => doc.Id, id), findOptions)).FirstOrDefaultAsync();
922
+ }
923
+
924
+ 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>
925
+ {
926
+ return await (await collection.FindAsync(Builders<T>.Filter.Eq(doc => doc.Id, id), new FindOptions<T> { Projection = projection })).FirstOrDefaultAsync();
927
+ }
928
+ }
929
+ }
930
+ `;
931
+
932
+ const resourceNamesFileContent = `${header}
933
+
934
+ namespace ${namespace}
935
+ {
936
+ public class ResourceNames
937
+ {
938
+ private ResourceNames() { }
939
+
940
+ ${resourceNames}
941
+ }
942
+ }
943
+ `;
944
+
945
+ const roleNamesFileContent = `${header}
946
+
947
+ namespace ${namespace}
948
+ {
949
+ public class RoleNames
950
+ {
951
+ private RoleNames() { }
952
+
953
+ ${roleNames}
954
+ }
955
+ }
956
+ `;
957
+
958
+
959
+ const refactorHelperFileContent = `${header}
960
+
961
+ #if DEBUG
962
+ namespace ${namespace}
963
+ {
964
+ class RefactorHelper
965
+ {
966
+ private RefactorHelper() { }
967
+ private void RegisterCustomMethod(System.Func<Mushroom.ActionArguments, System.Threading.Tasks.Task> fn) { }
968
+ private void RegisterCustomMethod(System.Action<Mushroom.ActionArguments> fn) { }
969
+ private void RegisterCustomViewMethod(System.Func<Mushroom.ViewArguments, System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<object>>> fn) { }
970
+ private void RegisterCustomViewMethod(System.Action<Mushroom.ViewArguments> fn) { }
971
+ private void RegisterCustomVnTextBuilderMethod(System.Func<System.Collections.Generic.IEnumerable<string>, System.Collections.Generic.IEnumerable<string>> fn) { }
972
+ private void RegisterEvent(System.Func<object, Mushroom.ActionArguments, System.Threading.Tasks.Task> fn) { }
973
+ private void RegisterEvent(System.Action<object, Mushroom.ActionArguments> fn) { }
974
+ private void RegisterJob<T>() where T : Mushroom.Job.JobBase { }
975
+ private void Help()
976
+ {
977
+ ${strDelegatorReferences}
978
+ ${strViewHandlerReferences}
979
+ ${strVnTextChannels}
980
+ ${strEventHandlerReferences}
981
+ ${strJobReferences}
982
+ }
983
+ }
984
+ }
985
+ #endif
986
+ `;
987
+
988
+ const infoFileContent = `// Mushroom CLI version: ${package.version}${newLine}// Compatible with Mushroom Server version: 0.2.18 or higher (https://www.nuget.org/packages/Mushroom/)`
989
+
990
+ fs.writeFileSync(aliasProject.output + "/DbConnector.cs", dbConnectorFileContent);
991
+ fs.writeFileSync(aliasProject.output + "/ResourceNames.cs", resourceNamesFileContent);
992
+ fs.writeFileSync(aliasProject.output + "/RoleNames.cs", roleNamesFileContent);
993
+ fs.writeFileSync(aliasProject.output + "/RefactorHelper.cs", refactorHelperFileContent);
994
+ fs.writeFileSync(aliasProject.output + "/Info.cs", infoFileContent);
995
+
996
+ console.log(`Generated CSharp MongoDb Classes for ${projectName}@${alias} to folder ${aliasProject.output}`);
997
+ }
491
998
  //#endregion
492
999
 
493
1000
  //#region CSharp Driver
@@ -515,12 +1022,12 @@ function generateCSharpClassDriver(source, className, fields, description, out)
515
1022
  const propertyName = toCSharpName(fieldName);
516
1023
  let type;
517
1024
  if (field.type === "object") {
518
- strClasses += generateCSharpClassDriver(source, className + "_" + propertyName, field.fields, null, out) + "\r\n";
1025
+ strClasses += generateCSharpClassDriver(source, className + "_" + propertyName, field.fields, null, out) + newLine;
519
1026
  type = className + "_" + propertyName;
520
1027
  }
521
1028
  else if (field.type === "array") {
522
1029
  if (field.items.type === "object") {
523
- strClasses += generateCSharpClassDriver(source, className + "_" + propertyName, field.items.fields, null, out) + "\r\n";
1030
+ strClasses += generateCSharpClassDriver(source, className + "_" + propertyName, field.items.fields, null, out) + newLine;
524
1031
  type = `System.Collections.Generic.List<${className}_${propertyName}>`;
525
1032
  } else {
526
1033
  type = `System.Collections.Generic.List<${getCSharpTypeFromMushroomType(source, field.items.type, field.items.validation && field.items.validation.required)}>`;
@@ -531,7 +1038,7 @@ function generateCSharpClassDriver(source, className, fields, description, out)
531
1038
  ` /// <summary>
532
1039
  /// ${singleLine(field.description)}
533
1040
  /// </summary>
534
- [JsonProperty(PropertyName ="${fieldName}", NullValueHandling = NullValueHandling.Ignore)]
1041
+ [Newtonsoft.Json.JsonProperty(PropertyName ="${fieldName}", NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore${type === "System.Datetime" ? ", DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore" : ""})]
535
1042
  public ${type} ${propertyName} { get; set; }
536
1043
 
537
1044
  `;
@@ -545,15 +1052,15 @@ function generateCSharpClassDriver(source, className, fields, description, out)
545
1052
  }
546
1053
 
547
1054
 
548
- content += " }\r\n";
549
- return strClasses + "\r\n" + content;
1055
+ content += " }" + newLine;
1056
+ return strClasses + newLine + content;
550
1057
  }
551
1058
 
552
1059
  function genCSharpDriver(args, projectName, project, alias, source) {
553
1060
  const aliasProject = ((project.csharpDriver || {}).alias || {})[alias];
554
1061
 
555
1062
  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`);
1063
+ 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
1064
  }
558
1065
 
559
1066
  const entities = common.getEntities(source, aliasProject.allowRoles);
@@ -578,8 +1085,8 @@ function genCSharpDriver(args, projectName, project, alias, source) {
578
1085
  var className = toCSharpName(entityName);
579
1086
 
580
1087
  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`;
1088
+ codeStaticCtor += ` ${className} = new ${className}Connector(client);${newLine}`;
1089
+ codeStaticProperties += ` public static ${className}Connector ${className} { get; }${newLine}${newLine}`;
583
1090
 
584
1091
  var entity = entities[entityName];
585
1092
 
@@ -689,7 +1196,7 @@ function genCSharpDriver(args, projectName, project, alias, source) {
689
1196
  if (actionName.indexOf("_raw_http_method_"))
690
1197
  break;
691
1198
 
692
- var customMethod = toCSharpName(actionName.substr("_raw_http_method_".length));
1199
+ var customMethod = toCSharpName(actionName.substring("_raw_http_method_".length));
693
1200
 
694
1201
  codeConnectors += ` public async System.Threading.Tasks.Task<${className}${customMethod}Result> ${customMethod}(${className}${customMethod}Arg arg)
695
1202
  {
@@ -738,11 +1245,11 @@ function genCSharpDriver(args, projectName, project, alias, source) {
738
1245
 
739
1246
  partial void BuildCustomUrl();
740
1247
 
741
- private string OriginUrl => "${entityName}s/${actionName.substr("_raw_http_method_".length)}";
1248
+ private string OriginUrl => "${entityName}s/${actionName.substring("_raw_http_method_".length)}";
742
1249
 
743
- private string CustomUrl { get; set; } = "${entityName}s/${actionName.substr("_raw_http_method_".length)}";
1250
+ private string CustomUrl { get; set; } = "${entityName}s/${actionName.substring("_raw_http_method_".length)}";
744
1251
 
745
- public override string Method { get; } = "${actionName.substr("_raw_http_method_".length)}";
1252
+ public override string Method { get; } = "${actionName.substring("_raw_http_method_".length)}";
746
1253
 
747
1254
  public ${className}${customMethod}Body Data { get; set; }
748
1255
 
@@ -797,7 +1304,7 @@ function genCSharpDriver(args, projectName, project, alias, source) {
797
1304
  var type = getCSharpTypeFromMushroomType(source, p.type, p.validation && p.validation.required);
798
1305
  if (p.isArray)
799
1306
  type = `System.Collections.Generic.List<${type}>`;
800
- viewExtraClass += ` [JsonProperty(PropertyName = "${p.field}")]
1307
+ viewExtraClass += ` [Newtonsoft.Json.JsonProperty(PropertyName = "${p.field}")]
801
1308
  public ${type} ${toCSharpName(p.field)} { get; set; }
802
1309
 
803
1310
  `;
@@ -833,15 +1340,15 @@ function genCSharpDriver(args, projectName, project, alias, source) {
833
1340
  ${viewExtraClass}`;
834
1341
  }
835
1342
 
836
- codeConnectors += " }\r\n\r\n";
1343
+ codeConnectors += " }" + newLine + newLine;
837
1344
  }
838
1345
 
839
1346
  if (out.strEnumClasses)
840
1347
  strEnumClasses += out.strEnumClasses;
841
1348
 
842
- const code = `// This file was generated by Mushroom CLI (https://www.npmjs.com/package/mushroom-cli), please do not modify
1349
+ const code = `// This file was generated by Mushroom CLI ${package.version} (https://www.npmjs.com/package/mushroom-cli), please do not modify
843
1350
 
844
- // Require package: Mushroom.Driver version 1.4.0 or later https://www.nuget.org/packages/Mushroom.Driver/
1351
+ // Require package: Mushroom.Driver version 1.4.0 or later (https://www.nuget.org/packages/Mushroom.Driver/)
845
1352
 
846
1353
  // ReSharper disable InconsistentNaming
847
1354
  // ReSharper disable PartialTypeWithSinglePart