mushroom-cli 1.1.2 → 1.2.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/gen/gen-csharp.js CHANGED
@@ -1,1687 +1,1399 @@
1
- const fs = require("fs");
2
- const common = require("../common.js");
3
- const package_json = require("./../package.json");
4
-
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
-
25
- function singleLine(str) {
26
- if (!str) return "";
27
- return str.replace(/\r/g, "").replace(/\n/g, "<br/>");
28
- }
29
-
30
- function toVietnameseNonTongue(str) {
31
- const signText =
32
- "ăâđêôơưàảãạáằẳẵặắầẩẫậấèẻẽẹéềểễệếìỉĩịíòỏõọóồổỗộốờởỡợớùủũụúừửữựứỳỷỹỵýĂÂĐÐÊÔƠƯÀẢÃẠÁẰẲẴẶẮẦẨẪẬẤÈẺẼẸÉỀỂỄỆẾÌỈĨỊÍÒỎÕỌÓỒỔỖỘỐỜỞỠỢỚÙỦŨỤÚỪỬỮỰỨỲỶỸỴÝ";
33
- const unsignedText =
34
- "aadeoouaaaaaaaaaaaaaaaeeeeeeeeeeiiiiiooooooooooooooouuuuuuuuuuyyyyyAADDEOOUAAAAAAAAAAAAAAAEEEEEEEEEEIIIIIOOOOOOOOOOOOOOOUUUUUUUUUUYYYYY";
35
- let returnValue = "";
36
- for (let i = 0; i < str.length; i++) {
37
- const index = signText.indexOf(str.charAt(i));
38
- returnValue += index !== -1 ? unsignedText.charAt(index) : str.charAt(i);
39
- }
40
- return returnValue;
41
- }
42
-
43
- function toCSharpName(str) {
44
- if (!str) return "_";
45
- const name = toVietnameseNonTongue(str).replace(/\W/g, "_");
46
- const c = name.charAt(0);
47
- return (
48
- ("0" <= c && c <= "9" ? "_" : "") + c.toUpperCase() + name.substring(1)
49
- );
50
- }
51
-
52
- function getCSharpTypeFromMushroomType(source, type, required) {
53
- switch (type) {
54
- case "string":
55
- return "string";
56
- case "object":
57
- return "";
58
- case "boolean":
59
- return required ? "bool" : "bool?";
60
- case "integer":
61
- return required ? "int" : "int?";
62
- case "long":
63
- return required ? "long" : "long?";
64
- case "double":
65
- return required ? "double" : "double?";
66
- case "array":
67
- return "";
68
- case "datetime":
69
- return required ? "System.DateTime" : "System.DateTime?";
70
- case "IdRef":
71
- case "AutoId":
72
- if (source.idType === "ObjectId" || source.idType === "GUID")
73
- return "string";
74
- if (source.idType === "AutoIncInt") return "int";
75
- if (source.idType === "AutoIncLong") return "long";
76
- }
77
- return "UNKNOWN_TYPE";
78
- }
79
-
80
- function getCSharpInitValue(csType, value) {
81
- switch (csType) {
82
- case "string":
83
- return JSON.stringify(value);
84
- case "int":
85
- return parseInt(Number(value));
86
- case "long":
87
- return parseInt(Number(value)) + "L";
88
- case "double":
89
- return Number(value);
90
- case "bool":
91
- if (value === "false") return false;
92
- if (value === "true") return true;
93
- return "NotABoolean";
94
- case "datetime":
95
- return `System.DateTime.Parse(${JSON.stringify(value)})`;
96
- default:
97
- return "UNSUPPORTED";
98
- }
99
- }
100
-
101
- function generateEnumClass(source, out, field, defaultClassName) {
102
- if (!out) return "";
103
-
104
- let strEnumClasses = "";
105
- const validation =
106
- field.type === "array" ? field.items.validation : field.validation;
107
- if (!validation) return "";
108
-
109
- if (!validation.validValues) return "";
110
-
111
- const mrType = field.type === "array" ? field.items.type : field.type;
112
- if (mrType == "object" || mrType == "array") {
113
- console.log("Unsuported enum type for type ", mrType, field);
114
- return "";
115
- }
116
-
117
- const type = getCSharpTypeFromMushroomType(source, mrType, true);
118
-
119
- validation.codeHint = validation.codeHint || {};
120
- if (validation.validValues) {
121
- validation.codeHint.validValues = validation.codeHint.validValues || {};
122
-
123
- if (!validation.codeHint.validValues.disabled) {
124
- const enumClassName =
125
- validation.codeHint.validValues.className || defaultClassName;
126
-
127
- out.arrEnumClassNames = out.arrEnumClassNames || [];
128
-
129
- if (out.arrEnumClassNames.indexOf(enumClassName) === -1) {
130
- out.arrEnumClassNames.push(enumClassName);
131
- strEnumClasses += ` /// <summary>
132
- /// ${singleLine(validation.codeHint.validValues.description || field.description)}
133
- /// </summary>
134
- public class ${enumClassName}
135
- {
136
- private ${enumClassName}() { }
137
-
138
- `;
139
- const enumProperties =
140
- validation.codeHint.validValues.nameMap || validation.validValues;
141
- for (
142
- let i = 0;
143
- i < enumProperties.length && i < validation.validValues.length;
144
- i++
145
- ) {
146
- strEnumClasses += ` public const ${type} ${toCSharpName(enumProperties[i])} = ${getCSharpInitValue(type, validation.validValues[i])};
147
- `;
148
- }
149
- strEnumClasses += ` }
150
-
151
- `;
152
- }
153
- }
154
- }
155
-
156
- return strEnumClasses;
157
- }
158
- //#endregion
159
-
160
- //#region CSharp MongoDb Classes
161
- function generateCSharpClassMongoDb(
162
- source,
163
- className,
164
- fields,
165
- isRoot,
166
- description,
167
- out,
168
- ) {
169
- let strClasses = "";
170
- let strEnumClasses = "";
171
- let content = "";
172
- if (description) {
173
- content += ` /// <summary>
174
- /// ${singleLine(description)}
175
- /// </summary>
176
- `;
177
- }
178
- let supperClass = "";
179
- if (isRoot) {
180
- // thêm cho trường hợp không khai báo id hoặc id.type
181
- if (!fields.id) {
182
- fields.id = {
183
- type: "AutoId",
184
- };
185
- }
186
- if (!fields.id.type) fields.id.type = "AutoId";
187
-
188
- supperClass =
189
- " : Mushroom.Models.IResource<" +
190
- getCSharpTypeFromMushroomType(source, fields.id.type, true) +
191
- ">";
192
- }
193
- content += ` public class ${className}${supperClass}
194
- {
195
- `;
196
- for (const fieldName in fields) {
197
- if (!fields.hasOwnProperty(fieldName)) continue;
198
-
199
- const field = fields[fieldName];
200
- let type;
201
- const propertyName = toCSharpName(fieldName);
202
- if (field.codeHint && field.codeHint.type && field.codeHint.type.csharp) {
203
- type = field.codeHint.type.csharp;
204
- } else if (field.type === "object") {
205
- strClasses +=
206
- generateCSharpClassMongoDb(
207
- source,
208
- className + "_" + propertyName,
209
- field.fields,
210
- false,
211
- null,
212
- out,
213
- ) + newLine;
214
- type = className + "_" + propertyName;
215
- } else if (field.type === "array") {
216
- if (field.items.type === "object") {
217
- strClasses +=
218
- generateCSharpClassMongoDb(
219
- source,
220
- className + "_" + propertyName,
221
- field.items.fields,
222
- false,
223
- null,
224
- out,
225
- ) + newLine;
226
- type = `System.Collections.Generic.List<${className}_${propertyName}>`;
227
- } else {
228
- type = `System.Collections.Generic.List<${getCSharpTypeFromMushroomType(source, field.items.type, field.items.validation && field.items.validation.required)}>`;
229
- }
230
- } else
231
- type = getCSharpTypeFromMushroomType(
232
- source,
233
- field.type,
234
- field.validation && field.validation.required,
235
- );
236
- content += ` /// <summary>
237
- /// ${singleLine(field.description)}
238
- /// </summary>
239
- `;
240
-
241
- if (isRoot && fieldName === "id") {
242
- content += ` [MongoDB.Bson.Serialization.Attributes.BsonId${field.type === "AutoId" && source.idType === "GUID" ? "(IdGenerator = typeof(MongoDB.Bson.Serialization.IdGenerators.GuidGenerator))" : ""}]${newLine}`;
243
- }
244
- content += ` [MongoDB.Bson.Serialization.Attributes.BsonElement("${isRoot && fieldName === "id" ? "_id" : fieldName}")]
245
- [MongoDB.Bson.Serialization.Attributes.BsonIgnoreIfNull]
246
- [Newtonsoft.Json.JsonProperty(PropertyName = "${fieldName}", NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore${type === "System.DateTime" ? ", DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore" : ""})]
247
- `;
248
- if (
249
- (field.type === "AutoId" || field.type === "IdRef") &&
250
- source.idType === "ObjectId"
251
- ) {
252
- content +=
253
- " [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)]" +
254
- newLine;
255
- }
256
- if (field.type === "AutoId" && source.idType === "GUID") {
257
- content +=
258
- " [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.String)]" +
259
- newLine;
260
- }
261
- if (field.type === "datetime") {
262
- content +=
263
- " [MongoDB.Bson.Serialization.Attributes.BsonDateTimeOptions(Kind = System.DateTimeKind.Local)]" +
264
- newLine;
265
- }
266
- if (field.type === "array") {
267
- if (
268
- (field.items.type === "AutoId" || field.items.type === "IdRef") &&
269
- source.idType === "ObjectId"
270
- ) {
271
- content +=
272
- " [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)]" +
273
- newLine;
274
- }
275
- if (field.items.type === "AutoId" && source.idType === "GUID") {
276
- content +=
277
- " [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.String)]" +
278
- newLine;
279
- }
280
- if (field.items.type === "datetime") {
281
- content +=
282
- " [MongoDB.Bson.Serialization.Attributes.BsonDateTimeOptions(Kind = System.DateTimeKind.Local)]" +
283
- newLine;
284
- }
285
- }
286
-
287
- content += ` public ${type} ${propertyName} { get; set; }${newLine}${newLine}`;
288
-
289
- strEnumClasses += generateEnumClass(
290
- source,
291
- out,
292
- field,
293
- `${className.toUpperCase()}_${propertyName.toUpperCase()}_ENUM`,
294
- );
295
- }
296
- content += ` [MongoDB.Bson.Serialization.Attributes.BsonExtraElements]
297
- public System.Collections.Generic.Dictionary<string, object> Mushroom_ExtraProperties { get; set; }
298
-
299
- }
300
- `;
301
- if (strEnumClasses) {
302
- out.strEnumClasses = out.strEnumClasses || "";
303
-
304
- out.strEnumClasses += strEnumClasses;
305
- }
306
-
307
- return strClasses + newLine + content;
308
- }
309
-
310
- function getCSharpFunc(methodName, methodType) {
311
- if (methodType === "static") return methodName;
312
- const idx = methodName.lastIndexOf(".");
313
- if (idx === -1) return methodName;
314
- return `new ${methodName.substring(0, idx)}()${methodName.substring(idx)}`;
315
- }
316
-
317
- function genCSharpMongoDbClasses(args, projectName, project, alias, source) {
318
- const aliasProject = ((project.csharpMongo || {}).alias || {})[alias];
319
-
320
- if (!aliasProject) {
321
- throw new Error(
322
- `Not found gen c#-mongo configuration. Please run 'npx mushroom-cli config ${projectName} gen c#-mongo OUTPUT_FILE.cs${alias === "default" ? "" : " alias " + alias}' first`,
323
- );
324
- }
325
-
326
- if (aliasProject.outputToFolder) {
327
- genCSharpMongoDbClassesToFolder(projectName, alias, source, aliasProject);
328
- return;
329
- }
330
-
331
- const entities = common.getEntities(source, aliasProject.allowRoles, true);
332
-
333
- const namespace = toCSharpName(source.name);
334
-
335
- let strClasses = "";
336
- let strEnumClasses = "";
337
- let collectionNames = "";
338
- let resourceNames = "";
339
- let roleNames = "";
340
-
341
- source.roles?.forEach((role) => {
342
- if (!role.name) return;
343
- roleNames += `
344
- /// <summary>
345
- /// ${role.description ?? ""}
346
- /// </summary>
347
- public static string ${toCSharpName(role.name)} => "${role.name}";
348
- `;
349
- });
350
-
351
- const out = {};
352
- for (let entityName in entities) {
353
- if (!entities.hasOwnProperty(entityName)) continue;
354
-
355
- const className = toCSharpName(entityName);
356
- collectionNames += ` public static string ${className}CollectionName => "${entities[entityName].storageName}";
357
- public static IMongoCollection<Resources.${className}> ${className}Collection => GetDatabase().GetCollection<Resources.${className}>(${className}CollectionName);
358
- `;
359
- resourceNames += ` public static string ${className} => "${entityName}";${newLine}`;
360
- strClasses += generateCSharpClassMongoDb(
361
- source,
362
- className,
363
- entities[entityName].fields,
364
- true,
365
- entities[entityName].description,
366
- out,
367
- );
368
-
369
- const actions = entities[entityName].actions || {};
370
- for (let actionName in actions) {
371
- const action = actions[actionName];
372
- if (!Array.isArray(action)) continue;
373
-
374
- action.forEach((a) => {
375
- if (!a) return;
376
- if (
377
- typeof a.delegator === "string" &&
378
- a.delegator.indexOf("lib:") === 0
379
- ) {
380
- out.delegators = out.delegators || [];
381
- const method = a.delegator.substring(4);
382
- let type =
383
- a.codeHint && a.codeHint.delegator && a.codeHint.delegator.csharp
384
- ? a.codeHint.delegator.csharp.methodType
385
- : null;
386
- if (type !== "non-static") type = "static";
387
- out.delegators.push({
388
- method: method,
389
- source: `entity: ${entityName}, action: ${actionName}, grant: ${a.grant}`,
390
- type: type,
391
- });
392
- }
393
-
394
- if (!a.events && typeof a.events !== "object") return;
395
-
396
- for (let eventName in a.events) {
397
- if (!Array.isArray(a.events[eventName])) return;
398
-
399
- out.eventHandlers = out.eventHandlers || [];
400
- a.events[eventName].forEach((ev, i) => {
401
- if (typeof ev !== "string" || ev.indexOf("lib:") !== 0) return;
402
- const method = ev.substring(4);
403
- let type =
404
- a.codeHint &&
405
- a.codeHint.events &&
406
- Array.isArray(a.codeHint.events[eventName]) &&
407
- a.codeHint.events[eventName][i] &&
408
- a.codeHint.events[eventName][i].csharp
409
- ? a.codeHint.events[eventName][i].csharp.methodType
410
- : null;
411
- if (type !== "non-static") type = "static";
412
- out.eventHandlers.push({
413
- method: method,
414
- source: `entity: ${entityName}, action: ${actionName}, grant: ${a.grant}, event: ${eventName}`,
415
- type: type,
416
- });
417
- });
418
- }
419
- });
420
- }
421
-
422
- const views = entities[entityName].views || {};
423
- for (let viewName in views) {
424
- const view = views[viewName];
425
- if (!Array.isArray(view)) continue;
426
-
427
- view.forEach((v) => {
428
- if (!v) return;
429
-
430
- if (typeof v.query === "string" && v.query.indexOf("lib:") === 0) {
431
- out.viewHandlers = out.viewHandlers || [];
432
- const method = v.query.substring(4);
433
- let type =
434
- v.codeHint && v.codeHint.query && v.codeHint.query.csharp
435
- ? v.codeHint.query.csharp.methodType
436
- : null;
437
- if (type !== "non-static") type = "static";
438
- out.viewHandlers.push({
439
- method: method,
440
- source: `entity: ${entityName}, view: ${viewName}, grant: ${v.grant}`,
441
- type: type,
442
- });
443
- }
444
- });
445
- }
446
-
447
- const channels = entities[entityName].features?.vn_text?.channels;
448
- if (channels != null) {
449
- channels.forEach((channel) => {
450
- if (
451
- !channel.nativeBuilder ||
452
- typeof channel.nativeBuilder !== "string" ||
453
- channel.nativeBuilder.indexOf("lib:") !== 0
454
- )
455
- return;
456
-
457
- out.vnTextChannels = out.vnTextChannels || [];
458
- const method = channel.nativeBuilder.substring(4);
459
- let type =
460
- channel.codeHint &&
461
- channel.codeHint.nativeBuilder &&
462
- channel.codeHint.nativeBuilder.csharp
463
- ? channel.codeHint.nativeBuilder.csharp.methodType
464
- : null;
465
- if (type !== "non-static") type = "static";
466
- out.vnTextChannels.push({
467
- method: method,
468
- source: `entity: ${entityName}, feature: vn_text, channel: ${channel.name}`,
469
- type: type,
470
- });
471
- });
472
- }
473
- }
474
-
475
- if (out.strEnumClasses) strEnumClasses += out.strEnumClasses;
476
-
477
- const delegators = (out.delegators || []).reduce((prev, cur) => {
478
- if (cur.method in prev) {
479
- if (prev[cur.method].indexOf(cur.source) === -1) {
480
- prev[cur.method].push(cur);
481
- }
482
- } else {
483
- prev[cur.method] = [cur];
484
- }
485
- return prev;
486
- }, {});
487
- const strDelegatorReferences = Object.keys(delegators)
488
- .map(
489
- (method) =>
490
- delegators[method]
491
- .map((ev) => ` // ${ev.source}`)
492
- .join(newLine) +
493
- newLine +
494
- ` RegisterCustomMethod(${getCSharpFunc(method, delegators[method][0].type)});`,
495
- )
496
- .join(newLine);
497
-
498
- const viewHandlers = (out.viewHandlers || []).reduce((prev, cur) => {
499
- if (cur.method in prev) {
500
- if (prev[cur.method].indexOf(cur.source) === -1) {
501
- prev[cur.method].push(cur);
502
- }
503
- } else {
504
- prev[cur.method] = [cur];
505
- }
506
- return prev;
507
- }, {});
508
- const strViewHandlerReferences = Object.keys(viewHandlers)
509
- .map(
510
- (method) =>
511
- viewHandlers[method]
512
- .map((ev) => ` // ${ev.source}`)
513
- .join(newLine) +
514
- newLine +
515
- ` RegisterCustomViewMethod(${getCSharpFunc(method, viewHandlers[method][0].type)});`,
516
- )
517
- .join(newLine);
518
-
519
- const vnTextChannels = (out.vnTextChannels || []).reduce((prev, cur) => {
520
- if (cur.method in prev) {
521
- if (prev[cur.method].indexOf(cur.source) === -1) {
522
- prev[cur.method].push(cur);
523
- }
524
- } else {
525
- prev[cur.method] = [cur];
526
- }
527
- return prev;
528
- }, {});
529
- const strVnTextChannels = Object.keys(vnTextChannels)
530
- .map(
531
- (method) =>
532
- vnTextChannels[method]
533
- .map((channel) => ` // ${channel.source}`)
534
- .join(newLine) +
535
- newLine +
536
- ` RegisterCustomVnTextBuilderMethod(${getCSharpFunc(method, vnTextChannels[method][0].type)});`,
537
- )
538
- .join(newLine);
539
-
540
- const eventHandlers = (out.eventHandlers || []).reduce((prev, cur) => {
541
- if (cur.method in prev) {
542
- if (prev[cur.method].indexOf(cur.source) === -1) {
543
- prev[cur.method].push(cur);
544
- }
545
- } else {
546
- prev[cur.method] = [cur];
547
- }
548
- return prev;
549
- }, {});
550
- const strEventHandlerReferences = Object.keys(eventHandlers)
551
- .map(
552
- (method) =>
553
- eventHandlers[method]
554
- .map((ev) => ` // ${ev.source}`)
555
- .join(newLine) +
556
- newLine +
557
- ` RegisterEvent(${getCSharpFunc(method, eventHandlers[method][0].type)});`,
558
- )
559
- .join(newLine);
560
-
561
- const strJobReferences = Array.isArray(source.jobs)
562
- ? source.jobs
563
- .filter(
564
- (job) =>
565
- job !== null &&
566
- typeof job === "object" &&
567
- job.action &&
568
- typeof job.action === "string" &&
569
- job.action.indexOf("lib:") === 0,
570
- )
571
- .map(
572
- (job) =>
573
- ` RegisterJob<${job.action.substring(4).split(",")[0]}>();`,
574
- )
575
- .join(newLine)
576
- : "";
577
-
578
- const code = `// This file was generated by Mushroom CLI ${package_json.version} (https://www.npmjs.com/package/mushroom-cli), please do not modify
579
-
580
- // NOTE: Compatible with Mushroom Server version 0.2.18 or higher (https://www.nuget.org/packages/Mushroom/)
581
-
582
- // ReSharper disable RedundantUsingDirective
583
- // ReSharper disable InconsistentNaming
584
- // ReSharper disable PartialTypeWithSinglePart
585
- // ReSharper disable UnusedMember.Global
586
- // ReSharper disable UnusedMember.Local
587
- // ReSharper disable UnusedParameter.Local
588
- // ReSharper disable IdentifierTypo
589
- // ReSharper disable StringLiteralTypo
590
- // ReSharper disable CommentTypo
591
- // ReSharper disable EmptyNamespace
592
-
593
- namespace ${namespace}
594
- {
595
- using MongoDB.Driver;
596
-
597
- public static class DbConnector
598
- {
599
- ${collectionNames}
600
- public static IMongoDatabase GetDatabase() => Mushroom.MushroomDaoFactory.GetDbAdapter() as IMongoDatabase;
601
-
602
- public static async System.Threading.Tasks.Task<T> FindByIdAsync<T, TId>(this IMongoCollection<T> collection, TId id) where T : Mushroom.Models.IResource<TId>
603
- {
604
- return await (await collection.FindAsync(Builders<T>.Filter.Eq(doc => doc.Id, id))).FirstOrDefaultAsync();
605
- }
606
-
607
- 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>
608
- {
609
- return await (await collection.FindAsync(Builders<T>.Filter.Eq(doc => doc.Id, id), findOptions)).FirstOrDefaultAsync();
610
- }
611
-
612
- 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>
613
- {
614
- return await (await collection.FindAsync(Builders<T>.Filter.Eq(doc => doc.Id, id), new FindOptions<T> { Projection = projection })).FirstOrDefaultAsync();
615
- }
616
- }
617
-
618
- public class ResourceNames
619
- {
620
- private ResourceNames() { }
621
-
622
- ${resourceNames}
623
- }
624
-
625
- public class RoleNames {
626
- private RoleNames() { }
627
-
628
- ${roleNames}
629
- }
630
- }
631
-
632
- namespace ${namespace}.Resources
633
- {
634
- ${strClasses}
635
- }
636
-
637
- namespace ${namespace}.Enums
638
- {
639
- ${strEnumClasses}
640
- }
641
-
642
- #if DEBUG
643
- namespace ${namespace}.CodeHelper
644
- {
645
- class RefactorHelper
646
- {
647
- private RefactorHelper() { }
648
- private void RegisterCustomMethod(System.Func<Mushroom.ActionArguments, System.Threading.Tasks.Task> fn) { }
649
- private void RegisterCustomMethod(System.Action<Mushroom.ActionArguments> fn) { }
650
- private void RegisterCustomViewMethod(System.Func<Mushroom.ViewArguments, System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<object>>> fn) { }
651
- private void RegisterCustomViewMethod(System.Action<Mushroom.ViewArguments> fn) { }
652
- private void RegisterCustomVnTextBuilderMethod(System.Func<System.Collections.Generic.IEnumerable<string>, System.Collections.Generic.IEnumerable<string>> fn) { }
653
- private void RegisterEvent(System.Func<object, Mushroom.ActionArguments, System.Threading.Tasks.Task> fn) { }
654
- private void RegisterEvent(System.Action<object, Mushroom.ActionArguments> fn) { }
655
- private void RegisterJob<T>() where T : Mushroom.Job.JobBase { }
656
- private void Help()
657
- {
658
- ${strDelegatorReferences}
659
- ${strViewHandlerReferences}
660
- ${strVnTextChannels}
661
- ${strEventHandlerReferences}
662
- ${strJobReferences}
663
- }
664
- }
665
- }
666
- #endif
667
- `;
668
-
669
- common.ensureFolder(aliasProject.output);
670
-
671
- fs.writeFile(aliasProject.output, code, (err) => {
672
- if (err) throw err;
673
- console.log(
674
- `Generated CSharp MongoDb Classes for ${projectName}@${alias} to ${aliasProject.output}`,
675
- );
676
- });
677
- }
678
-
679
- function generateCSharpClassMongoDbToFolder(
680
- source,
681
- className,
682
- fields,
683
- isRoot,
684
- description,
685
- out,
686
- aliasProject,
687
- ) {
688
- let content = "";
689
- const namespace = toCSharpName(source.name);
690
- if (description) {
691
- content += ` /// <summary>
692
- /// ${singleLine(description)}
693
- /// </summary>
694
- `;
695
- }
696
- let supperClass = "";
697
- if (isRoot) {
698
- // thêm cho trường hợp không khai báo id hoặc id.type
699
- if (!fields.id) {
700
- fields.id = {
701
- type: "AutoId",
702
- };
703
- }
704
- if (!fields.id.type) fields.id.type = "AutoId";
705
-
706
- supperClass =
707
- " : Mushroom.Models.IResource<" +
708
- getCSharpTypeFromMushroomType(source, fields.id.type, true) +
709
- ">";
710
- }
711
- content += ` public class ${className}${supperClass}
712
- {
713
- `;
714
- for (const fieldName in fields) {
715
- if (!fields.hasOwnProperty(fieldName)) continue;
716
-
717
- const field = fields[fieldName];
718
- let type;
719
- const propertyName = toCSharpName(fieldName);
720
- if (field.codeHint && field.codeHint.type && field.codeHint.type.csharp) {
721
- type = field.codeHint.type.csharp;
722
- } else if (field.type === "object") {
723
- generateCSharpClassMongoDbToFolder(
724
- source,
725
- className + "_" + propertyName,
726
- field.fields,
727
- false,
728
- null,
729
- out,
730
- aliasProject,
731
- );
732
- type = className + "_" + propertyName;
733
- } else if (field.type === "array") {
734
- if (field.items.type === "object") {
735
- generateCSharpClassMongoDbToFolder(
736
- source,
737
- className + "_" + propertyName,
738
- field.items.fields,
739
- false,
740
- null,
741
- out,
742
- aliasProject,
743
- );
744
- type = `System.Collections.Generic.List<${className}_${propertyName}>`;
745
- } else {
746
- type = `System.Collections.Generic.List<${getCSharpTypeFromMushroomType(source, field.items.type, field.items.validation && field.items.validation.required)}>`;
747
- }
748
- } else
749
- type = getCSharpTypeFromMushroomType(
750
- source,
751
- field.type,
752
- field.validation && field.validation.required,
753
- );
754
- content += ` /// <summary>
755
- /// ${singleLine(field.description)}
756
- /// </summary>
757
- `;
758
-
759
- if (isRoot && fieldName === "id") {
760
- content += ` [MongoDB.Bson.Serialization.Attributes.BsonId${field.type === "AutoId" && source.idType === "GUID" ? "(IdGenerator = typeof(MongoDB.Bson.Serialization.IdGenerators.GuidGenerator))" : ""}]${newLine}`;
761
- }
762
- content += ` [MongoDB.Bson.Serialization.Attributes.BsonElement("${isRoot && fieldName === "id" ? "_id" : fieldName}")]
763
- [MongoDB.Bson.Serialization.Attributes.BsonIgnoreIfNull]
764
- [Newtonsoft.Json.JsonProperty(PropertyName = "${fieldName}", NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore${type === "System.DateTime" ? ", DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore" : ""})]
765
- `;
766
- if (
767
- (field.type === "AutoId" || field.type === "IdRef") &&
768
- source.idType === "ObjectId"
769
- ) {
770
- content +=
771
- " [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)]" +
772
- newLine;
773
- }
774
- if (field.type === "AutoId" && source.idType === "GUID") {
775
- content +=
776
- " [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.String)]" +
777
- newLine;
778
- }
779
- if (field.type === "datetime") {
780
- content +=
781
- " [MongoDB.Bson.Serialization.Attributes.BsonDateTimeOptions(Kind = System.DateTimeKind.Local)]" +
782
- newLine;
783
- }
784
- if (field.type === "array") {
785
- if (
786
- (field.items.type === "AutoId" || field.items.type === "IdRef") &&
787
- source.idType === "ObjectId"
788
- ) {
789
- content +=
790
- " [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)]" +
791
- newLine;
792
- }
793
- if (field.items.type === "AutoId" && source.idType === "GUID") {
794
- content +=
795
- " [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.String)]" +
796
- newLine;
797
- }
798
- if (field.items.type === "datetime") {
799
- content +=
800
- " [MongoDB.Bson.Serialization.Attributes.BsonDateTimeOptions(Kind = System.DateTimeKind.Local)]" +
801
- newLine;
802
- }
803
- }
804
-
805
- content += ` public ${type} ${propertyName} { get; set; }
806
-
807
- `;
808
-
809
- let strEnumClasses = generateEnumClass(
810
- source,
811
- {},
812
- field,
813
- `${className.toUpperCase()}_${propertyName.toUpperCase()}_ENUM`,
814
- );
815
-
816
- const match = strEnumClasses.match(/public class\s+(\w+)/);
817
- if (!match) continue;
818
- common.ensureFolder(aliasProject.output + "/Enums", true);
819
- strEnumClasses = `${header}
820
-
821
- namespace ${namespace}.Enums
822
- {
823
- ${strEnumClasses}
824
- }
825
- `;
826
-
827
- fs.writeFileSync(
828
- aliasProject.output + "/Enums/" + match[1] + ".cs",
829
- strEnumClasses,
830
- );
831
- }
832
-
833
- content += ` [MongoDB.Bson.Serialization.Attributes.BsonExtraElements]
834
- [Newtonsoft.Json.JsonIgnore]
835
- public System.Collections.Generic.Dictionary<string, object> Mushroom_ExtraProperties { get; set; }
836
-
837
- }
838
- `;
839
-
840
- common.ensureFolder(aliasProject.output + "/Resources", true);
841
-
842
- content = `${header}
843
-
844
- namespace ${namespace}.Resources
845
- {
846
- ${content}
847
- }
848
- `;
849
-
850
- out.allClasses = out.allClasses || [];
851
-
852
- const normalizedName = className.toLowerCase();
853
- const duplicate = out.allClasses.find(
854
- (c) => c.normalizedName == normalizedName,
855
- );
856
- if (duplicate) {
857
- fs.appendFileSync(
858
- aliasProject.output + "/Resources/" + duplicate.className + ".cs",
859
- content,
860
- );
861
- } else {
862
- out.allClasses.push({
863
- className,
864
- normalizedName,
865
- });
866
- fs.writeFileSync(
867
- aliasProject.output + "/Resources/" + className + ".cs",
868
- content,
869
- );
870
- }
871
- }
872
-
873
- function genCSharpMongoDbClassesToFolder(
874
- projectName,
875
- alias,
876
- source,
877
- aliasProject,
878
- ) {
879
- if (fs.existsSync(aliasProject.output)) {
880
- try {
881
- fs.unlinkSync(aliasProject.output); // xóa file nếu có
882
- } catch (e) {}
883
- try {
884
- fs.rmSync(aliasProject.output, { recursive: true, force: true }); // xóa thư mục nếu có
885
- } catch (e) {}
886
- }
887
- fs.mkdirSync(aliasProject.output, { recursive: true, mode: 493 }); // 493 = 755 in octa
888
-
889
- const entities = common.getEntities(source, aliasProject.allowRoles, true);
890
-
891
- const namespace = toCSharpName(source.name);
892
-
893
- let collectionNames = "";
894
- let resourceNames = "";
895
- let roleNames = "";
896
-
897
- source.roles?.forEach((role) => {
898
- if (!role.name) return;
899
- roleNames += `
900
- /// <summary>
901
- /// ${role.description ?? ""}
902
- /// </summary>
903
- public static string ${toCSharpName(role.name)} => "${role.name}";
904
- `;
905
- });
906
-
907
- const out = {};
908
- for (let entityName in entities) {
909
- if (!entities.hasOwnProperty(entityName)) continue;
910
-
911
- const className = toCSharpName(entityName);
912
- collectionNames += ` public static string ${className}CollectionName => "${entities[entityName].storageName}";
913
- public static IMongoCollection<Resources.${className}> ${className}Collection => GetDatabase().GetCollection<Resources.${className}>(${className}CollectionName);
914
- `;
915
- resourceNames += ` public static string ${className} => "${entityName}";
916
- `;
917
-
918
- generateCSharpClassMongoDbToFolder(
919
- source,
920
- className,
921
- entities[entityName].fields,
922
- true,
923
- entities[entityName].description,
924
- out,
925
- aliasProject,
926
- );
927
-
928
- const actions = entities[entityName].actions || {};
929
- for (let actionName in actions) {
930
- const action = actions[actionName];
931
- if (!Array.isArray(action)) continue;
932
-
933
- action.forEach((a) => {
934
- if (!a) return;
935
- if (
936
- typeof a.delegator === "string" &&
937
- a.delegator.indexOf("lib:") === 0
938
- ) {
939
- out.delegators = out.delegators || [];
940
- const method = a.delegator.substring(4);
941
- let type =
942
- a.codeHint && a.codeHint.delegator && a.codeHint.delegator.csharp
943
- ? a.codeHint.delegator.csharp.methodType
944
- : null;
945
- if (type !== "non-static") type = "static";
946
- out.delegators.push({
947
- method: method,
948
- source: `entity: ${entityName}, action: ${actionName}, grant: ${a.grant}`,
949
- type: type,
950
- });
951
- }
952
-
953
- if (!a.events && typeof a.events !== "object") return;
954
-
955
- for (let eventName in a.events) {
956
- if (!Array.isArray(a.events[eventName])) return;
957
-
958
- out.eventHandlers = out.eventHandlers || [];
959
- a.events[eventName].forEach((ev, i) => {
960
- if (typeof ev !== "string" || ev.indexOf("lib:") !== 0) return;
961
- const method = ev.substring(4);
962
- let type =
963
- a.codeHint &&
964
- a.codeHint.events &&
965
- Array.isArray(a.codeHint.events[eventName]) &&
966
- a.codeHint.events[eventName][i] &&
967
- a.codeHint.events[eventName][i].csharp
968
- ? a.codeHint.events[eventName][i].csharp.methodType
969
- : null;
970
- if (type !== "non-static") type = "static";
971
- out.eventHandlers.push({
972
- method: method,
973
- source: `entity: ${entityName}, action: ${actionName}, grant: ${a.grant}, event: ${eventName}`,
974
- type: type,
975
- });
976
- });
977
- }
978
- });
979
- }
980
-
981
- const views = entities[entityName].views || {};
982
- for (let viewName in views) {
983
- const view = views[viewName];
984
- if (!Array.isArray(view)) continue;
985
-
986
- view.forEach((v) => {
987
- if (!v) return;
988
-
989
- if (typeof v.query === "string" && v.query.indexOf("lib:") === 0) {
990
- out.viewHandlers = out.viewHandlers || [];
991
- const method = v.query.substring(4);
992
- let type =
993
- v.codeHint && v.codeHint.query && v.codeHint.query.csharp
994
- ? v.codeHint.query.csharp.methodType
995
- : null;
996
- if (type !== "non-static") type = "static";
997
- out.viewHandlers.push({
998
- method: method,
999
- source: `entity: ${entityName}, view: ${viewName}, grant: ${v.grant}`,
1000
- type: type,
1001
- });
1002
- }
1003
- });
1004
- }
1005
-
1006
- const channels = entities[entityName].features?.vn_text?.channels;
1007
- if (channels != null) {
1008
- channels.forEach((channel) => {
1009
- if (
1010
- !channel.nativeBuilder ||
1011
- typeof channel.nativeBuilder !== "string" ||
1012
- channel.nativeBuilder.indexOf("lib:") !== 0
1013
- )
1014
- return;
1015
-
1016
- out.vnTextChannels = out.vnTextChannels || [];
1017
- const method = channel.nativeBuilder.substring(4);
1018
- let type =
1019
- channel.codeHint &&
1020
- channel.codeHint.nativeBuilder &&
1021
- channel.codeHint.nativeBuilder.csharp
1022
- ? channel.codeHint.nativeBuilder.csharp.methodType
1023
- : null;
1024
- if (type !== "non-static") type = "static";
1025
- out.vnTextChannels.push({
1026
- method: method,
1027
- source: `entity: ${entityName}, feature: vn_text, channel: ${channel.name}`,
1028
- type: type,
1029
- });
1030
- });
1031
- }
1032
- }
1033
-
1034
- const delegators = (out.delegators || []).reduce((prev, cur) => {
1035
- if (cur.method in prev) {
1036
- if (prev[cur.method].indexOf(cur.source) === -1) {
1037
- prev[cur.method].push(cur);
1038
- }
1039
- } else {
1040
- prev[cur.method] = [cur];
1041
- }
1042
- return prev;
1043
- }, {});
1044
- const strDelegatorReferences = Object.keys(delegators)
1045
- .map(
1046
- (method) =>
1047
- delegators[method]
1048
- .map((ev) => ` // ${ev.source}`)
1049
- .join(newLine) +
1050
- newLine +
1051
- ` RegisterCustomMethod(${getCSharpFunc(method, delegators[method][0].type)});`,
1052
- )
1053
- .join(newLine);
1054
-
1055
- const viewHandlers = (out.viewHandlers || []).reduce((prev, cur) => {
1056
- if (cur.method in prev) {
1057
- if (prev[cur.method].indexOf(cur.source) === -1) {
1058
- prev[cur.method].push(cur);
1059
- }
1060
- } else {
1061
- prev[cur.method] = [cur];
1062
- }
1063
- return prev;
1064
- }, {});
1065
- const strViewHandlerReferences = Object.keys(viewHandlers)
1066
- .map(
1067
- (method) =>
1068
- viewHandlers[method]
1069
- .map((ev) => ` // ${ev.source}`)
1070
- .join(newLine) +
1071
- newLine +
1072
- ` RegisterCustomViewMethod(${getCSharpFunc(method, viewHandlers[method][0].type)});`,
1073
- )
1074
- .join(newLine);
1075
-
1076
- const vnTextChannels = (out.vnTextChannels || []).reduce((prev, cur) => {
1077
- if (cur.method in prev) {
1078
- if (prev[cur.method].indexOf(cur.source) === -1) {
1079
- prev[cur.method].push(cur);
1080
- }
1081
- } else {
1082
- prev[cur.method] = [cur];
1083
- }
1084
- return prev;
1085
- }, {});
1086
- const strVnTextChannels = Object.keys(vnTextChannels)
1087
- .map(
1088
- (method) =>
1089
- vnTextChannels[method]
1090
- .map((channel) => ` // ${channel.source}`)
1091
- .join(newLine) +
1092
- newLine +
1093
- ` RegisterCustomVnTextBuilderMethod(${getCSharpFunc(method, vnTextChannels[method][0].type)});`,
1094
- )
1095
- .join(newLine);
1096
-
1097
- const eventHandlers = (out.eventHandlers || []).reduce((prev, cur) => {
1098
- if (cur.method in prev) {
1099
- if (prev[cur.method].indexOf(cur.source) === -1) {
1100
- prev[cur.method].push(cur);
1101
- }
1102
- } else {
1103
- prev[cur.method] = [cur];
1104
- }
1105
- return prev;
1106
- }, {});
1107
- const strEventHandlerReferences = Object.keys(eventHandlers)
1108
- .map(
1109
- (method) =>
1110
- eventHandlers[method]
1111
- .map((ev) => ` // ${ev.source}`)
1112
- .join(newLine) +
1113
- newLine +
1114
- ` RegisterEvent(${getCSharpFunc(method, eventHandlers[method][0].type)});`,
1115
- )
1116
- .join(newLine);
1117
-
1118
- const strJobReferences = Array.isArray(source.jobs)
1119
- ? source.jobs
1120
- .filter(
1121
- (job) =>
1122
- job !== null &&
1123
- typeof job === "object" &&
1124
- job.action &&
1125
- typeof job.action === "string" &&
1126
- job.action.indexOf("lib:") === 0,
1127
- )
1128
- .map(
1129
- (job) =>
1130
- ` RegisterJob<${job.action.substring(4).split(",")[0]}>();`,
1131
- )
1132
- .join(newLine)
1133
- : "";
1134
-
1135
- const dbConnectorFileContent = `${header}
1136
- using MongoDB.Driver;
1137
-
1138
- namespace ${namespace}
1139
- {
1140
- public static class DbConnector
1141
- {
1142
- ${collectionNames}
1143
- public static IMongoDatabase GetDatabase() => Mushroom.MushroomDaoFactory.GetDbAdapter() as IMongoDatabase;
1144
- }
1145
- }
1146
- `;
1147
-
1148
- const resourceNamesFileContent = `${header}
1149
-
1150
- namespace ${namespace}
1151
- {
1152
- public class ResourceNames
1153
- {
1154
- private ResourceNames() { }
1155
-
1156
- ${resourceNames}
1157
- }
1158
- }
1159
- `;
1160
-
1161
- const roleNamesFileContent = `${header}
1162
-
1163
- namespace ${namespace}
1164
- {
1165
- public class RoleNames
1166
- {
1167
- private RoleNames() { }
1168
-
1169
- ${roleNames}
1170
- }
1171
- }
1172
- `;
1173
-
1174
- const refactorHelperFileContent = `${header}
1175
-
1176
- #if DEBUG
1177
- namespace ${namespace}
1178
- {
1179
- class RefactorHelper
1180
- {
1181
- private RefactorHelper() { }
1182
- private void RegisterCustomMethod(System.Func<Mushroom.ActionArguments, System.Threading.Tasks.Task> fn) { }
1183
- private void RegisterCustomMethod(System.Action<Mushroom.ActionArguments> fn) { }
1184
- private void RegisterCustomViewMethod(System.Func<Mushroom.ViewArguments, System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<object>>> fn) { }
1185
- private void RegisterCustomViewMethod(System.Action<Mushroom.ViewArguments> fn) { }
1186
- private void RegisterCustomVnTextBuilderMethod(System.Func<System.Collections.Generic.IEnumerable<string>, System.Collections.Generic.IEnumerable<string>> fn) { }
1187
- private void RegisterEvent(System.Func<object, Mushroom.ActionArguments, System.Threading.Tasks.Task> fn) { }
1188
- private void RegisterEvent(System.Action<object, Mushroom.ActionArguments> fn) { }
1189
- private void RegisterJob<T>() where T : Mushroom.Job.JobBase { }
1190
- private void Help()
1191
- {
1192
- ${strDelegatorReferences}
1193
- ${strViewHandlerReferences}
1194
- ${strVnTextChannels}
1195
- ${strEventHandlerReferences}
1196
- ${strJobReferences}
1197
- }
1198
- }
1199
- }
1200
- #endif
1201
- `;
1202
-
1203
- const infoFileContent = `// Mushroom CLI version: ${package_json.version}${newLine}// Compatible with Mushroom Server version: 0.2.25.4 or higher (https://www.nuget.org/packages/Mushroom/)
1204
- // For Mushroom Server 0.2.18 to 0.2.25.4: Please remove all FindById methods in DbConnector.cs`;
1205
-
1206
- fs.writeFileSync(
1207
- aliasProject.output + "/DbConnector.cs",
1208
- dbConnectorFileContent,
1209
- );
1210
- fs.writeFileSync(
1211
- aliasProject.output + "/ResourceNames.cs",
1212
- resourceNamesFileContent,
1213
- );
1214
- fs.writeFileSync(aliasProject.output + "/RoleNames.cs", roleNamesFileContent);
1215
- fs.writeFileSync(
1216
- aliasProject.output + "/RefactorHelper.cs",
1217
- refactorHelperFileContent,
1218
- );
1219
- fs.writeFileSync(aliasProject.output + "/Info.cs", infoFileContent);
1220
-
1221
- console.log(
1222
- `Generated CSharp MongoDb Classes for ${projectName}@${alias} to folder ${aliasProject.output}`,
1223
- );
1224
- }
1225
- //#endregion
1226
-
1227
- //#region CSharp Driver
1228
- function generateCSharpClassDriver(
1229
- source,
1230
- className,
1231
- fields,
1232
- description,
1233
- out,
1234
- ) {
1235
- let strClasses = "";
1236
- let strEnumClasses = "";
1237
- let content = "";
1238
- if (description) {
1239
- content += ` /// <summary>
1240
- /// ${singleLine(description)}
1241
- /// </summary>
1242
- `;
1243
- }
1244
- content += ` public partial class ${className}
1245
- {
1246
- `;
1247
-
1248
- for (let fieldName in fields) {
1249
- if (!fields.hasOwnProperty(fieldName)) continue;
1250
-
1251
- const field = fields[fieldName];
1252
-
1253
- const propertyName = toCSharpName(fieldName);
1254
- let type;
1255
- if (field.type === "object") {
1256
- strClasses +=
1257
- generateCSharpClassDriver(
1258
- source,
1259
- className + "_" + propertyName,
1260
- field.fields,
1261
- null,
1262
- out,
1263
- ) + newLine;
1264
- type = className + "_" + propertyName;
1265
- } else if (field.type === "array") {
1266
- if (field.items.type === "object") {
1267
- strClasses +=
1268
- generateCSharpClassDriver(
1269
- source,
1270
- className + "_" + propertyName,
1271
- field.items.fields,
1272
- null,
1273
- out,
1274
- ) + newLine;
1275
- type = `System.Collections.Generic.List<${className}_${propertyName}>`;
1276
- } else {
1277
- type = `System.Collections.Generic.List<${getCSharpTypeFromMushroomType(source, field.items.type, field.items.validation && field.items.validation.required)}>`;
1278
- }
1279
- } else
1280
- type = getCSharpTypeFromMushroomType(
1281
- source,
1282
- field.type,
1283
- field.validation && field.validation.required,
1284
- );
1285
- content += ` /// <summary>
1286
- /// ${singleLine(field.description)}
1287
- /// </summary>
1288
- [Newtonsoft.Json.JsonProperty(PropertyName ="${fieldName}", NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore${type === "System.Datetime" ? ", DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore" : ""})]
1289
- public ${type} ${propertyName} { get; set; }
1290
-
1291
- `;
1292
- strEnumClasses += generateEnumClass(
1293
- source,
1294
- out,
1295
- field,
1296
- `${className.toUpperCase()}_${propertyName.toUpperCase()}_ENUM`,
1297
- );
1298
- }
1299
-
1300
- if (strEnumClasses) {
1301
- out.strEnumClasses = out.strEnumClasses || "";
1302
-
1303
- out.strEnumClasses += strEnumClasses;
1304
- }
1305
-
1306
- content += " }" + newLine;
1307
- return strClasses + newLine + content;
1308
- }
1309
-
1310
- function genCSharpDriver(args, projectName, project, alias, source) {
1311
- const aliasProject = ((project.csharpDriver || {}).alias || {})[alias];
1312
-
1313
- if (!aliasProject) {
1314
- throw new Error(
1315
- `Not found gen c#-driver configuration. Please run 'npx mushroom-cli config ${projectName} gen c#-driver OUTPUT_FILE.cs${alias === "default" ? "" : " alias " + alias}' first`,
1316
- );
1317
- }
1318
-
1319
- const entities = common.getEntities(source, aliasProject.allowRoles);
1320
-
1321
- const namespace = toCSharpName(source.name);
1322
-
1323
- let strClasses = "";
1324
- let strEnumClasses = "";
1325
- let codeStaticCtor = "";
1326
- let codeStaticProperties = "";
1327
- let codeConnectors = "";
1328
- let codeExtraClasses = "";
1329
-
1330
- const out = {};
1331
-
1332
- let accessModifier = aliasProject.accessModifier || "internal";
1333
-
1334
- for (const entityName in entities) {
1335
- if (!entities.hasOwnProperty(entityName)) continue;
1336
-
1337
- const className = toCSharpName(entityName);
1338
-
1339
- strClasses += generateCSharpClassDriver(
1340
- source,
1341
- className,
1342
- entities[entityName].fields,
1343
- entities[entityName].description,
1344
- out,
1345
- );
1346
- codeStaticCtor += ` ${className} = new ${className}Connector(client);${newLine}`;
1347
- codeStaticProperties += ` public static ${className}Connector ${className} { get; }${newLine}${newLine}`;
1348
-
1349
- const entity = entities[entityName];
1350
-
1351
- codeConnectors += ` ${accessModifier} partial class ${className}Connector : MushroomDriver.MushroomResourceConnector<${className}>
1352
- {
1353
- protected override string Resource { get; } = ${JSON.stringify(entityName)};
1354
-
1355
- `;
1356
-
1357
- if (Object.keys(entity.views).length) {
1358
- codeConnectors += ` public ${className}Connector(MushroomDriver.MushroomClient client) : base(client)
1359
- {
1360
- Views = new ${className}Views(Client, () => Resource);
1361
- }
1362
-
1363
- `;
1364
- } else {
1365
- codeConnectors += ` public ${className}Connector(MushroomDriver.MushroomClient client) : base(client) { }
1366
-
1367
- `;
1368
- }
1369
-
1370
- for (const actionName in entity.actions) {
1371
- if (!entity.actions.hasOwnProperty(actionName)) continue;
1372
-
1373
- switch (actionName) {
1374
- case "findMany":
1375
- codeConnectors += ` public System.Threading.Tasks.Task<System.Collections.Generic.List<${className}>> List(MushroomDriver.ListArg arg = null)
1376
- {
1377
- return InternalList(arg);
1378
- }
1379
-
1380
- `;
1381
- break;
1382
- case "findById":
1383
- codeConnectors += ` public System.Threading.Tasks.Task<${className}> FindById(MushroomDriver.FindByIdArg arg)
1384
- {
1385
- return InternalFindById(arg);
1386
- }
1387
-
1388
- `;
1389
- break;
1390
- case "createOne":
1391
- codeConnectors += ` public System.Threading.Tasks.Task<string> Create(MushroomDriver.CreateArg<${className}> arg)
1392
- {
1393
- return InternalCreate(arg);
1394
- }
1395
-
1396
- `;
1397
- break;
1398
- case "createMany":
1399
- codeConnectors += ` public System.Threading.Tasks.Task<System.Collections.Generic.List<string>> Create(MushroomDriver.BatchCreateArg<${className}> arg)
1400
- {
1401
- return InternalCreate(arg);
1402
- }
1403
-
1404
- `;
1405
- break;
1406
- case "updateOne":
1407
- codeConnectors += ` public System.Threading.Tasks.Task<string> Update(MushroomDriver.UpdateArg<${className}> arg)
1408
- {
1409
- return InternalUpdate(arg);
1410
- }
1411
-
1412
- `;
1413
- break;
1414
- case "updateMany":
1415
- codeConnectors += ` public System.Threading.Tasks.Task<System.Collections.Generic.List<string>> Update(MushroomDriver.BatchUpdateArg<${className}> arg)
1416
- {
1417
- return InternalUpdate(arg);
1418
- }
1419
-
1420
- `;
1421
- break;
1422
- case "updatePartially":
1423
- codeConnectors += ` public System.Threading.Tasks.Task<string> Update(MushroomDriver.PartialUpdateArg<${className}> arg)
1424
- {
1425
- return InternalUpdate(arg);
1426
- }
1427
-
1428
- public System.Threading.Tasks.Task<string> Update(MushroomDriver.PartialUpdateArg<System.Collections.Generic.Dictionary<string, object>> arg)
1429
- {
1430
- return InternalUpdate(arg);
1431
- }
1432
-
1433
- `;
1434
- break;
1435
- case "deleteOne":
1436
- codeConnectors += ` public System.Threading.Tasks.Task<long> Delete(MushroomDriver.DeleteArg arg)
1437
- {
1438
- return InternalDelete(arg);
1439
- }
1440
-
1441
- `;
1442
- break;
1443
- case "deleteMany":
1444
- codeConnectors += ` public System.Threading.Tasks.Task<long> Delete(MushroomDriver.BatchDeleteArg arg)
1445
- {
1446
- return InternalDelete(arg);
1447
- }
1448
-
1449
- `;
1450
- break;
1451
- default:
1452
- // if not start with _raw_http_method_ --> break;
1453
- if (actionName.indexOf("_raw_http_method_")) break;
1454
-
1455
- const customMethod = toCSharpName(
1456
- actionName.substring("_raw_http_method_".length),
1457
- );
1458
-
1459
- codeConnectors += ` public async System.Threading.Tasks.Task<${className}${customMethod}Result> ${customMethod}(${className}${customMethod}Arg arg)
1460
- {
1461
- if (arg == null)
1462
- throw new System.ArgumentNullException(nameof(arg));
1463
-
1464
- var request = new MushroomDriver.MushroomRequest
1465
- {
1466
- RootApiUrl = Client.RootApiUrl,
1467
- Url = Client.RootApiUrl + arg.BuildUrl(),
1468
- Method = arg.Method
1469
- };
1470
- var headers = new System.Collections.Generic.Dictionary<string, string>
1471
- {
1472
- {"X-Requested-With", "Mushroom Driver " + MushroomDriver.MushroomConnector.Version}
1473
- };
1474
- if (arg.UseXHttpMethodOverride)
1475
- {
1476
- headers["X-Http-Method-Override"] = request.Method;
1477
- request.Method = "POST";
1478
- }
1479
- request.Headers = headers;
1480
- request.Data = arg.CustomData ?? arg.Data;
1481
- var response = await MushroomDriver.MushroomConnector.Execute(request);
1482
- var result = response.GetResult<${className}${customMethod}Result>();
1483
- result.MushroomResponseMetadata = response.Metadata;
1484
- return result;
1485
- }
1486
-
1487
- `;
1488
-
1489
- codeExtraClasses += ` ${accessModifier} partial class ${className}${customMethod}Result
1490
- {
1491
- public System.Collections.Generic.Dictionary<string, object> MushroomResponseMetadata { get; set; }
1492
- }
1493
-
1494
- ${accessModifier} partial class ${className}${customMethod}Body { }
1495
-
1496
- ${accessModifier} partial class ${className}${customMethod}Arg : MushroomDriver.MushroomRequestArg
1497
- {
1498
- public override string BuildUrl()
1499
- {
1500
- BuildCustomUrl();
1501
- return CustomUrl;
1502
- }
1503
-
1504
- partial void BuildCustomUrl();
1505
-
1506
- private string OriginUrl => "${entityName}s/${actionName.substring("_raw_http_method_".length)}";
1507
-
1508
- private string CustomUrl { get; set; } = "${entityName}s/${actionName.substring("_raw_http_method_".length)}";
1509
-
1510
- public override string Method { get; } = "${actionName.substring("_raw_http_method_".length)}";
1511
-
1512
- public ${className}${customMethod}Body Data { get; set; }
1513
-
1514
- public object CustomData { get; set; }
1515
- }
1516
-
1517
- `;
1518
- break;
1519
- }
1520
- }
1521
-
1522
- if (Object.keys(entity.views).length) {
1523
- codeConnectors += ` public ${className}Views Views { get; }
1524
-
1525
- `;
1526
- codeExtraClasses += ` ${accessModifier} partial class ${className}Views : MushroomDriver.MushroomViewConnector
1527
- {
1528
- protected System.Func<string> FnResource;
1529
-
1530
- public ${className}Views(MushroomDriver.MushroomClient client, System.Func<string> fnResource) : base(client)
1531
- {
1532
- FnResource = fnResource;
1533
- }
1534
-
1535
- `;
1536
- let viewExtraClass = "";
1537
- for (let viewName in entity.views) {
1538
- if (!entity.views.hasOwnProperty(viewName)) continue;
1539
-
1540
- let viewMethodName = toCSharpName(viewName);
1541
-
1542
- let hasNoParamView = false;
1543
- entity.views[viewName].forEach((view) => {
1544
- let role = view.grant === "*" ? "" : `_${toCSharpName(view.grant)}`;
1545
- let hasParameter = view.parameters && view.parameters.length;
1546
- if (hasParameter) {
1547
- codeExtraClasses += ` public System.Threading.Tasks.Task<System.Collections.Generic.List<${className}View_${viewMethodName}Result>> ${viewMethodName}(${className}View${role}_${viewMethodName}Arg arg)
1548
- {
1549
- return InternalExecuteView<${className}View_${viewMethodName}Result>(new MushroomDriver.ViewArg<${className}View${role}_${viewMethodName}Arg> {
1550
- Parameters = arg,
1551
- Resource = FnResource?.Invoke(),
1552
- ViewName = "${viewName}"
1553
- });
1554
- }
1555
-
1556
- `;
1557
- viewExtraClass += ` ${accessModifier} partial class ${className}View${role}_${viewMethodName}Arg
1558
- {
1559
- `;
1560
- view.parameters.forEach((p) => {
1561
- let type = getCSharpTypeFromMushroomType(
1562
- source,
1563
- p.type,
1564
- p.validation && p.validation.required,
1565
- );
1566
- if (p.isArray) type = `System.Collections.Generic.List<${type}>`;
1567
- viewExtraClass += ` [Newtonsoft.Json.JsonProperty(PropertyName = "${p.field}")]
1568
- public ${type} ${toCSharpName(p.field)} { get; set; }
1569
-
1570
- `;
1571
- });
1572
- viewExtraClass += ` }
1573
-
1574
- `;
1575
- } else if (!hasNoParamView) {
1576
- hasNoParamView = true;
1577
- codeExtraClasses += ` public System.Threading.Tasks.Task<System.Collections.Generic.List<${className}View_${viewMethodName}Result>> ${viewMethodName}()
1578
- {
1579
- return InternalExecuteView<${className}View_${viewMethodName}Result>(new MushroomDriver.ViewArg {
1580
- Resource = FnResource?.Invoke(),
1581
- ViewName = "${viewName}"
1582
- });
1583
- }
1584
-
1585
- `;
1586
- }
1587
- });
1588
-
1589
- viewExtraClass += ` ${accessModifier} partial class ${className}View_${viewMethodName}Result
1590
- {
1591
-
1592
- }
1593
-
1594
- `;
1595
- }
1596
- codeExtraClasses += ` }
1597
-
1598
- ${viewExtraClass}`;
1599
- }
1600
-
1601
- codeConnectors += " }" + newLine + newLine;
1602
- }
1603
-
1604
- if (out.strEnumClasses) strEnumClasses += out.strEnumClasses;
1605
-
1606
- const code = `// This file was generated by Mushroom CLI ${package_json.version} (https://www.npmjs.com/package/mushroom-cli), please do not modify
1607
-
1608
- // Require package: Mushroom.Driver version 1.4.0 or later (https://www.nuget.org/packages/Mushroom.Driver/)
1609
-
1610
- // ReSharper disable InconsistentNaming
1611
- // ReSharper disable PartialTypeWithSinglePart
1612
- // ReSharper disable PartialMethodWithSinglePart
1613
- // ReSharper disable UnusedMember.Global
1614
- // ReSharper disable UnusedMember.Local
1615
- // ReSharper disable IdentifierTypo
1616
- // ReSharper disable StringLiteralTypo
1617
- // ReSharper disable CommentTypo
1618
- // ReSharper disable AutoPropertyCanBeMadeGetOnly.Local
1619
-
1620
-
1621
- using JsonPropertyAttribute = Newtonsoft.Json.JsonPropertyAttribute;
1622
- using NullValueHandling = Newtonsoft.Json.NullValueHandling;
1623
- using ${namespace}.Resources;
1624
-
1625
- namespace ${namespace}
1626
- {
1627
- ${accessModifier} partial class API
1628
- {
1629
- static API()
1630
- {
1631
- CustomizeRootApiUrl();
1632
- var client = new MushroomDriver.MushroomClient(_rootApiUrl);
1633
- MushroomClient = client;
1634
-
1635
- ${Array.isArray(aliasProject.features) && aliasProject.features.indexOf("auth") !== -1 ? "Authentication = new MushroomDriver.Auth.Authentication(_rootApiUrl);" : ""}
1636
- ${Array.isArray(aliasProject.features) && aliasProject.features.indexOf("file") !== -1 ? "FileExtension = new MushroomDriver.File.FileExtension(_rootApiUrl);" : ""}
1637
-
1638
- ${codeStaticCtor}
1639
- }
1640
-
1641
- static partial void CustomizeRootApiUrl();
1642
-
1643
- private static string _rootApiUrl = ${JSON.stringify(common.getRootUrl(source))};
1644
-
1645
- public static MushroomDriver.MushroomClient MushroomClient { get; }
1646
-
1647
- ${Array.isArray(aliasProject.features) && aliasProject.features.indexOf("auth") !== -1 ? "public static MushroomDriver.Auth.Authentication Authentication { get; }" : ""}
1648
-
1649
- ${Array.isArray(aliasProject.features) && aliasProject.features.indexOf("file") !== -1 ? "public static MushroomDriver.File.FileExtension FileExtension { get; }" : ""}
1650
-
1651
- ${codeStaticProperties}
1652
- }
1653
-
1654
- /*${accessModifier} partial class API
1655
- {
1656
- static partial void CustomizeRootApiUrl()
1657
- {
1658
- _rootApiUrl = "your customized root api url";
1659
- }
1660
- }*/
1661
-
1662
- ${codeConnectors}${codeExtraClasses}
1663
- }
1664
-
1665
- namespace ${namespace}.Resources
1666
- {
1667
- ${strClasses}
1668
- }
1669
-
1670
- namespace ${namespace}.Enums
1671
- {
1672
- ${strEnumClasses}
1673
- }`;
1674
-
1675
- common.ensureFolder(aliasProject.output);
1676
-
1677
- fs.writeFileSync(aliasProject.output, code);
1678
- console.log(
1679
- `Generated CSharp Driver for ${projectName}@${alias} to ${aliasProject.output}`,
1680
- );
1681
- }
1682
- //#endregion
1683
-
1684
- module.exports = {
1685
- genCSharpMongoDbClasses: genCSharpMongoDbClasses,
1686
- genCSharpDriver: genCSharpDriver,
1687
- };
1
+ const fs = require("fs");
2
+ const common = require("../common.js");
3
+ const package = require("./../package.json");
4
+
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
+
25
+ function singleLine(str) {
26
+ if (!str)
27
+ return "";
28
+ return str.replace(/\r/g, "").replace(/\n/g, "<br/>");
29
+ }
30
+
31
+ function toVietnameseNonTongue(str) {
32
+ const signText = "ăâđêôơưàảãạáằẳẵặắầẩẫậấèẻẽẹéềểễệếìỉĩịíòỏõọóồổỗộốờởỡợớùủũụúừửữựứỳỷỹỵýĂÂĐÐÊÔƠƯÀẢÃẠÁẰẲẴẶẮẦẨẪẬẤÈẺẼẸÉỀỂỄỆẾÌỈĨỊÍÒỎÕỌÓỒỔỖỘỐỜỞỠỢỚÙỦŨỤÚỪỬỮỰỨỲỶỸỴÝ";
33
+ const unsignedText = "aadeoouaaaaaaaaaaaaaaaeeeeeeeeeeiiiiiooooooooooooooouuuuuuuuuuyyyyyAADDEOOUAAAAAAAAAAAAAAAEEEEEEEEEEIIIIIOOOOOOOOOOOOOOOUUUUUUUUUUYYYYY";
34
+ var returnValue = "";
35
+ for (let i = 0; i < str.length; i++) {
36
+ const index = signText.indexOf(str.charAt(i));
37
+ returnValue += index !== -1 ? unsignedText.charAt(index) : str.charAt(i);
38
+ }
39
+ return returnValue;
40
+ }
41
+
42
+ function toCSharpName(str) {
43
+ if (!str)
44
+ return "_";
45
+ const name = toVietnameseNonTongue(str).replace(/\W/g, "_");
46
+ const c = name.charAt(0);
47
+ return ('0' <= c && c <= '9' ? '_' : "") + c.toUpperCase() + name.substring(1);
48
+ }
49
+
50
+ function getCSharpTypeFromMushroomType(source, type, required) {
51
+ switch (type) {
52
+ case "string":
53
+ return "string";
54
+ case "object":
55
+ return "";
56
+ case "boolean":
57
+ return required ? "bool" : "bool?";
58
+ case "integer":
59
+ return required ? "int" : "int?";
60
+ case "long":
61
+ return required ? "long" : "long?";
62
+ case "double":
63
+ return required ? "double" : "double?";
64
+ case "array":
65
+ return "";
66
+ case "datetime":
67
+ return required ? "System.DateTime" : "System.DateTime?";
68
+ case "IdRef":
69
+ case "AutoId":
70
+ if (source.idType === "ObjectId" || source.idType === "GUID")
71
+ return "string";
72
+ if (source.idType === "AutoIncInt")
73
+ return "int";
74
+ if (source.idType === "AutoIncLong")
75
+ return "long";
76
+ }
77
+ return "UNKNOWN_TYPE";
78
+ }
79
+
80
+ function getCSharpInitValue(csType, value) {
81
+ switch(csType) {
82
+ case "string":
83
+ return JSON.stringify(value);
84
+ case "int":
85
+ return parseInt(Number(value));
86
+ case "long":
87
+ return parseInt(Number(value)) + "L";
88
+ case "double":
89
+ return Number(value);
90
+ case "bool":
91
+ if (value === "false")
92
+ return false;
93
+ if (value === "true")
94
+ return true;
95
+ return "NotABoolean"
96
+ case "datetime":
97
+ return `System.DateTime.Parse(${JSON.stringify(value)})`;
98
+ default:
99
+ return "UNSUPPORTED";
100
+ }
101
+ }
102
+
103
+ function generateEnumClass(source, out, field, defaultClassName) {
104
+ if (!out)
105
+ return "";
106
+
107
+ let strEnumClasses = "";
108
+ const validation = field.type === "array" ? field.items.validation : field.validation;
109
+ if (!validation)
110
+ return "";
111
+
112
+ if (!validation.validValues)
113
+ return "";
114
+
115
+ const mrType = field.type === "array" ? field.items.type : field.type;
116
+ if (mrType == "object" || mrType == "array") {
117
+ console.log("Unsuported enum type for type ", mrType, field);
118
+ return "";
119
+ }
120
+
121
+ var type = getCSharpTypeFromMushroomType(source, mrType, true);
122
+
123
+ validation.codeHint = validation.codeHint || {};
124
+ if (validation.validValues) {
125
+ validation.codeHint.validValues = validation.codeHint.validValues || {};
126
+
127
+ if (!validation.codeHint.validValues.disabled) {
128
+ const enumClassName = validation.codeHint.validValues.className || defaultClassName;
129
+
130
+ out.arrEnumClassNames = out.arrEnumClassNames || [];
131
+
132
+ if (out.arrEnumClassNames.indexOf(enumClassName) === -1) {
133
+ out.arrEnumClassNames.push(enumClassName);
134
+ strEnumClasses += ` /// <summary>
135
+ /// ${singleLine(validation.codeHint.validValues.description || field.description)}
136
+ /// </summary>
137
+ public partial class ${enumClassName}
138
+ {
139
+ private ${enumClassName}() { }
140
+
141
+ `;
142
+ const enumProperties = validation.codeHint.validValues.nameMap || validation.validValues;
143
+ for (let i = 0; i < enumProperties.length && i < validation.validValues.length; i++) {
144
+ strEnumClasses += ` public const ${type} ${toCSharpName(enumProperties[i])} = ${getCSharpInitValue(type, validation.validValues[i])};
145
+ `;
146
+ }
147
+ strEnumClasses += ` }
148
+
149
+ `;
150
+ }
151
+ }
152
+ }
153
+
154
+ return strEnumClasses;
155
+ }
156
+ //#endregion
157
+
158
+ //#region CSharp MongoDb Classes
159
+ function generateCSharpClassMongoDb(source, className, fields, isRoot, description, out) {
160
+ var strClasses = "";
161
+ let strEnumClasses = "";
162
+ var content = "";
163
+ if (description) {
164
+ content +=
165
+ ` /// <summary>
166
+ /// ${singleLine(description)}
167
+ /// </summary>
168
+ `;
169
+ }
170
+ var supperClass = "";
171
+ if (isRoot) {
172
+ // thêm cho trường hợp không khai báo id hoặc id.type
173
+ if (!fields.id) {
174
+ fields.id = {
175
+ type: "AutoId"
176
+ };
177
+ }
178
+ if (!fields.id.type) fields.id.type = "AutoId";
179
+
180
+ supperClass = " : Mushroom.Models.IResource<" + getCSharpTypeFromMushroomType(source, fields.id.type, true) + ">";
181
+ }
182
+ content += ` public partial class ${className}${supperClass}
183
+ {
184
+ `;
185
+ for (var fieldName in fields) {
186
+ if (!fields.hasOwnProperty(fieldName))
187
+ continue;
188
+
189
+ var field = fields[fieldName];
190
+ var type;
191
+ var propertyName = toCSharpName(fieldName);
192
+ if (field.codeHint && field.codeHint.type && field.codeHint.type.csharp) {
193
+ type = field.codeHint.type.csharp;
194
+ }
195
+ else if (field.type === "object") {
196
+ strClasses += generateCSharpClassMongoDb(source, className + "_" + propertyName, field.fields, false, null, out) + newLine;
197
+ type = className + "_" + propertyName;
198
+ }
199
+ else if (field.type === "array") {
200
+ if (field.items.type === "object") {
201
+ strClasses += generateCSharpClassMongoDb(source, className + "_" + propertyName, field.items.fields, false, null, out) + newLine;
202
+ type = `System.Collections.Generic.List<${className}_${propertyName}>`;
203
+ } else {
204
+ type = `System.Collections.Generic.List<${getCSharpTypeFromMushroomType(source, field.items.type, field.items.validation && field.items.validation.required)}>`;
205
+ }
206
+ } else
207
+ type = getCSharpTypeFromMushroomType(source, field.type, field.validation && field.validation.required);
208
+ content +=
209
+ ` /// <summary>
210
+ /// ${singleLine(field.description)}
211
+ /// </summary>
212
+ `;
213
+
214
+ if (isRoot && fieldName === "id") {
215
+ content += ` [MongoDB.Bson.Serialization.Attributes.BsonId${field.type === "AutoId" && source.idType === "GUID" ? "(IdGenerator = typeof(MongoDB.Bson.Serialization.IdGenerators.GuidGenerator))" : ""}]${newLine}`;
216
+ }
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" : ""})]
220
+ `;
221
+ if ((field.type === "AutoId" || field.type === "IdRef") && source.idType === "ObjectId") {
222
+ content += " [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)]" + newLine;
223
+ }
224
+ if (field.type === "AutoId" && source.idType === "GUID") {
225
+ content += " [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.String)]" + newLine;
226
+ }
227
+ if (field.type === "datetime") {
228
+ content += " [MongoDB.Bson.Serialization.Attributes.BsonDateTimeOptions(Kind = System.DateTimeKind.Local)]" + newLine;
229
+ }
230
+ if (field.type === "array") {
231
+ if ((field.items.type === "AutoId" || field.items.type === "IdRef") && source.idType === "ObjectId") {
232
+ content += " [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)]" + newLine;
233
+ }
234
+ if (field.items.type === "AutoId" && source.idType === "GUID") {
235
+ content += " [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.String)]" + newLine;
236
+ }
237
+ if (field.items.type === "datetime") {
238
+ content += " [MongoDB.Bson.Serialization.Attributes.BsonDateTimeOptions(Kind = System.DateTimeKind.Local)]" + newLine;
239
+ }
240
+ }
241
+
242
+ content += ` public ${type} ${propertyName} { get; set; }${newLine}${newLine}`;
243
+
244
+ strEnumClasses += generateEnumClass(source, out, field, `${className.toUpperCase()}_${propertyName.toUpperCase()}_ENUM`);
245
+ }
246
+ content += ` [MongoDB.Bson.Serialization.Attributes.BsonExtraElements]
247
+ public System.Collections.Generic.Dictionary<string, object> Mushroom_ExtraProperties { get; set; }
248
+
249
+ }
250
+ `;
251
+ if (strEnumClasses) {
252
+ out.strEnumClasses = out.strEnumClasses || "";
253
+
254
+ out.strEnumClasses += strEnumClasses;
255
+ //console.log("strEnumClasses("+typeof(strEnumClasses)+"):" + strEnumClasses);
256
+ }
257
+
258
+ return strClasses + newLine + content;
259
+ }
260
+
261
+ function getCSharpFunc(methodName, methodType) {
262
+ if (methodType === "static") return methodName;
263
+ const idx = methodName.lastIndexOf('.');
264
+ if (idx === -1) return methodName;
265
+ return `new ${methodName.substring(0, idx)}()${methodName.substring(idx)}`;
266
+ }
267
+
268
+ function genCSharpMongoDbClasses(args, projectName, project, alias, source) {
269
+ const aliasProject = ((project.csharpMongo || {}).alias || {})[alias];
270
+
271
+ if (!aliasProject) {
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;
278
+ }
279
+
280
+ const entities = common.getEntities(source, aliasProject.allowRoles, true);
281
+
282
+ const namespace = toCSharpName(source.name);
283
+
284
+ let strClasses = "";
285
+ let strEnumClasses = "";
286
+ let collectionNames = "";
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
+ });
299
+
300
+ const out = {};
301
+ for (let entityName in entities) {
302
+ if (!entities.hasOwnProperty(entityName))
303
+ continue;
304
+
305
+ const className = toCSharpName(entityName);
306
+ collectionNames += ` public static string ${className}CollectionName => "${entities[entityName].storageName}";
307
+ public static IMongoCollection<Resources.${className}> ${className}Collection => GetDatabase().GetCollection<Resources.${className}>(${className}CollectionName);
308
+ `;
309
+ resourceNames += ` public static string ${className} => "${entityName}";${newLine}`;
310
+ strClasses += generateCSharpClassMongoDb(source, className, entities[entityName].fields, true, entities[entityName].description, out);
311
+
312
+ const actions = entities[entityName].actions || {};
313
+ for (let actionName in actions) {
314
+ const action = actions[actionName];
315
+ if (!Array.isArray(action))
316
+ continue;
317
+
318
+ action.forEach(a => {
319
+ if (!a)
320
+ return;
321
+ if (typeof a.delegator === "string" && a.delegator.indexOf("lib:") === 0) {
322
+ out.delegators = out.delegators || [];
323
+ const method = a.delegator.substr(4, a.delegator.length - 4);
324
+ let type = a.codeHint && a.codeHint.delegator && a.codeHint.delegator.csharp
325
+ ? a.codeHint.delegator.csharp.methodType
326
+ : null;
327
+ if (type !== "non-static") type = "static";
328
+ out.delegators.push({
329
+ method: method,
330
+ source: `entity: ${entityName}, action: ${actionName}, grant: ${a.grant}`,
331
+ type: type
332
+ });
333
+ }
334
+
335
+ if (!a.events && !(typeof a.events === "object")) return;
336
+
337
+ for (let eventName in a.events) {
338
+ if (!Array.isArray(a.events[eventName])) return;
339
+
340
+ out.eventHandlers = out.eventHandlers || [];
341
+ a.events[eventName].forEach((ev, i) => {
342
+ if (typeof ev !== "string" || ev.indexOf("lib:") !== 0) return;
343
+ const method = ev.substr(4, ev.length - 4);
344
+ let type = a.codeHint && a.codeHint.events
345
+ && Array.isArray(a.codeHint.events[eventName])
346
+ && a.codeHint.events[eventName][i]
347
+ && a.codeHint.events[eventName][i].csharp
348
+ ? a.codeHint.events[eventName][i].csharp.methodType
349
+ : null;
350
+ if (type !== "non-static") type = "static";
351
+ out.eventHandlers.push({
352
+ method: method,
353
+ source: `entity: ${entityName}, action: ${actionName}, grant: ${a.grant}, event: ${eventName}`,
354
+ type: type
355
+ });
356
+ });
357
+ }
358
+ });
359
+ }
360
+
361
+ const views = entities[entityName].views || {};
362
+ for (let viewName in views) {
363
+ const view = views[viewName];
364
+ if (!Array.isArray(view))
365
+ continue;
366
+
367
+ view.forEach(v => {
368
+ if (!v) return;
369
+
370
+ if (typeof v.query === "string" && v.query.indexOf("lib:") === 0) {
371
+ out.viewHandlers = out.viewHandlers || [];
372
+ const method = v.query.substr(4, v.query.length - 4);
373
+ let type = v.codeHint && v.codeHint.query && v.codeHint.query.csharp
374
+ ? v.codeHint.query.csharp.methodType
375
+ : null;
376
+ if (type !== "non-static") type = "static";
377
+ out.viewHandlers.push({
378
+ method: method,
379
+ source: `entity: ${entityName}, view: ${viewName}, grant: ${v.grant}`,
380
+ type: type
381
+ });
382
+ }
383
+ });
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
+ }
404
+ }
405
+
406
+ if (out.strEnumClasses)
407
+ strEnumClasses += out.strEnumClasses;
408
+
409
+ const delegators = (out.delegators || []).reduce((prev, cur) => {
410
+ if (cur.method in prev) {
411
+ if (prev[cur.method].indexOf(cur.source) === -1) {
412
+ prev[cur.method].push(cur);
413
+ }
414
+ }
415
+ else {
416
+ prev[cur.method] = [cur];
417
+ }
418
+ return prev;
419
+ }, {});
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);
421
+
422
+ const viewHandlers = (out.viewHandlers || []).reduce((prev, cur) => {
423
+ if (cur.method in prev) {
424
+ if (prev[cur.method].indexOf(cur.source) === -1) {
425
+ prev[cur.method].push(cur);
426
+ }
427
+ }
428
+ else {
429
+ prev[cur.method] = [cur];
430
+ }
431
+ return prev;
432
+ }, {});
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);
447
+
448
+ const eventHandlers = (out.eventHandlers || []).reduce((prev, cur) => {
449
+ if (cur.method in prev) {
450
+ if (prev[cur.method].indexOf(cur.source) === -1) {
451
+ prev[cur.method].push(cur);
452
+ }
453
+ }
454
+ else {
455
+ prev[cur.method] = [cur];
456
+ }
457
+ return prev;
458
+ }, {});
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);
460
+
461
+ const strJobReferences = Array.isArray(source.jobs)
462
+ ? source.jobs
463
+ .filter(job => job !== null && typeof(job) === "object" && job.action && typeof (job.action) === "string" && job.action.indexOf("lib:") === 0)
464
+ .map(job => ` RegisterJob<${job.action.substring(4).split(',')[0]}>();`)
465
+ .join(newLine)
466
+ : "";
467
+
468
+ const code = `// This file was generated by Mushroom CLI ${package.version} (https://www.npmjs.com/package/mushroom-cli), please do not modify
469
+
470
+ // NOTE: Compatible with Mushroom Server version 0.2.18 or higher (https://www.nuget.org/packages/Mushroom/)
471
+
472
+ // ReSharper disable RedundantUsingDirective
473
+ // ReSharper disable InconsistentNaming
474
+ // ReSharper disable PartialTypeWithSinglePart
475
+ // ReSharper disable UnusedMember.Global
476
+ // ReSharper disable UnusedMember.Local
477
+ // ReSharper disable UnusedParameter.Local
478
+ // ReSharper disable IdentifierTypo
479
+ // ReSharper disable StringLiteralTypo
480
+ // ReSharper disable CommentTypo
481
+ // ReSharper disable EmptyNamespace
482
+
483
+ namespace ${namespace}
484
+ {
485
+ using MongoDB.Driver;
486
+
487
+ public static class DbConnector
488
+ {
489
+ ${collectionNames}
490
+ public static IMongoDatabase GetDatabase() => Mushroom.MushroomDaoFactory.GetDbAdapter() as IMongoDatabase;
491
+ }
492
+
493
+ public class ResourceNames
494
+ {
495
+ private ResourceNames() { }
496
+
497
+ ${resourceNames}
498
+ }
499
+
500
+ public class RoleNames {
501
+ private RoleNames() { }
502
+
503
+ ${roleNames}
504
+ }
505
+ }
506
+
507
+ namespace ${namespace}.Resources
508
+ {
509
+ ${strClasses}
510
+ }
511
+
512
+ namespace ${namespace}.Enums
513
+ {
514
+ ${strEnumClasses}
515
+ }
516
+
517
+ #if DEBUG
518
+ namespace ${namespace}.CodeHelper
519
+ {
520
+ class RefactorHelper
521
+ {
522
+ private RefactorHelper() { }
523
+ private void RegisterCustomMethod(System.Func<Mushroom.ActionArguments, System.Threading.Tasks.Task> fn) { }
524
+ private void RegisterCustomMethod(System.Action<Mushroom.ActionArguments> fn) { }
525
+ private void RegisterCustomViewMethod(System.Func<Mushroom.ViewArguments, System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<object>>> fn) { }
526
+ private void RegisterCustomViewMethod(System.Action<Mushroom.ViewArguments> fn) { }
527
+ private void RegisterCustomVnTextBuilderMethod(System.Func<System.Collections.Generic.IEnumerable<string>, System.Collections.Generic.IEnumerable<string>> fn) { }
528
+ private void RegisterEvent(System.Func<object, Mushroom.ActionArguments, System.Threading.Tasks.Task> fn) { }
529
+ private void RegisterEvent(System.Action<object, Mushroom.ActionArguments> fn) { }
530
+ private void RegisterJob<T>() where T : Mushroom.Job.JobBase { }
531
+ private void Help()
532
+ {
533
+ ${strDelegatorReferences}
534
+ ${strViewHandlerReferences}
535
+ ${strVnTextChannels}
536
+ ${strEventHandlerReferences}
537
+ ${strJobReferences}
538
+ }
539
+ }
540
+ }
541
+ #endif
542
+ `;
543
+
544
+ common.ensureFolder(aliasProject.output);
545
+
546
+ fs.writeFile(aliasProject.output, code, err => {
547
+ if (err)
548
+ throw err;
549
+ console.log(`Generated CSharp MongoDb Classes for ${projectName}@${alias} to ${aliasProject.output}`);
550
+ });
551
+ }
552
+
553
+ function generateCSharpClassMongoDbToFolder(source, className, fields, isRoot, description, out, aliasProject) {
554
+ var content = "";
555
+ const namespace = toCSharpName(source.name);
556
+ if (description) {
557
+ content +=
558
+ ` /// <summary>
559
+ /// ${singleLine(description)}
560
+ /// </summary>
561
+ `;
562
+ }
563
+ var supperClass = "";
564
+ if (isRoot) {
565
+ // thêm cho trường hợp không khai báo id hoặc id.type
566
+ if (!fields.id) {
567
+ fields.id = {
568
+ type: "AutoId"
569
+ };
570
+ }
571
+ if (!fields.id.type) fields.id.type = "AutoId";
572
+
573
+ supperClass = " : Mushroom.Models.IResource<" + getCSharpTypeFromMushroomType(source, fields.id.type, true) + ">";
574
+ }
575
+ content += ` public partial class ${className}${supperClass}
576
+ {
577
+ `;
578
+ for (var fieldName in fields) {
579
+ if (!fields.hasOwnProperty(fieldName))
580
+ continue;
581
+
582
+ var field = fields[fieldName];
583
+ var type;
584
+ var propertyName = toCSharpName(fieldName);
585
+ if (field.codeHint && field.codeHint.type && field.codeHint.type.csharp) {
586
+ type = field.codeHint.type.csharp;
587
+ }
588
+ else if (field.type === "object") {
589
+ generateCSharpClassMongoDbToFolder(source, className + "_" + propertyName, field.fields, false, null, out, aliasProject) + newLine;
590
+ type = className + "_" + propertyName;
591
+ }
592
+ else if (field.type === "array") {
593
+ if (field.items.type === "object") {
594
+ generateCSharpClassMongoDbToFolder(source, className + "_" + propertyName, field.items.fields, false, null, out, aliasProject) + newLine;
595
+ type = `System.Collections.Generic.List<${className}_${propertyName}>`;
596
+ } else {
597
+ type = `System.Collections.Generic.List<${getCSharpTypeFromMushroomType(source, field.items.type, field.items.validation && field.items.validation.required)}>`;
598
+ }
599
+ } else
600
+ type = getCSharpTypeFromMushroomType(source, field.type, field.validation && field.validation.required);
601
+ content +=
602
+ ` /// <summary>
603
+ /// ${singleLine(field.description)}
604
+ /// </summary>
605
+ `;
606
+
607
+ if (isRoot && fieldName === "id") {
608
+ content += ` [MongoDB.Bson.Serialization.Attributes.BsonId${field.type === "AutoId" && source.idType === "GUID" ? "(IdGenerator = typeof(MongoDB.Bson.Serialization.IdGenerators.GuidGenerator))" : ""}]${newLine}`;
609
+ }
610
+ content += ` [MongoDB.Bson.Serialization.Attributes.BsonElement("${isRoot && fieldName === "id" ? "_id" : fieldName}")]
611
+ [MongoDB.Bson.Serialization.Attributes.BsonIgnoreIfNull]
612
+ [Newtonsoft.Json.JsonProperty(PropertyName = "${fieldName}", NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore${type === "System.DateTime" ? ", DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore" : ""})]
613
+ `;
614
+ if ((field.type === "AutoId" || field.type === "IdRef") && source.idType === "ObjectId") {
615
+ content += " [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)]" + newLine;
616
+ }
617
+ if (field.type === "AutoId" && source.idType === "GUID") {
618
+ content += " [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.String)]" + newLine;
619
+ }
620
+ if (field.type === "datetime") {
621
+ content += " [MongoDB.Bson.Serialization.Attributes.BsonDateTimeOptions(Kind = System.DateTimeKind.Local)]" + newLine;
622
+ }
623
+ if (field.type === "array") {
624
+ if ((field.items.type === "AutoId" || field.items.type === "IdRef") && source.idType === "ObjectId") {
625
+ content += " [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)]" + newLine;
626
+ }
627
+ if (field.items.type === "AutoId" && source.idType === "GUID") {
628
+ content += " [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.String)]" + newLine;
629
+ }
630
+ if (field.items.type === "datetime") {
631
+ content += " [MongoDB.Bson.Serialization.Attributes.BsonDateTimeOptions(Kind = System.DateTimeKind.Local)]" + newLine;
632
+ }
633
+ }
634
+
635
+ content += ` public ${type} ${propertyName} { get; set; }
636
+
637
+ `;
638
+
639
+ let strEnumClasses = generateEnumClass(source, {}, field, `${className.toUpperCase()}_${propertyName.toUpperCase()}_ENUM`);
640
+
641
+ const match = strEnumClasses.match(/public partial class\s+(\w+)/);
642
+ if (!match) continue;
643
+ common.ensureFolder(aliasProject.output + "/Enums", true);
644
+ strEnumClasses = `${header}
645
+
646
+ namespace ${namespace}.Enums
647
+ {
648
+ ${strEnumClasses}
649
+ }
650
+ `;
651
+
652
+ fs.writeFileSync(aliasProject.output + "/Enums/" + match[1] + ".cs", strEnumClasses);
653
+ }
654
+
655
+ content += ` [MongoDB.Bson.Serialization.Attributes.BsonExtraElements]
656
+ [Newtonsoft.Json.JsonIgnore]
657
+ public System.Collections.Generic.Dictionary<string, object> Mushroom_ExtraProperties { get; set; }
658
+
659
+ }
660
+ `;
661
+
662
+ //return strClasses + newLine + content;
663
+ common.ensureFolder(aliasProject.output + "/Resources", true);
664
+
665
+ content = `${header}
666
+
667
+ namespace ${namespace}.Resources
668
+ {
669
+ ${content}
670
+ }
671
+ `;
672
+
673
+ out.allClasses = out.allClasses || [];
674
+
675
+ const normalizedName = className.toLowerCase();
676
+ const duplicate = out.allClasses.find(c => c.normalizedName == normalizedName);
677
+ if (duplicate) {
678
+ fs.appendFileSync(aliasProject.output + "/Resources/" + duplicate.className + ".cs", content);
679
+ }
680
+ else {
681
+ out.allClasses.push({
682
+ className,
683
+ normalizedName
684
+ });
685
+ fs.writeFileSync(aliasProject.output + "/Resources/" + className + ".cs", content);
686
+ }
687
+ }
688
+
689
+ function genCSharpMongoDbClassesToFolder(projectName, alias, source, aliasProject) {
690
+
691
+ if (fs.existsSync(aliasProject.output)) {
692
+ try {
693
+ fs.unlinkSync(aliasProject.output); // xóa file nếu có
694
+ } catch(e) {}
695
+ try {
696
+ // fs.rmdirSync(aliasProject.output, { recursive: true, force: true }); // xóa thư mục nếu có
697
+ fs.rmSync(aliasProject.output, { recursive: true, force: true }); // xóa thư mục nếu có
698
+ } catch(e) {}
699
+ }
700
+ fs.mkdirSync(aliasProject.output, { recursive: true, mode: 0755 });
701
+
702
+ const entities = common.getEntities(source, aliasProject.allowRoles, true);
703
+
704
+ const namespace = toCSharpName(source.name);
705
+
706
+ let collectionNames = "";
707
+ let resourceNames = "";
708
+ let roleNames = "";
709
+
710
+ source.roles?.forEach(role => {
711
+ if (!role.name) return;
712
+ roleNames += `
713
+ /// <summary>
714
+ /// ${role.description ?? ""}
715
+ /// </summary>
716
+ public static string ${toCSharpName(role.name)} => "${role.name}";
717
+ `;
718
+ });
719
+
720
+ const out = {};
721
+ for (let entityName in entities) {
722
+ if (!entities.hasOwnProperty(entityName))
723
+ continue;
724
+
725
+ const className = toCSharpName(entityName);
726
+ collectionNames += ` public static string ${className}CollectionName => "${entities[entityName].storageName}";
727
+ public static IMongoCollection<Resources.${className}> ${className}Collection => GetDatabase().GetCollection<Resources.${className}>(${className}CollectionName);
728
+ `;
729
+ resourceNames += ` public static string ${className} => "${entityName}";
730
+ `;
731
+ //strClasses += generateCSharpClassMongoDbToFolder(source, className, entities[entityName].fields, true, entities[entityName].description, out);
732
+
733
+ generateCSharpClassMongoDbToFolder(source, className, entities[entityName].fields, true, entities[entityName].description, out, aliasProject);
734
+
735
+ const actions = entities[entityName].actions || {};
736
+ for (let actionName in actions) {
737
+ const action = actions[actionName];
738
+ if (!Array.isArray(action))
739
+ continue;
740
+
741
+ action.forEach(a => {
742
+ if (!a)
743
+ return;
744
+ if (typeof a.delegator === "string" && a.delegator.indexOf("lib:") === 0) {
745
+ out.delegators = out.delegators || [];
746
+ const method = a.delegator.substr(4, a.delegator.length - 4);
747
+ let type = a.codeHint && a.codeHint.delegator && a.codeHint.delegator.csharp
748
+ ? a.codeHint.delegator.csharp.methodType
749
+ : null;
750
+ if (type !== "non-static") type = "static";
751
+ out.delegators.push({
752
+ method: method,
753
+ source: `entity: ${entityName}, action: ${actionName}, grant: ${a.grant}`,
754
+ type: type
755
+ });
756
+ }
757
+
758
+ if (!a.events && !(typeof a.events === "object")) return;
759
+
760
+ for (let eventName in a.events) {
761
+ if (!Array.isArray(a.events[eventName])) return;
762
+
763
+ out.eventHandlers = out.eventHandlers || [];
764
+ a.events[eventName].forEach((ev, i) => {
765
+ if (typeof ev !== "string" || ev.indexOf("lib:") !== 0) return;
766
+ const method = ev.substr(4, ev.length - 4);
767
+ let type = a.codeHint && a.codeHint.events
768
+ && Array.isArray(a.codeHint.events[eventName])
769
+ && a.codeHint.events[eventName][i]
770
+ && a.codeHint.events[eventName][i].csharp
771
+ ? a.codeHint.events[eventName][i].csharp.methodType
772
+ : null;
773
+ if (type !== "non-static") type = "static";
774
+ out.eventHandlers.push({
775
+ method: method,
776
+ source: `entity: ${entityName}, action: ${actionName}, grant: ${a.grant}, event: ${eventName}`,
777
+ type: type
778
+ });
779
+ });
780
+ }
781
+ });
782
+ }
783
+
784
+ const views = entities[entityName].views || {};
785
+ for (let viewName in views) {
786
+ const view = views[viewName];
787
+ if (!Array.isArray(view))
788
+ continue;
789
+
790
+ view.forEach(v => {
791
+ if (!v) return;
792
+
793
+ if (typeof v.query === "string" && v.query.indexOf("lib:") === 0) {
794
+ out.viewHandlers = out.viewHandlers || [];
795
+ const method = v.query.substr(4, v.query.length - 4);
796
+ let type = v.codeHint && v.codeHint.query && v.codeHint.query.csharp
797
+ ? v.codeHint.query.csharp.methodType
798
+ : null;
799
+ if (type !== "non-static") type = "static";
800
+ out.viewHandlers.push({
801
+ method: method,
802
+ source: `entity: ${entityName}, view: ${viewName}, grant: ${v.grant}`,
803
+ type: type
804
+ });
805
+ }
806
+ });
807
+ }
808
+
809
+ const channels = entities[entityName].features?.vn_text?.channels;
810
+ if (channels != null) {
811
+ channels.forEach(channel => {
812
+ if (!channel.nativeBuilder || typeof channel.nativeBuilder !== "string" || channel.nativeBuilder.indexOf("lib:") !== 0) return;
813
+
814
+ out.vnTextChannels = out.vnTextChannels || [];
815
+ const method = channel.nativeBuilder.substr(4, channel.nativeBuilder.length - 4);
816
+ let type = channel.codeHint && channel.codeHint.nativeBuilder && channel.codeHint.nativeBuilder.csharp
817
+ ? channel.codeHint.nativeBuilder.csharp.methodType
818
+ : null;
819
+ if (type !== "non-static") type = "static";
820
+ out.vnTextChannels.push({
821
+ method: method,
822
+ source: `entity: ${entityName}, feature: vn_text, channel: ${channel.name}`,
823
+ type: type
824
+ });
825
+ });
826
+ }
827
+ }
828
+
829
+
830
+ const delegators = (out.delegators || []).reduce((prev, cur) => {
831
+ if (cur.method in prev) {
832
+ if (prev[cur.method].indexOf(cur.source) === -1) {
833
+ prev[cur.method].push(cur);
834
+ }
835
+ }
836
+ else {
837
+ prev[cur.method] = [cur];
838
+ }
839
+ return prev;
840
+ }, {});
841
+ 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);
842
+
843
+ const viewHandlers = (out.viewHandlers || []).reduce((prev, cur) => {
844
+ if (cur.method in prev) {
845
+ if (prev[cur.method].indexOf(cur.source) === -1) {
846
+ prev[cur.method].push(cur);
847
+ }
848
+ }
849
+ else {
850
+ prev[cur.method] = [cur];
851
+ }
852
+ return prev;
853
+ }, {});
854
+ 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);
855
+
856
+ const vnTextChannels = (out.vnTextChannels || []).reduce((prev, cur) => {
857
+ if (cur.method in prev) {
858
+ if (prev[cur.method].indexOf(cur.source) === -1) {
859
+ prev[cur.method].push(cur);
860
+ }
861
+ }
862
+ else {
863
+ prev[cur.method] = [cur];
864
+ }
865
+ return prev;
866
+ }, {});
867
+ 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);
868
+
869
+ const eventHandlers = (out.eventHandlers || []).reduce((prev, cur) => {
870
+ if (cur.method in prev) {
871
+ if (prev[cur.method].indexOf(cur.source) === -1) {
872
+ prev[cur.method].push(cur);
873
+ }
874
+ }
875
+ else {
876
+ prev[cur.method] = [cur];
877
+ }
878
+ return prev;
879
+ }, {});
880
+ 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);
881
+
882
+ const strJobReferences = Array.isArray(source.jobs)
883
+ ? source.jobs
884
+ .filter(job => job !== null && typeof(job) === "object" && job.action && typeof (job.action) === "string" && job.action.indexOf("lib:") === 0)
885
+ .map(job => ` RegisterJob<${job.action.substring(4).split(',')[0]}>();`)
886
+ .join(newLine)
887
+ : "";
888
+
889
+ const dbConnectorFileContent = `${header}
890
+ using MongoDB.Driver;
891
+
892
+ namespace ${namespace}
893
+ {
894
+ public static class DbConnector
895
+ {
896
+ ${collectionNames}
897
+ public static IMongoDatabase GetDatabase() => Mushroom.MushroomDaoFactory.GetDbAdapter() as IMongoDatabase;
898
+ }
899
+ }
900
+ `;
901
+
902
+ const resourceNamesFileContent = `${header}
903
+
904
+ namespace ${namespace}
905
+ {
906
+ public class ResourceNames
907
+ {
908
+ private ResourceNames() { }
909
+
910
+ ${resourceNames}
911
+ }
912
+ }
913
+ `;
914
+
915
+ const roleNamesFileContent = `${header}
916
+
917
+ namespace ${namespace}
918
+ {
919
+ public class RoleNames
920
+ {
921
+ private RoleNames() { }
922
+
923
+ ${roleNames}
924
+ }
925
+ }
926
+ `;
927
+
928
+
929
+ const refactorHelperFileContent = `${header}
930
+
931
+ #if DEBUG
932
+ namespace ${namespace}
933
+ {
934
+ class RefactorHelper
935
+ {
936
+ private RefactorHelper() { }
937
+ private void RegisterCustomMethod(System.Func<Mushroom.ActionArguments, System.Threading.Tasks.Task> fn) { }
938
+ private void RegisterCustomMethod(System.Action<Mushroom.ActionArguments> fn) { }
939
+ private void RegisterCustomViewMethod(System.Func<Mushroom.ViewArguments, System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<object>>> fn) { }
940
+ private void RegisterCustomViewMethod(System.Action<Mushroom.ViewArguments> fn) { }
941
+ private void RegisterCustomVnTextBuilderMethod(System.Func<System.Collections.Generic.IEnumerable<string>, System.Collections.Generic.IEnumerable<string>> fn) { }
942
+ private void RegisterEvent(System.Func<object, Mushroom.ActionArguments, System.Threading.Tasks.Task> fn) { }
943
+ private void RegisterEvent(System.Action<object, Mushroom.ActionArguments> fn) { }
944
+ private void RegisterJob<T>() where T : Mushroom.Job.JobBase { }
945
+ private void Help()
946
+ {
947
+ ${strDelegatorReferences}
948
+ ${strViewHandlerReferences}
949
+ ${strVnTextChannels}
950
+ ${strEventHandlerReferences}
951
+ ${strJobReferences}
952
+ }
953
+ }
954
+ }
955
+ #endif
956
+ `;
957
+
958
+ 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/)
959
+ // For Mushroom Server 0.2.18 to 0.2.25.4: Please remove all FindById methods in DbConnector.cs`
960
+
961
+ fs.writeFileSync(aliasProject.output + "/DbConnector.cs", dbConnectorFileContent);
962
+ fs.writeFileSync(aliasProject.output + "/ResourceNames.cs", resourceNamesFileContent);
963
+ fs.writeFileSync(aliasProject.output + "/RoleNames.cs", roleNamesFileContent);
964
+ fs.writeFileSync(aliasProject.output + "/RefactorHelper.cs", refactorHelperFileContent);
965
+ fs.writeFileSync(aliasProject.output + "/Info.cs", infoFileContent);
966
+
967
+ console.log(`Generated CSharp MongoDb Classes for ${projectName}@${alias} to folder ${aliasProject.output}`);
968
+ }
969
+ //#endregion
970
+
971
+ //#region CSharp Driver
972
+ function generateCSharpClassDriver(source, className, fields, description, out) {
973
+ var strClasses = "";
974
+ var strEnumClasses = "";
975
+ var content = "";
976
+ if (description) {
977
+ content +=
978
+ ` /// <summary>
979
+ /// ${singleLine(description)}
980
+ /// </summary>
981
+ `;
982
+ }
983
+ content += ` public partial class ${className}
984
+ {
985
+ `;
986
+
987
+ for (let fieldName in fields) {
988
+ if (!fields.hasOwnProperty(fieldName))
989
+ continue;
990
+
991
+ const field = fields[fieldName];
992
+
993
+ const propertyName = toCSharpName(fieldName);
994
+ let type;
995
+ if (field.type === "object") {
996
+ strClasses += generateCSharpClassDriver(source, className + "_" + propertyName, field.fields, null, out) + newLine;
997
+ type = className + "_" + propertyName;
998
+ }
999
+ else if (field.type === "array") {
1000
+ if (field.items.type === "object") {
1001
+ strClasses += generateCSharpClassDriver(source, className + "_" + propertyName, field.items.fields, null, out) + newLine;
1002
+ type = `System.Collections.Generic.List<${className}_${propertyName}>`;
1003
+ } else {
1004
+ type = `System.Collections.Generic.List<${getCSharpTypeFromMushroomType(source, field.items.type, field.items.validation && field.items.validation.required)}>`;
1005
+ }
1006
+ } else
1007
+ type = getCSharpTypeFromMushroomType(source, field.type, field.validation && field.validation.required);
1008
+ content +=
1009
+ ` /// <summary>
1010
+ /// ${singleLine(field.description)}
1011
+ /// </summary>
1012
+ [Newtonsoft.Json.JsonProperty(PropertyName ="${fieldName}", NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore${type === "System.Datetime" ? ", DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore" : ""})]
1013
+ public ${type} ${propertyName} { get; set; }
1014
+
1015
+ `;
1016
+ strEnumClasses += generateEnumClass(source, out, field, `${className.toUpperCase()}_${propertyName.toUpperCase()}_ENUM`);
1017
+ }
1018
+
1019
+ if (strEnumClasses) {
1020
+ out.strEnumClasses = out.strEnumClasses || "";
1021
+
1022
+ out.strEnumClasses += strEnumClasses;
1023
+ }
1024
+
1025
+
1026
+ content += " }" + newLine;
1027
+ return strClasses + newLine + content;
1028
+ }
1029
+
1030
+ function genCSharpDriver(args, projectName, project, alias, source) {
1031
+ const aliasProject = ((project.csharpDriver || {}).alias || {})[alias];
1032
+
1033
+ if (!aliasProject) {
1034
+ 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`);
1035
+ }
1036
+
1037
+ const entities = common.getEntities(source, aliasProject.allowRoles);
1038
+
1039
+ var namespace = toCSharpName(source.name);
1040
+
1041
+ var strClasses = "";
1042
+ var strEnumClasses = "";
1043
+ var codeStaticCtor = "";
1044
+ var codeStaticProperties = "";
1045
+ var codeConnectors = "";
1046
+ var codeExtraClasses = "";
1047
+
1048
+ var out = {};
1049
+
1050
+ let accessModifier = aliasProject.accessModifier || "internal";
1051
+
1052
+ for (var entityName in entities) {
1053
+ if (!entities.hasOwnProperty(entityName))
1054
+ continue;
1055
+
1056
+ var className = toCSharpName(entityName);
1057
+
1058
+ strClasses += generateCSharpClassDriver(source, className, entities[entityName].fields, entities[entityName].description, out);
1059
+ codeStaticCtor += ` ${className} = new ${className}Connector(client);${newLine}`;
1060
+ codeStaticProperties += ` public static ${className}Connector ${className} { get; }${newLine}${newLine}`;
1061
+
1062
+ var entity = entities[entityName];
1063
+
1064
+ codeConnectors += ` ${accessModifier} partial class ${className}Connector : MushroomDriver.MushroomResourceConnector<${className}>
1065
+ {
1066
+ protected override string Resource { get; } = ${JSON.stringify(entityName)};
1067
+
1068
+ `;
1069
+
1070
+ if (Object.keys(entity.views).length) {
1071
+ codeConnectors += ` public ${className}Connector(MushroomDriver.MushroomClient client) : base(client)
1072
+ {
1073
+ Views = new ${className}Views(Client, () => Resource);
1074
+ }
1075
+
1076
+ `;
1077
+ } else {
1078
+ codeConnectors += ` public ${className}Connector(MushroomDriver.MushroomClient client) : base(client) { }
1079
+
1080
+ `;
1081
+ }
1082
+
1083
+ for (var actionName in entity.actions) {
1084
+ if (!entity.actions.hasOwnProperty(actionName))
1085
+ continue;
1086
+
1087
+ switch (actionName) {
1088
+ case "findMany":
1089
+ codeConnectors += ` public System.Threading.Tasks.Task<System.Collections.Generic.List<${className}>> List(MushroomDriver.ListArg arg = null)
1090
+ {
1091
+ return InternalList(arg);
1092
+ }
1093
+
1094
+ `;
1095
+ break;
1096
+ case "findById":
1097
+ codeConnectors += ` public System.Threading.Tasks.Task<${className}> FindById(MushroomDriver.FindByIdArg arg)
1098
+ {
1099
+ return InternalFindById(arg);
1100
+ }
1101
+
1102
+ `;
1103
+ break;
1104
+ case "createOne":
1105
+ codeConnectors += ` public System.Threading.Tasks.Task<string> Create(MushroomDriver.CreateArg<${className}> arg)
1106
+ {
1107
+ return InternalCreate(arg);
1108
+ }
1109
+
1110
+ `;
1111
+ break;
1112
+ case "createMany":
1113
+ codeConnectors += ` public System.Threading.Tasks.Task<System.Collections.Generic.List<string>> Create(MushroomDriver.BatchCreateArg<${className}> arg)
1114
+ {
1115
+ return InternalCreate(arg);
1116
+ }
1117
+
1118
+ `;
1119
+ break;
1120
+ case "updateOne":
1121
+ codeConnectors += ` public System.Threading.Tasks.Task<string> Update(MushroomDriver.UpdateArg<${className}> arg)
1122
+ {
1123
+ return InternalUpdate(arg);
1124
+ }
1125
+
1126
+ `;
1127
+ break;
1128
+ case "updateMany":
1129
+ codeConnectors += ` public System.Threading.Tasks.Task<System.Collections.Generic.List<string>> Update(MushroomDriver.BatchUpdateArg<${className}> arg)
1130
+ {
1131
+ return InternalUpdate(arg);
1132
+ }
1133
+
1134
+ `;
1135
+ break;
1136
+ case "updatePartially":
1137
+ codeConnectors += ` public System.Threading.Tasks.Task<string> Update(MushroomDriver.PartialUpdateArg<${className}> arg)
1138
+ {
1139
+ return InternalUpdate(arg);
1140
+ }
1141
+
1142
+ public System.Threading.Tasks.Task<string> Update(MushroomDriver.PartialUpdateArg<System.Collections.Generic.Dictionary<string, object>> arg)
1143
+ {
1144
+ return InternalUpdate(arg);
1145
+ }
1146
+
1147
+ `;
1148
+ break;
1149
+ case "deleteOne":
1150
+ codeConnectors += ` public System.Threading.Tasks.Task<long> Delete(MushroomDriver.DeleteArg arg)
1151
+ {
1152
+ return InternalDelete(arg);
1153
+ }
1154
+
1155
+ `;
1156
+ break;
1157
+ case "deleteMany":
1158
+ codeConnectors += ` public System.Threading.Tasks.Task<long> Delete(MushroomDriver.BatchDeleteArg arg)
1159
+ {
1160
+ return InternalDelete(arg);
1161
+ }
1162
+
1163
+ `;
1164
+ break;
1165
+ default:
1166
+ // if not start with _raw_http_method_ --> break;
1167
+ if (actionName.indexOf("_raw_http_method_"))
1168
+ break;
1169
+
1170
+ var customMethod = toCSharpName(actionName.substring("_raw_http_method_".length));
1171
+
1172
+ codeConnectors += ` public async System.Threading.Tasks.Task<${className}${customMethod}Result> ${customMethod}(${className}${customMethod}Arg arg)
1173
+ {
1174
+ if (arg == null)
1175
+ throw new System.ArgumentNullException(nameof(arg));
1176
+
1177
+ var request = new MushroomDriver.MushroomRequest
1178
+ {
1179
+ RootApiUrl = Client.RootApiUrl,
1180
+ Url = Client.RootApiUrl + arg.BuildUrl(),
1181
+ Method = arg.Method
1182
+ };
1183
+ var headers = new System.Collections.Generic.Dictionary<string, string>
1184
+ {
1185
+ {"X-Requested-With", "Mushroom Driver " + MushroomDriver.MushroomConnector.Version}
1186
+ };
1187
+ if (arg.UseXHttpMethodOverride)
1188
+ {
1189
+ headers["X-Http-Method-Override"] = request.Method;
1190
+ request.Method = "POST";
1191
+ }
1192
+ request.Headers = headers;
1193
+ request.Data = arg.CustomData ?? arg.Data;
1194
+ var response = await MushroomDriver.MushroomConnector.Execute(request);
1195
+ var result = response.GetResult<${className}${customMethod}Result>();
1196
+ result.MushroomResponseMetadata = response.Metadata;
1197
+ return result;
1198
+ }
1199
+
1200
+ `;
1201
+
1202
+ codeExtraClasses += ` ${accessModifier} partial class ${className}${customMethod}Result
1203
+ {
1204
+ public System.Collections.Generic.Dictionary<string, object> MushroomResponseMetadata { get; set; }
1205
+ }
1206
+
1207
+ ${accessModifier} partial class ${className}${customMethod}Body { }
1208
+
1209
+ ${accessModifier} partial class ${className}${customMethod}Arg : MushroomDriver.MushroomRequestArg
1210
+ {
1211
+ public override string BuildUrl()
1212
+ {
1213
+ BuildCustomUrl();
1214
+ return CustomUrl;
1215
+ }
1216
+
1217
+ partial void BuildCustomUrl();
1218
+
1219
+ private string OriginUrl => "${entityName}s/${actionName.substring("_raw_http_method_".length)}";
1220
+
1221
+ private string CustomUrl { get; set; } = "${entityName}s/${actionName.substring("_raw_http_method_".length)}";
1222
+
1223
+ public override string Method { get; } = "${actionName.substring("_raw_http_method_".length)}";
1224
+
1225
+ public ${className}${customMethod}Body Data { get; set; }
1226
+
1227
+ public object CustomData { get; set; }
1228
+ }
1229
+
1230
+ `;
1231
+ break;
1232
+ }
1233
+ }
1234
+
1235
+ if (Object.keys(entity.views).length) {
1236
+ codeConnectors += ` public ${className}Views Views { get; }
1237
+
1238
+ `;
1239
+ codeExtraClasses += ` ${accessModifier} partial class ${className}Views : MushroomDriver.MushroomViewConnector
1240
+ {
1241
+ protected System.Func<string> FnResource;
1242
+
1243
+ public ${className}Views(MushroomDriver.MushroomClient client, System.Func<string> fnResource) : base(client)
1244
+ {
1245
+ FnResource = fnResource;
1246
+ }
1247
+
1248
+ `;
1249
+ let viewExtraClass = "";
1250
+ for (let viewName in entity.views) {
1251
+ if (!entity.views.hasOwnProperty(viewName))
1252
+ continue;
1253
+
1254
+ let viewMethodName = toCSharpName(viewName);
1255
+
1256
+ let hasNoParamView = false;
1257
+ entity.views[viewName].forEach(view => {
1258
+ let role = view.grant === "*" ? "" : `_${toCSharpName(view.grant)}`;
1259
+ let hasParameter = view.parameters && view.parameters.length;
1260
+ if (hasParameter) {
1261
+ codeExtraClasses += ` public System.Threading.Tasks.Task<System.Collections.Generic.List<${className}View_${viewMethodName}Result>> ${viewMethodName}(${className}View${role}_${viewMethodName}Arg arg)
1262
+ {
1263
+ return InternalExecuteView<${className}View_${viewMethodName}Result>(new MushroomDriver.ViewArg<${className}View${role}_${viewMethodName}Arg> {
1264
+ Parameters = arg,
1265
+ Resource = FnResource?.Invoke(),
1266
+ ViewName = "${viewName}"
1267
+ });
1268
+ }
1269
+
1270
+ `;
1271
+ viewExtraClass += ` ${accessModifier} partial class ${className}View${role}_${viewMethodName}Arg
1272
+ {
1273
+ `;
1274
+ view.parameters.forEach(p => {
1275
+ var type = getCSharpTypeFromMushroomType(source, p.type, p.validation && p.validation.required);
1276
+ if (p.isArray)
1277
+ type = `System.Collections.Generic.List<${type}>`;
1278
+ viewExtraClass += ` [Newtonsoft.Json.JsonProperty(PropertyName = "${p.field}")]
1279
+ public ${type} ${toCSharpName(p.field)} { get; set; }
1280
+
1281
+ `;
1282
+ });
1283
+ viewExtraClass += ` }
1284
+
1285
+ `;
1286
+ }
1287
+ else if (!hasNoParamView) {
1288
+ hasNoParamView = true;
1289
+ codeExtraClasses += ` public System.Threading.Tasks.Task<System.Collections.Generic.List<${className}View_${viewMethodName}Result>> ${viewMethodName}()
1290
+ {
1291
+ return InternalExecuteView<${className}View_${viewMethodName}Result>(new MushroomDriver.ViewArg {
1292
+ Resource = FnResource?.Invoke(),
1293
+ ViewName = "${viewName}"
1294
+ });
1295
+ }
1296
+
1297
+ `;
1298
+ }
1299
+ });
1300
+
1301
+
1302
+ viewExtraClass += ` ${accessModifier} partial class ${className}View_${viewMethodName}Result
1303
+ {
1304
+
1305
+ }
1306
+
1307
+ `;
1308
+ }
1309
+ codeExtraClasses += ` }
1310
+
1311
+ ${viewExtraClass}`;
1312
+ }
1313
+
1314
+ codeConnectors += " }" + newLine + newLine;
1315
+ }
1316
+
1317
+ if (out.strEnumClasses)
1318
+ strEnumClasses += out.strEnumClasses;
1319
+
1320
+ const code = `// This file was generated by Mushroom CLI ${package.version} (https://www.npmjs.com/package/mushroom-cli), please do not modify
1321
+
1322
+ // Require package: Mushroom.Driver version 1.4.0 or later (https://www.nuget.org/packages/Mushroom.Driver/)
1323
+
1324
+ // ReSharper disable InconsistentNaming
1325
+ // ReSharper disable PartialTypeWithSinglePart
1326
+ // ReSharper disable PartialMethodWithSinglePart
1327
+ // ReSharper disable UnusedMember.Global
1328
+ // ReSharper disable UnusedMember.Local
1329
+ // ReSharper disable IdentifierTypo
1330
+ // ReSharper disable StringLiteralTypo
1331
+ // ReSharper disable CommentTypo
1332
+ // ReSharper disable AutoPropertyCanBeMadeGetOnly.Local
1333
+
1334
+
1335
+ using JsonPropertyAttribute = Newtonsoft.Json.JsonPropertyAttribute;
1336
+ using NullValueHandling = Newtonsoft.Json.NullValueHandling;
1337
+ using ${namespace}.Resources;
1338
+
1339
+ namespace ${namespace}
1340
+ {
1341
+ ${accessModifier} partial class API
1342
+ {
1343
+ static API()
1344
+ {
1345
+ CustomizeRootApiUrl();
1346
+ var client = new MushroomDriver.MushroomClient(_rootApiUrl);
1347
+ MushroomClient = client;
1348
+
1349
+ ${Array.isArray(aliasProject.features) && aliasProject.features.indexOf("auth") !== -1 ? "Authentication = new MushroomDriver.Auth.Authentication(_rootApiUrl);" : ""}
1350
+ ${Array.isArray(aliasProject.features) && aliasProject.features.indexOf("file") !== -1 ? "FileExtension = new MushroomDriver.File.FileExtension(_rootApiUrl);" : ""}
1351
+
1352
+ ${codeStaticCtor}
1353
+ }
1354
+
1355
+ static partial void CustomizeRootApiUrl();
1356
+
1357
+ private static string _rootApiUrl = ${JSON.stringify(common.getRootUrl(source))};
1358
+
1359
+ public static MushroomDriver.MushroomClient MushroomClient { get; }
1360
+
1361
+ ${Array.isArray(aliasProject.features) && aliasProject.features.indexOf("auth") !== -1 ? "public static MushroomDriver.Auth.Authentication Authentication { get; }" : ""}
1362
+
1363
+ ${Array.isArray(aliasProject.features) && aliasProject.features.indexOf("file") !== -1 ? "public static MushroomDriver.File.FileExtension FileExtension { get; }" : ""}
1364
+
1365
+ ${codeStaticProperties}
1366
+ }
1367
+
1368
+ /*${accessModifier} partial class API
1369
+ {
1370
+ static partial void CustomizeRootApiUrl()
1371
+ {
1372
+ _rootApiUrl = "your customized root api url";
1373
+ }
1374
+ }*/
1375
+
1376
+ ${codeConnectors}${codeExtraClasses}
1377
+ }
1378
+
1379
+ namespace ${namespace}.Resources
1380
+ {
1381
+ ${strClasses}
1382
+ }
1383
+
1384
+ namespace ${namespace}.Enums
1385
+ {
1386
+ ${strEnumClasses}
1387
+ }`;
1388
+
1389
+ common.ensureFolder(aliasProject.output);
1390
+
1391
+ fs.writeFileSync(aliasProject.output, code);
1392
+ console.log(`Generated CSharp Driver for ${projectName}@${alias} to ${aliasProject.output}`);
1393
+ }
1394
+ //#endregion
1395
+
1396
+ module.exports = {
1397
+ genCSharpMongoDbClasses: genCSharpMongoDbClasses,
1398
+ genCSharpDriver: genCSharpDriver
1399
+ };