mushroom-cli 1.2.0-alpha.8 → 1.2.0

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.
Files changed (51) hide show
  1. package/README.md +199 -154
  2. package/dist/check-update.js +6 -0
  3. package/dist/common.js +280 -0
  4. package/dist/config.js +394 -0
  5. package/dist/docs/bootstrap-theme.min.css +6 -0
  6. package/dist/docs/bootstrap.min.css +6 -0
  7. package/dist/docs/bootstrap.min.js +7 -0
  8. package/dist/docs/doc-mt.js +633 -0
  9. package/dist/docs/docs.html +5380 -0
  10. package/{docs → dist/docs}/docs.v2.html +5205 -6615
  11. package/dist/docs/docs.v2.js +2036 -0
  12. package/dist/docs/jquery.min.js +4 -0
  13. package/dist/docs/mt-dom-1.0.js +1398 -0
  14. package/dist/docs/mt.extension.js +199 -0
  15. package/dist/gen/gen-api-docs-v1.js +110 -0
  16. package/dist/gen/gen-api-docs.js +327 -0
  17. package/{gen → dist/gen}/gen-csharp.js +1256 -1399
  18. package/{gen → dist/gen}/gen-db-docs.js +204 -222
  19. package/{gen → dist/gen}/gen-js-driver-tarball.js +81 -101
  20. package/{gen → dist/gen}/gen-js-driver.js +116 -133
  21. package/dist/gen/gen-ts-driver.js +600 -0
  22. package/{gen.js → dist/gen.js} +109 -124
  23. package/{help.js → dist/help.js} +53 -55
  24. package/dist/init/init-json.js +92 -0
  25. package/dist/init/init-netcore.js +30 -0
  26. package/dist/init.js +23 -0
  27. package/dist/master-file/master-file.js +185 -0
  28. package/dist/merge.js +70 -0
  29. package/dist/mr.js +77 -0
  30. package/dist/types.js +1 -0
  31. package/dist/update/tsCode.js +82 -0
  32. package/dist/update.js +20 -0
  33. package/package.json +64 -28
  34. package/check-update.js +0 -9
  35. package/common.js +0 -273
  36. package/config.js +0 -445
  37. package/docs/doc-mt.js +0 -523
  38. package/docs/docs.html +0 -5190
  39. package/docs/mt-dom-1.0.js +0 -1268
  40. package/docs/mt.extension.js +0 -174
  41. package/gen/gen-api-docs-v1.js +0 -125
  42. package/gen/gen-api-docs.js +0 -259
  43. package/gen/gen-ts-driver.js +0 -471
  44. package/init/init-json.js +0 -106
  45. package/init/init-netcore.js +0 -32
  46. package/init.js +0 -28
  47. package/master-file/master-file.js +0 -234
  48. package/merge.js +0 -84
  49. package/mr.js +0 -86
  50. package/update/tsCode.js +0 -20
  51. package/update.js +0 -24
@@ -1,1399 +1,1256 @@
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
- };
1
+ import fs from 'fs';
2
+ import * as common from '../common.js';
3
+ const packageVersion = common.getPackageVersion();
4
+ const newLine = '\n';
5
+ const header = `// NOTE: Please do not modify this file
6
+ // NOTE: Version and compatibility information: please see in Info.cs file
7
+
8
+ // ReSharper disable CheckNamespace
9
+ // ReSharper disable CommentTypo
10
+ // ReSharper disable EmptyNamespace
11
+ // ReSharper disable IdentifierTypo
12
+ // ReSharper disable InconsistentNaming
13
+ // ReSharper disable PartialTypeWithSinglePart
14
+ // ReSharper disable RedundantUsingDirective
15
+ // ReSharper disable StringLiteralTypo
16
+ // ReSharper disable UnusedMember.Global
17
+ // ReSharper disable UnusedMember.Local
18
+ // ReSharper disable UnusedParameter.Local
19
+ // ReSharper disable UnusedTypeParameter
20
+ `;
21
+ function singleLine(str) {
22
+ if (!str)
23
+ return '';
24
+ return str.replace(/\r/g, '').replace(/\n/g, '<br/>');
25
+ }
26
+ function toVietnameseNonTongue(str) {
27
+ const signText = 'ăâđêôơưàảãạáằẳẵặắầẩẫậấèẻẽẹéềểễệếìỉĩịíòỏõọóồổỗộốờởỡợớùủũụúừửữựứỳỷỹỵýĂÂĐÐÊÔƠƯÀẢÃẠÁẰẲẴẶẮẦẨẪẬẤÈẺẼẸÉỀỂỄỆẾÌỈĨỊÍÒỎÕỌÓỒỔỖỘỐỜỞỠỢỚÙỦŨỤÚỪỬỮỰỨỲỶỸỴÝ';
28
+ const unsignedText = 'aadeoouaaaaaaaaaaaaaaaeeeeeeeeeeiiiiiooooooooooooooouuuuuuuuuuyyyyyAADDEOOUAAAAAAAAAAAAAAAEEEEEEEEEEIIIIIOOOOOOOOOOOOOOOUUUUUUUUUUYYYYY';
29
+ let returnValue = '';
30
+ for (let i = 0; i < str.length; i++) {
31
+ const index = signText.indexOf(str.charAt(i));
32
+ returnValue += index !== -1 ? unsignedText.charAt(index) : str.charAt(i);
33
+ }
34
+ return returnValue;
35
+ }
36
+ function toCSharpName(str) {
37
+ if (!str)
38
+ return '_';
39
+ const name = toVietnameseNonTongue(str).replace(/\W/g, '_');
40
+ const c = name.charAt(0);
41
+ return ('0' <= c && c <= '9' ? '_' : '') + c.toUpperCase() + name.substring(1);
42
+ }
43
+ function getCSharpTypeFromMushroomType(source, type, required) {
44
+ switch (type) {
45
+ case 'string':
46
+ return 'string';
47
+ case 'object':
48
+ return '';
49
+ case 'boolean':
50
+ return required ? 'bool' : 'bool?';
51
+ case 'integer':
52
+ return required ? 'int' : 'int?';
53
+ case 'long':
54
+ return required ? 'long' : 'long?';
55
+ case 'double':
56
+ return required ? 'double' : 'double?';
57
+ case 'array':
58
+ return '';
59
+ case 'datetime':
60
+ return required ? 'System.DateTime' : 'System.DateTime?';
61
+ case 'IdRef':
62
+ case 'AutoId':
63
+ if (source.idType === 'ObjectId' || source.idType === 'GUID')
64
+ return 'string';
65
+ if (source.idType === 'AutoIncInt')
66
+ return 'int';
67
+ if (source.idType === 'AutoIncLong')
68
+ return 'long';
69
+ }
70
+ return 'UNKNOWN_TYPE';
71
+ }
72
+ function getCSharpInitValue(csType, value) {
73
+ switch (csType) {
74
+ case 'string':
75
+ return JSON.stringify(value);
76
+ case 'int':
77
+ return parseInt(value);
78
+ case 'long':
79
+ return parseInt(value) + 'L';
80
+ case 'double':
81
+ return Number(value);
82
+ case 'bool':
83
+ if (value === 'false')
84
+ return false;
85
+ if (value === 'true')
86
+ return true;
87
+ return 'NotABoolean';
88
+ case 'datetime':
89
+ return `System.DateTime.Parse(${JSON.stringify(value)})`;
90
+ default:
91
+ return 'UNSUPPORTED';
92
+ }
93
+ }
94
+ function generateEnumClass(source, out, field, defaultClassName) {
95
+ if (!out)
96
+ return '';
97
+ let strEnumClasses = '';
98
+ const validation = field.type === 'array' ? field.items?.validation : field.validation;
99
+ if (!validation)
100
+ return '';
101
+ if (!validation.validValues)
102
+ return '';
103
+ const mrType = field.type === 'array' ? field.items?.type : field.type;
104
+ if (!mrType) {
105
+ common.logWarning('Missing type', mrType, field);
106
+ return '';
107
+ }
108
+ if (mrType == 'object' || mrType == 'array') {
109
+ common.logWarning('Unsuported enum type for type', mrType, field);
110
+ return '';
111
+ }
112
+ const type = getCSharpTypeFromMushroomType(source, mrType, true);
113
+ validation.codeHint = validation.codeHint || {};
114
+ if (validation.validValues) {
115
+ validation.codeHint.validValues = validation.codeHint.validValues || {};
116
+ if (!validation.codeHint.validValues.disabled) {
117
+ const enumClassName = validation.codeHint.validValues.className || defaultClassName;
118
+ out.arrEnumClassNames ?? (out.arrEnumClassNames = []);
119
+ if (!out.arrEnumClassNames.includes(enumClassName)) {
120
+ out.arrEnumClassNames.push(enumClassName);
121
+ strEnumClasses += ` /// <summary>
122
+ /// ${singleLine(validation.codeHint.validValues.description || field.description)}
123
+ /// </summary>
124
+ public partial class ${enumClassName}
125
+ {
126
+ private ${enumClassName}() { }
127
+
128
+ `;
129
+ const enumProperties = validation.codeHint.validValues.nameMap || validation.validValues;
130
+ for (let i = 0; i < enumProperties.length && i < validation.validValues.length; i++) {
131
+ strEnumClasses += ` public const ${type} ${toCSharpName(enumProperties[i])} = ${getCSharpInitValue(type, validation.validValues[i])};
132
+ `;
133
+ }
134
+ strEnumClasses += ` }
135
+
136
+ `;
137
+ }
138
+ }
139
+ }
140
+ return strEnumClasses;
141
+ }
142
+ function groupCSharpMethodHandlerByMethod(handlers) {
143
+ if (!handlers)
144
+ return {};
145
+ return handlers.reduce((prev, cur) => {
146
+ if (cur.method in prev) {
147
+ if (prev[cur.method].every((handler) => handler.source !== cur.source)) {
148
+ prev[cur.method].push(cur);
149
+ }
150
+ }
151
+ else {
152
+ prev[cur.method] = [cur];
153
+ }
154
+ return prev;
155
+ }, {});
156
+ }
157
+ function generateCSharpClassMongoDb(source, className, fields, isRoot, description, out) {
158
+ let strClasses = '';
159
+ let strEnumClasses = '';
160
+ let content = '';
161
+ if (description) {
162
+ content += ` /// <summary>
163
+ /// ${singleLine(description)}
164
+ /// </summary>
165
+ `;
166
+ }
167
+ let supperClass = '';
168
+ if (isRoot) {
169
+ if (!fields.id) {
170
+ fields.id = {
171
+ type: 'AutoId',
172
+ };
173
+ }
174
+ if (!fields.id.type)
175
+ fields.id.type = 'AutoId';
176
+ supperClass = ' : Mushroom.Models.IResource<' + getCSharpTypeFromMushroomType(source, fields.id.type, true) + '>';
177
+ }
178
+ content += ` public partial class ${className}${supperClass}
179
+ {
180
+ `;
181
+ for (const fieldName in fields) {
182
+ const field = fields[fieldName];
183
+ let type;
184
+ const propertyName = toCSharpName(fieldName);
185
+ if (field.codeHint && field.codeHint.type && field.codeHint.type.csharp) {
186
+ type = field.codeHint.type.csharp;
187
+ }
188
+ else if (field.type === 'object') {
189
+ strClasses +=
190
+ generateCSharpClassMongoDb(source, className + '_' + propertyName, field.fields ?? {}, false, null, out) +
191
+ newLine;
192
+ type = className + '_' + propertyName;
193
+ }
194
+ else if (field.type === 'array') {
195
+ if (field.items?.type === 'object') {
196
+ strClasses +=
197
+ generateCSharpClassMongoDb(source, className + '_' + propertyName, field.items.fields ?? {}, false, null, out) + newLine;
198
+ type = `System.Collections.Generic.List<${className}_${propertyName}>`;
199
+ }
200
+ else if (field.items) {
201
+ type = `System.Collections.Generic.List<${getCSharpTypeFromMushroomType(source, field.items.type, field.items.validation && field.items.validation.required)}>`;
202
+ }
203
+ }
204
+ else
205
+ type = getCSharpTypeFromMushroomType(source, field.type, field.validation && field.validation.required);
206
+ content += ` /// <summary>
207
+ /// ${singleLine(field.description)}
208
+ /// </summary>
209
+ `;
210
+ if (isRoot && fieldName === 'id') {
211
+ content += ` [MongoDB.Bson.Serialization.Attributes.BsonId${field.type === 'AutoId' && source.idType === 'GUID' ? '(IdGenerator = typeof(MongoDB.Bson.Serialization.IdGenerators.GuidGenerator))' : ''}]\n`;
212
+ }
213
+ content += ` [MongoDB.Bson.Serialization.Attributes.BsonElement("${isRoot && fieldName === 'id' ? '_id' : fieldName}")]
214
+ [MongoDB.Bson.Serialization.Attributes.BsonIgnoreIfNull]
215
+ [Newtonsoft.Json.JsonProperty(PropertyName = "${fieldName}", NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore${type === 'System.DateTime' ? ', DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore' : ''})]
216
+ [System.Text.Json.Serialization.JsonPropertyName("${fieldName}")]
217
+ [System.Text.Json.Serialization.JsonIgnore(Condition = ${type === 'System.DateTime' ? 'System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingDefault' : 'System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull'})]
218
+ `;
219
+ if ((field.type === 'AutoId' || field.type === 'IdRef') && source.idType === 'ObjectId') {
220
+ content += ' [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)]\n';
221
+ }
222
+ if (field.type === 'AutoId' && source.idType === 'GUID') {
223
+ content += ' [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.String)]\n';
224
+ }
225
+ if (field.type === 'datetime') {
226
+ content +=
227
+ ' [MongoDB.Bson.Serialization.Attributes.BsonDateTimeOptions(Kind = System.DateTimeKind.Local)]\n';
228
+ }
229
+ if (field.type === 'array' && field.items) {
230
+ if ((field.items.type === 'AutoId' || field.items.type === 'IdRef') && source.idType === 'ObjectId') {
231
+ content +=
232
+ ' [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)]\n';
233
+ }
234
+ if (field.items.type === 'AutoId' && source.idType === 'GUID') {
235
+ content += ' [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.String)]\n';
236
+ }
237
+ if (field.items.type === 'datetime') {
238
+ content +=
239
+ ' [MongoDB.Bson.Serialization.Attributes.BsonDateTimeOptions(Kind = System.DateTimeKind.Local)]\n';
240
+ }
241
+ }
242
+ content += ` public ${type} ${propertyName} { get; set; }\n\n`;
243
+ strEnumClasses += generateEnumClass(source, out, field, `${className.toUpperCase()}_${propertyName.toUpperCase()}_ENUM`);
244
+ }
245
+ content += ` [MongoDB.Bson.Serialization.Attributes.BsonExtraElements]
246
+ public System.Collections.Generic.Dictionary<string, object> Mushroom_ExtraProperties { get; set; }
247
+
248
+ }
249
+ `;
250
+ if (strEnumClasses) {
251
+ out.strEnumClasses ?? (out.strEnumClasses = '');
252
+ out.strEnumClasses += strEnumClasses;
253
+ }
254
+ return strClasses + newLine + content;
255
+ }
256
+ function getCSharpFunc(methodName, methodType) {
257
+ if (methodType === 'static')
258
+ return methodName;
259
+ const idx = methodName.lastIndexOf('.');
260
+ if (idx === -1)
261
+ return methodName;
262
+ return `new ${methodName.substring(0, idx)}()${methodName.substring(idx)}`;
263
+ }
264
+ export function genCSharpMongoDbClasses(args, projectName, project, alias, source) {
265
+ const aliasProject = ((project.csharpMongo || {}).alias || {})[alias];
266
+ if (!aliasProject) {
267
+ 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`);
268
+ }
269
+ if (aliasProject.outputToFolder) {
270
+ genCSharpMongoDbClassesToFolder(projectName, alias, source, aliasProject);
271
+ return;
272
+ }
273
+ const entities = common.getEntities(source, aliasProject.allowRoles, true);
274
+ const namespace = toCSharpName(source.name);
275
+ let strClasses = '';
276
+ let strEnumClasses = '';
277
+ let collectionNames = '';
278
+ let resourceNames = '';
279
+ let roleNames = '';
280
+ source.roles?.forEach((role) => {
281
+ if (!role.name)
282
+ return;
283
+ roleNames += `
284
+ /// <summary>
285
+ /// ${role.description ?? ''}
286
+ /// </summary>
287
+ public static string ${toCSharpName(role.name)} => "${role.name}";
288
+ `;
289
+ });
290
+ const out = {
291
+ strEnumClasses: '',
292
+ };
293
+ for (const entityName in entities) {
294
+ const className = toCSharpName(entityName);
295
+ collectionNames += ` public static string ${className}CollectionName => "${entities[entityName].storageName}";
296
+ public static IMongoCollection<Resources.${className}> ${className}Collection => GetDatabase().GetCollection<Resources.${className}>(${className}CollectionName);
297
+ `;
298
+ resourceNames += ` public static string ${className} => "${entityName}";\n`;
299
+ strClasses += generateCSharpClassMongoDb(source, className, entities[entityName].fields, true, entities[entityName].description, out);
300
+ const actions = entities[entityName].actions || {};
301
+ for (const actionName in actions) {
302
+ const action = actions[actionName];
303
+ if (!Array.isArray(action))
304
+ continue;
305
+ action.forEach((a) => {
306
+ if (!a)
307
+ return;
308
+ if (typeof a.delegator === 'string' && a.delegator.indexOf('lib:') === 0) {
309
+ const method = a.delegator.substring(4);
310
+ let type = a.codeHint && a.codeHint.delegator && a.codeHint.delegator.csharp
311
+ ? a.codeHint.delegator.csharp.methodType
312
+ : null;
313
+ if (type !== 'non-static')
314
+ type = 'static';
315
+ out.delegators ?? (out.delegators = []);
316
+ out.delegators.push({
317
+ method: method,
318
+ source: `entity: ${entityName}, action: ${actionName}, grant: ${a.grant}`,
319
+ type: type,
320
+ });
321
+ }
322
+ if (!a.events && !(typeof a.events === 'object'))
323
+ return;
324
+ for (const eventName in a.events) {
325
+ if (!Array.isArray(a.events[eventName]))
326
+ return;
327
+ a.events[eventName].forEach((ev, i) => {
328
+ if (typeof ev !== 'string' || ev.indexOf('lib:') !== 0)
329
+ return;
330
+ const method = ev.substring(4);
331
+ let type = a.codeHint &&
332
+ a.codeHint.events &&
333
+ Array.isArray(a.codeHint.events[eventName]) &&
334
+ a.codeHint.events[eventName][i] &&
335
+ a.codeHint.events[eventName][i].csharp
336
+ ? a.codeHint.events[eventName][i].csharp.methodType
337
+ : null;
338
+ if (type !== 'non-static')
339
+ type = 'static';
340
+ out.eventHandlers ?? (out.eventHandlers = []);
341
+ out.eventHandlers.push({
342
+ method: method,
343
+ source: `entity: ${entityName}, action: ${actionName}, grant: ${a.grant}, event: ${eventName}`,
344
+ type: type,
345
+ });
346
+ });
347
+ }
348
+ });
349
+ }
350
+ const views = entities[entityName].views || {};
351
+ for (const viewName in views) {
352
+ const view = views[viewName];
353
+ if (!Array.isArray(view))
354
+ continue;
355
+ view.forEach((v) => {
356
+ if (!v)
357
+ return;
358
+ if (typeof v.query === 'string' && v.query.indexOf('lib:') === 0) {
359
+ const method = v.query.substring(4);
360
+ let type = v.codeHint && v.codeHint.query && v.codeHint.query.csharp ? v.codeHint.query.csharp.methodType : null;
361
+ if (type !== 'non-static')
362
+ type = 'static';
363
+ out.viewHandlers ?? (out.viewHandlers = []);
364
+ out.viewHandlers.push({
365
+ method: method,
366
+ source: `entity: ${entityName}, view: ${viewName}, grant: ${v.grant}`,
367
+ type: type,
368
+ });
369
+ }
370
+ });
371
+ }
372
+ const channels = entities[entityName].features?.vn_text?.channels;
373
+ if (channels != null) {
374
+ channels.forEach((channel) => {
375
+ if (!channel.nativeBuilder ||
376
+ typeof channel.nativeBuilder !== 'string' ||
377
+ channel.nativeBuilder.indexOf('lib:') !== 0)
378
+ return;
379
+ const method = channel.nativeBuilder.substring(4);
380
+ let type = channel.codeHint && channel.codeHint.nativeBuilder && channel.codeHint.nativeBuilder.csharp
381
+ ? channel.codeHint.nativeBuilder.csharp.methodType
382
+ : null;
383
+ if (type !== 'non-static')
384
+ type = 'static';
385
+ out.vnTextChannels ?? (out.vnTextChannels = []);
386
+ out.vnTextChannels.push({
387
+ method: method,
388
+ source: `entity: ${entityName}, feature: vn_text, channel: ${channel.name}`,
389
+ type: type,
390
+ });
391
+ });
392
+ }
393
+ }
394
+ if (out.strEnumClasses)
395
+ strEnumClasses += out.strEnumClasses;
396
+ const delegators = groupCSharpMethodHandlerByMethod(out.delegators);
397
+ const strDelegatorReferences = Object.keys(delegators)
398
+ .map((method) => delegators[method].map((ev) => ` // ${ev.source}`).join(newLine) +
399
+ `\n RegisterCustomMethod(${getCSharpFunc(method, delegators[method][0].type)});`)
400
+ .join(newLine);
401
+ const viewHandlers = groupCSharpMethodHandlerByMethod(out.viewHandlers);
402
+ const strViewHandlerReferences = Object.keys(viewHandlers)
403
+ .map((method) => viewHandlers[method].map((ev) => ` // ${ev.source}`).join(newLine) +
404
+ `\n RegisterCustomViewMethod(${getCSharpFunc(method, viewHandlers[method][0].type)});`)
405
+ .join(newLine);
406
+ const vnTextChannels = groupCSharpMethodHandlerByMethod(out.vnTextChannels);
407
+ const strVnTextChannels = Object.keys(vnTextChannels)
408
+ .map((method) => vnTextChannels[method].map((channel) => ` // ${channel.source}`).join(newLine) +
409
+ `\n RegisterCustomVnTextBuilderMethod(${getCSharpFunc(method, vnTextChannels[method][0].type)});`)
410
+ .join(newLine);
411
+ const eventHandlers = groupCSharpMethodHandlerByMethod(out.eventHandlers);
412
+ const strEventHandlerReferences = Object.keys(eventHandlers)
413
+ .map((method) => eventHandlers[method].map((ev) => ` // ${ev.source}`).join(newLine) +
414
+ `\n RegisterEvent(${getCSharpFunc(method, eventHandlers[method][0].type)});`)
415
+ .join(newLine);
416
+ const strJobReferences = Array.isArray(source.jobs)
417
+ ? source.jobs
418
+ .filter((job) => job !== null &&
419
+ typeof job === 'object' &&
420
+ job.action &&
421
+ typeof job.action === 'string' &&
422
+ job.action.indexOf('lib:') === 0)
423
+ .map((job) => ` RegisterJob<${job.action.substring(4).split(',')[0]}>();`)
424
+ .join(newLine)
425
+ : '';
426
+ const code = `// This file was generated by Mushroom CLI ${packageVersion} (https://www.npmjs.com/package/mushroom-cli), please do not modify
427
+
428
+ // NOTE: Compatible with Mushroom Server version 0.2.18 or higher (https://www.nuget.org/packages/Mushroom/)
429
+
430
+ // ReSharper disable RedundantUsingDirective
431
+ // ReSharper disable InconsistentNaming
432
+ // ReSharper disable PartialTypeWithSinglePart
433
+ // ReSharper disable UnusedMember.Global
434
+ // ReSharper disable UnusedMember.Local
435
+ // ReSharper disable UnusedParameter.Local
436
+ // ReSharper disable IdentifierTypo
437
+ // ReSharper disable StringLiteralTypo
438
+ // ReSharper disable CommentTypo
439
+ // ReSharper disable EmptyNamespace
440
+
441
+ namespace ${namespace}
442
+ {
443
+ using MongoDB.Driver;
444
+
445
+ public static class DbConnector
446
+ {
447
+ ${collectionNames}
448
+ public static IMongoDatabase GetDatabase() => Mushroom.MushroomDaoFactory.GetDbAdapter() as IMongoDatabase;
449
+ }
450
+
451
+ public class ResourceNames
452
+ {
453
+ private ResourceNames() { }
454
+
455
+ ${resourceNames}
456
+ }
457
+
458
+ public class RoleNames {
459
+ private RoleNames() { }
460
+
461
+ ${roleNames}
462
+ }
463
+ }
464
+
465
+ namespace ${namespace}.Resources
466
+ {
467
+ ${strClasses}
468
+ }
469
+
470
+ namespace ${namespace}.Enums
471
+ {
472
+ ${strEnumClasses}
473
+ }
474
+
475
+ #if DEBUG
476
+ namespace ${namespace}.CodeHelper
477
+ {
478
+ class RefactorHelper
479
+ {
480
+ private RefactorHelper() { }
481
+ private void RegisterCustomMethod(System.Func<Mushroom.ActionArguments, System.Threading.Tasks.Task> fn) { }
482
+ private void RegisterCustomMethod(System.Action<Mushroom.ActionArguments> fn) { }
483
+ private void RegisterCustomViewMethod(System.Func<Mushroom.ViewArguments, System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<object>>> fn) { }
484
+ private void RegisterCustomViewMethod(System.Action<Mushroom.ViewArguments> fn) { }
485
+ private void RegisterCustomVnTextBuilderMethod(System.Func<System.Collections.Generic.IEnumerable<string>, System.Collections.Generic.IEnumerable<string>> fn) { }
486
+ private void RegisterEvent(System.Func<object, Mushroom.ActionArguments, System.Threading.Tasks.Task> fn) { }
487
+ private void RegisterEvent(System.Action<object, Mushroom.ActionArguments> fn) { }
488
+ private void RegisterJob<T>() where T : Mushroom.Job.JobBase { }
489
+ private void Help()
490
+ {
491
+ ${strDelegatorReferences}
492
+ ${strViewHandlerReferences}
493
+ ${strVnTextChannels}
494
+ ${strEventHandlerReferences}
495
+ ${strJobReferences}
496
+ }
497
+ }
498
+ }
499
+ #endif
500
+ `;
501
+ common.ensureFolder(aliasProject.output);
502
+ fs.writeFile(aliasProject.output, code, (err) => {
503
+ if (err)
504
+ throw err;
505
+ common.logInfo(`Generated CSharp MongoDb Classes for ${projectName}@${alias} to ${aliasProject.output}`);
506
+ });
507
+ }
508
+ function generateCSharpClassMongoDbToFolder(source, className, fields, isRoot, description, out, aliasProject) {
509
+ let content = '';
510
+ const namespace = toCSharpName(source.name);
511
+ if (description) {
512
+ content += ` /// <summary>
513
+ /// ${singleLine(description)}
514
+ /// </summary>
515
+ `;
516
+ }
517
+ let supperClass = '';
518
+ if (isRoot) {
519
+ if (!fields.id) {
520
+ fields.id = {
521
+ type: 'AutoId',
522
+ };
523
+ }
524
+ if (!fields.id.type)
525
+ fields.id.type = 'AutoId';
526
+ supperClass = ' : Mushroom.Models.IResource<' + getCSharpTypeFromMushroomType(source, fields.id.type, true) + '>';
527
+ }
528
+ content += ` public partial class ${className}${supperClass}
529
+ {
530
+ `;
531
+ for (const fieldName in fields) {
532
+ const field = fields[fieldName];
533
+ let type;
534
+ const propertyName = toCSharpName(fieldName);
535
+ if (field.codeHint && field.codeHint.type && field.codeHint.type.csharp) {
536
+ type = field.codeHint.type.csharp;
537
+ }
538
+ else if (field.type === 'object') {
539
+ generateCSharpClassMongoDbToFolder(source, className + '_' + propertyName, field.fields ?? {}, false, null, out, aliasProject);
540
+ type = className + '_' + propertyName;
541
+ }
542
+ else if (field.type === 'array') {
543
+ if (field.items?.type === 'object') {
544
+ generateCSharpClassMongoDbToFolder(source, className + '_' + propertyName, field.items.fields ?? {}, false, null, out, aliasProject);
545
+ type = `System.Collections.Generic.List<${className}_${propertyName}>`;
546
+ }
547
+ else if (field.items) {
548
+ type = `System.Collections.Generic.List<${getCSharpTypeFromMushroomType(source, field.items.type, field.items.validation && field.items.validation.required)}>`;
549
+ }
550
+ }
551
+ else
552
+ type = getCSharpTypeFromMushroomType(source, field.type, field.validation && field.validation.required);
553
+ content += ` /// <summary>
554
+ /// ${singleLine(field.description)}
555
+ /// </summary>
556
+ `;
557
+ if (isRoot && fieldName === 'id') {
558
+ content += ` [MongoDB.Bson.Serialization.Attributes.BsonId${field.type === 'AutoId' && source.idType === 'GUID' ? '(IdGenerator = typeof(MongoDB.Bson.Serialization.IdGenerators.GuidGenerator))' : ''}]\n`;
559
+ }
560
+ content += ` [MongoDB.Bson.Serialization.Attributes.BsonElement("${isRoot && fieldName === 'id' ? '_id' : fieldName}")]
561
+ [MongoDB.Bson.Serialization.Attributes.BsonIgnoreIfNull]
562
+ [Newtonsoft.Json.JsonProperty(PropertyName = "${fieldName}", NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore${type === 'System.DateTime' ? ', DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore' : ''})]
563
+ [System.Text.Json.Serialization.JsonPropertyName("${fieldName}")]
564
+ [System.Text.Json.Serialization.JsonIgnore(Condition = ${type === 'System.DateTime' ? 'System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingDefault' : 'System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull'})]
565
+ `;
566
+ if ((field.type === 'AutoId' || field.type === 'IdRef') && source.idType === 'ObjectId') {
567
+ content += ' [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)]\n';
568
+ }
569
+ if (field.type === 'AutoId' && source.idType === 'GUID') {
570
+ content += ' [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.String)]\n';
571
+ }
572
+ if (field.type === 'datetime') {
573
+ content +=
574
+ ' [MongoDB.Bson.Serialization.Attributes.BsonDateTimeOptions(Kind = System.DateTimeKind.Local)]\n';
575
+ }
576
+ if (field.type === 'array') {
577
+ if ((field.items?.type === 'AutoId' || field.items?.type === 'IdRef') && source.idType === 'ObjectId') {
578
+ content +=
579
+ ' [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)]\n';
580
+ }
581
+ if (field.items?.type === 'AutoId' && source.idType === 'GUID') {
582
+ content += ' [MongoDB.Bson.Serialization.Attributes.BsonRepresentation(MongoDB.Bson.BsonType.String)]\n';
583
+ }
584
+ if (field.items?.type === 'datetime') {
585
+ content +=
586
+ ' [MongoDB.Bson.Serialization.Attributes.BsonDateTimeOptions(Kind = System.DateTimeKind.Local)]\n';
587
+ }
588
+ }
589
+ content += ` public ${type} ${propertyName} { get; set; }
590
+
591
+ `;
592
+ let strEnumClasses = generateEnumClass(source, {}, field, `${className.toUpperCase()}_${propertyName.toUpperCase()}_ENUM`);
593
+ const match = strEnumClasses.match(/public partial class\s+(\w+)/);
594
+ if (!match)
595
+ continue;
596
+ common.ensureFolder(aliasProject.output + '/Enums', true);
597
+ strEnumClasses = `${header}
598
+
599
+ namespace ${namespace}.Enums
600
+ {
601
+ ${strEnumClasses}
602
+ }
603
+ `;
604
+ fs.writeFileSync(aliasProject.output + '/Enums/' + match[1] + '.cs', strEnumClasses);
605
+ }
606
+ content += ` [MongoDB.Bson.Serialization.Attributes.BsonExtraElements]
607
+ [Newtonsoft.Json.JsonIgnore]
608
+ public System.Collections.Generic.Dictionary<string, object> Mushroom_ExtraProperties { get; set; }
609
+
610
+ }
611
+ `;
612
+ common.ensureFolder(aliasProject.output + '/Resources', true);
613
+ content = `${header}
614
+
615
+ namespace ${namespace}.Resources
616
+ {
617
+ ${content}
618
+ }
619
+ `;
620
+ const normalizedName = className.toLowerCase();
621
+ out.allClasses ?? (out.allClasses = []);
622
+ const duplicate = out.allClasses.find((c) => c.normalizedName == normalizedName);
623
+ if (duplicate) {
624
+ fs.appendFileSync(aliasProject.output + '/Resources/' + duplicate.className + '.cs', content);
625
+ }
626
+ else {
627
+ out.allClasses.push({
628
+ className,
629
+ normalizedName,
630
+ });
631
+ fs.writeFileSync(aliasProject.output + '/Resources/' + className + '.cs', content);
632
+ }
633
+ }
634
+ function genCSharpMongoDbClassesToFolder(projectName, alias, source, aliasProject) {
635
+ if (fs.existsSync(aliasProject.output)) {
636
+ try {
637
+ fs.unlinkSync(aliasProject.output);
638
+ }
639
+ catch { }
640
+ try {
641
+ fs.rmSync(aliasProject.output, { recursive: true, force: true });
642
+ }
643
+ catch { }
644
+ }
645
+ fs.mkdirSync(aliasProject.output, { recursive: true, mode: 0o755 });
646
+ const entities = common.getEntities(source, aliasProject.allowRoles, true);
647
+ const namespace = toCSharpName(source.name);
648
+ let collectionNames = '';
649
+ let resourceNames = '';
650
+ let roleNames = '';
651
+ source.roles?.forEach((role) => {
652
+ if (!role.name)
653
+ return;
654
+ roleNames += `
655
+ /// <summary>
656
+ /// ${role.description ?? ''}
657
+ /// </summary>
658
+ public static string ${toCSharpName(role.name)} => "${role.name}";
659
+ `;
660
+ });
661
+ const out = {};
662
+ for (const entityName in entities) {
663
+ const className = toCSharpName(entityName);
664
+ collectionNames += ` public static string ${className}CollectionName => "${entities[entityName].storageName}";
665
+ public static IMongoCollection<Resources.${className}> ${className}Collection => GetDatabase().GetCollection<Resources.${className}>(${className}CollectionName);
666
+ `;
667
+ resourceNames += ` public static string ${className} => "${entityName}";
668
+ `;
669
+ generateCSharpClassMongoDbToFolder(source, className, entities[entityName].fields, true, entities[entityName].description, out, aliasProject);
670
+ const actions = entities[entityName].actions || {};
671
+ for (const actionName in actions) {
672
+ const action = actions[actionName];
673
+ if (!Array.isArray(action))
674
+ continue;
675
+ action.forEach((a) => {
676
+ if (!a)
677
+ return;
678
+ if (typeof a.delegator === 'string' && a.delegator.indexOf('lib:') === 0) {
679
+ const method = a.delegator.substring(4);
680
+ let type = a.codeHint && a.codeHint.delegator && a.codeHint.delegator.csharp
681
+ ? a.codeHint.delegator.csharp.methodType
682
+ : null;
683
+ if (type !== 'non-static')
684
+ type = 'static';
685
+ out.delegators ?? (out.delegators = []);
686
+ out.delegators.push({
687
+ method: method,
688
+ source: `entity: ${entityName}, action: ${actionName}, grant: ${a.grant}`,
689
+ type: type,
690
+ });
691
+ }
692
+ if (!a.events && !(typeof a.events === 'object'))
693
+ return;
694
+ for (const eventName in a.events) {
695
+ if (!Array.isArray(a.events[eventName]))
696
+ return;
697
+ a.events[eventName].forEach((ev, i) => {
698
+ if (typeof ev !== 'string' || ev.indexOf('lib:') !== 0)
699
+ return;
700
+ const method = ev.substring(4);
701
+ let type = a.codeHint &&
702
+ a.codeHint.events &&
703
+ Array.isArray(a.codeHint.events[eventName]) &&
704
+ a.codeHint.events[eventName][i] &&
705
+ a.codeHint.events[eventName][i].csharp
706
+ ? a.codeHint.events[eventName][i].csharp.methodType
707
+ : null;
708
+ if (type !== 'non-static')
709
+ type = 'static';
710
+ out.eventHandlers ?? (out.eventHandlers = []);
711
+ out.eventHandlers.push({
712
+ method: method,
713
+ source: `entity: ${entityName}, action: ${actionName}, grant: ${a.grant}, event: ${eventName}`,
714
+ type: type,
715
+ });
716
+ });
717
+ }
718
+ });
719
+ }
720
+ const views = entities[entityName].views || {};
721
+ for (const viewName in views) {
722
+ const view = views[viewName];
723
+ if (!Array.isArray(view))
724
+ continue;
725
+ view.forEach((v) => {
726
+ if (!v)
727
+ return;
728
+ if (typeof v.query === 'string' && v.query.indexOf('lib:') === 0) {
729
+ const method = v.query.substring(4);
730
+ let type = v.codeHint && v.codeHint.query && v.codeHint.query.csharp ? v.codeHint.query.csharp.methodType : null;
731
+ if (type !== 'non-static')
732
+ type = 'static';
733
+ out.viewHandlers ?? (out.viewHandlers = []);
734
+ out.viewHandlers.push({
735
+ method: method,
736
+ source: `entity: ${entityName}, view: ${viewName}, grant: ${v.grant}`,
737
+ type: type,
738
+ });
739
+ }
740
+ });
741
+ }
742
+ const channels = entities[entityName].features?.vn_text?.channels;
743
+ if (channels != null) {
744
+ channels.forEach((channel) => {
745
+ if (!channel.nativeBuilder ||
746
+ typeof channel.nativeBuilder !== 'string' ||
747
+ channel.nativeBuilder.indexOf('lib:') !== 0)
748
+ return;
749
+ const method = channel.nativeBuilder.substring(4);
750
+ let type = channel.codeHint && channel.codeHint.nativeBuilder && channel.codeHint.nativeBuilder.csharp
751
+ ? channel.codeHint.nativeBuilder.csharp.methodType
752
+ : null;
753
+ if (type !== 'non-static')
754
+ type = 'static';
755
+ out.vnTextChannels ?? (out.vnTextChannels = []);
756
+ out.vnTextChannels.push({
757
+ method: method,
758
+ source: `entity: ${entityName}, feature: vn_text, channel: ${channel.name}`,
759
+ type: type,
760
+ });
761
+ });
762
+ }
763
+ }
764
+ const delegators = groupCSharpMethodHandlerByMethod(out.delegators);
765
+ const strDelegatorReferences = Object.keys(delegators)
766
+ .map((method) => delegators[method].map((ev) => ` // ${ev.source}`).join(newLine) +
767
+ `\n RegisterCustomMethod(${getCSharpFunc(method, delegators[method][0].type)});`)
768
+ .join(newLine);
769
+ const viewHandlers = groupCSharpMethodHandlerByMethod(out.viewHandlers);
770
+ const strViewHandlerReferences = Object.keys(viewHandlers)
771
+ .map((method) => viewHandlers[method].map((ev) => ` // ${ev.source}`).join(newLine) +
772
+ `\n RegisterCustomViewMethod(${getCSharpFunc(method, viewHandlers[method][0].type)});`)
773
+ .join(newLine);
774
+ const vnTextChannels = groupCSharpMethodHandlerByMethod(out.vnTextChannels);
775
+ const strVnTextChannels = Object.keys(vnTextChannels)
776
+ .map((method) => vnTextChannels[method].map((channel) => ` // ${channel.source}`).join(newLine) +
777
+ `\n RegisterCustomVnTextBuilderMethod(${getCSharpFunc(method, vnTextChannels[method][0].type)});`)
778
+ .join(newLine);
779
+ const eventHandlers = groupCSharpMethodHandlerByMethod(out.eventHandlers);
780
+ const strEventHandlerReferences = Object.keys(eventHandlers)
781
+ .map((method) => eventHandlers[method].map((ev) => ` // ${ev.source}`).join(newLine) +
782
+ `\n RegisterEvent(${getCSharpFunc(method, eventHandlers[method][0].type)});`)
783
+ .join(newLine);
784
+ const strJobReferences = Array.isArray(source.jobs)
785
+ ? source.jobs
786
+ .filter((job) => job !== null &&
787
+ typeof job === 'object' &&
788
+ job.action &&
789
+ typeof job.action === 'string' &&
790
+ job.action.indexOf('lib:') === 0)
791
+ .map((job) => ` RegisterJob<${job.action.substring(4).split(',')[0]}>();`)
792
+ .join(newLine)
793
+ : '';
794
+ const dbConnectorFileContent = `${header}
795
+ using MongoDB.Driver;
796
+
797
+ namespace ${namespace}
798
+ {
799
+ public static class DbConnector
800
+ {
801
+ ${collectionNames}
802
+ public static IMongoDatabase GetDatabase() => Mushroom.MushroomDaoFactory.GetDbAdapter() as IMongoDatabase;
803
+ }
804
+ }
805
+ `;
806
+ const resourceNamesFileContent = `${header}
807
+
808
+ namespace ${namespace}
809
+ {
810
+ public class ResourceNames
811
+ {
812
+ private ResourceNames() { }
813
+
814
+ ${resourceNames}
815
+ }
816
+ }
817
+ `;
818
+ const roleNamesFileContent = `${header}
819
+
820
+ namespace ${namespace}
821
+ {
822
+ public class RoleNames
823
+ {
824
+ private RoleNames() { }
825
+
826
+ ${roleNames}
827
+ }
828
+ }
829
+ `;
830
+ const refactorHelperFileContent = `${header}
831
+
832
+ #if DEBUG
833
+ namespace ${namespace}
834
+ {
835
+ class RefactorHelper
836
+ {
837
+ private RefactorHelper() { }
838
+ private void RegisterCustomMethod(System.Func<Mushroom.ActionArguments, System.Threading.Tasks.Task> fn) { }
839
+ private void RegisterCustomMethod(System.Action<Mushroom.ActionArguments> fn) { }
840
+ private void RegisterCustomViewMethod(System.Func<Mushroom.ViewArguments, System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<object>>> fn) { }
841
+ private void RegisterCustomViewMethod(System.Action<Mushroom.ViewArguments> fn) { }
842
+ private void RegisterCustomVnTextBuilderMethod(System.Func<System.Collections.Generic.IEnumerable<string>, System.Collections.Generic.IEnumerable<string>> fn) { }
843
+ private void RegisterEvent(System.Func<object, Mushroom.ActionArguments, System.Threading.Tasks.Task> fn) { }
844
+ private void RegisterEvent(System.Action<object, Mushroom.ActionArguments> fn) { }
845
+ private void RegisterRespondingEvent(System.Func<object, Mushroom.ActionArguments, Mushroom.ActionResult, System.Threading.Tasks.Task> fn) { }
846
+ private void RegisterRespondingEvent(System.Action<object, Mushroom.ActionArguments, Mushroom.ActionResult> fn) { }
847
+ private void RegisterJob<T>() where T : Mushroom.Job.JobBase { }
848
+ private void Help()
849
+ {
850
+ ${strDelegatorReferences}
851
+ ${strViewHandlerReferences}
852
+ ${strVnTextChannels}
853
+ ${strEventHandlerReferences}
854
+ ${strJobReferences}
855
+ }
856
+ }
857
+ }
858
+ #endif
859
+ `;
860
+ const infoFileContent = `// Mushroom CLI version: ${packageVersion}
861
+ // Compatible with Mushroom Server version: 0.2.25.4 or higher (https://www.nuget.org/packages/Mushroom/)
862
+ // For Mushroom Server 0.2.18 to 0.2.25.4: Please remove all FindById methods in DbConnector.cs`;
863
+ fs.writeFileSync(aliasProject.output + '/DbConnector.cs', dbConnectorFileContent);
864
+ fs.writeFileSync(aliasProject.output + '/ResourceNames.cs', resourceNamesFileContent);
865
+ fs.writeFileSync(aliasProject.output + '/RoleNames.cs', roleNamesFileContent);
866
+ fs.writeFileSync(aliasProject.output + '/RefactorHelper.cs', refactorHelperFileContent);
867
+ fs.writeFileSync(aliasProject.output + '/Info.cs', infoFileContent);
868
+ common.logInfo(`Generated CSharp MongoDb Classes for ${projectName}@${alias} to folder ${aliasProject.output}`);
869
+ }
870
+ function generateCSharpClassDriver(source, className, fields, description, out) {
871
+ let strClasses = '';
872
+ let strEnumClasses = '';
873
+ let content = '';
874
+ if (description) {
875
+ content += ` /// <summary>
876
+ /// ${singleLine(description)}
877
+ /// </summary>
878
+ `;
879
+ }
880
+ content += ` public partial class ${className}
881
+ {
882
+ `;
883
+ for (const fieldName in fields) {
884
+ const field = fields[fieldName];
885
+ const propertyName = toCSharpName(fieldName);
886
+ let type;
887
+ if (field.type === 'object') {
888
+ strClasses +=
889
+ generateCSharpClassDriver(source, className + '_' + propertyName, field.fields ?? {}, null, out) + newLine;
890
+ type = className + '_' + propertyName;
891
+ }
892
+ else if (field.type === 'array') {
893
+ if (field.items?.type === 'object') {
894
+ strClasses +=
895
+ generateCSharpClassDriver(source, className + '_' + propertyName, field.items.fields ?? {}, null, out) +
896
+ newLine;
897
+ type = `System.Collections.Generic.List<${className}_${propertyName}>`;
898
+ }
899
+ else if (field.items) {
900
+ type = `System.Collections.Generic.List<${getCSharpTypeFromMushroomType(source, field.items.type, field.items.validation && field.items.validation.required)}>`;
901
+ }
902
+ }
903
+ else
904
+ type = getCSharpTypeFromMushroomType(source, field.type, field.validation && field.validation.required);
905
+ content += ` /// <summary>
906
+ /// ${singleLine(field.description)}
907
+ /// </summary>
908
+ [Newtonsoft.Json.JsonProperty(PropertyName ="${fieldName}", NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore${type === 'System.Datetime' ? ', DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore' : ''})]
909
+ [System.Text.Json.Serialization.JsonPropertyName("${fieldName}")]
910
+ [System.Text.Json.Serialization.JsonIgnore(Condition = ${type === 'System.DateTime' ? 'System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingDefault' : 'System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull'})]
911
+ public ${type} ${propertyName} { get; set; }
912
+
913
+ `;
914
+ strEnumClasses += generateEnumClass(source, out, field, `${className.toUpperCase()}_${propertyName.toUpperCase()}_ENUM`);
915
+ }
916
+ if (strEnumClasses) {
917
+ out.strEnumClasses ?? (out.strEnumClasses = '');
918
+ out.strEnumClasses += strEnumClasses;
919
+ }
920
+ content += ' }\n';
921
+ return strClasses + newLine + content;
922
+ }
923
+ export function genCSharpDriver(args, projectName, project, alias, source) {
924
+ const aliasProject = ((project.csharpDriver || {}).alias || {})[alias];
925
+ if (!aliasProject) {
926
+ 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`);
927
+ }
928
+ const entities = common.getEntities(source, aliasProject.allowRoles);
929
+ const namespace = toCSharpName(source.name);
930
+ let strClasses = '';
931
+ let strEnumClasses = '';
932
+ let codeStaticCtor = '';
933
+ let codeStaticProperties = '';
934
+ let codeConnectors = '';
935
+ let codeExtraClasses = '';
936
+ const out = {};
937
+ const accessModifier = aliasProject.accessModifier || 'internal';
938
+ for (const entityName in entities) {
939
+ const className = toCSharpName(entityName);
940
+ strClasses += generateCSharpClassDriver(source, className, entities[entityName].fields, entities[entityName].description, out);
941
+ codeStaticCtor += ` ${className} = new ${className}Connector(client);\n`;
942
+ codeStaticProperties += ` public static ${className}Connector ${className} { get; }\n\n`;
943
+ const entity = entities[entityName];
944
+ codeConnectors += ` ${accessModifier} partial class ${className}Connector : MushroomDriver.MushroomResourceConnector<${className}>
945
+ {
946
+ protected override string Resource { get; } = ${JSON.stringify(entityName)};
947
+
948
+ `;
949
+ if (Object.keys(entity.views ?? {}).length) {
950
+ codeConnectors += ` public ${className}Connector(MushroomDriver.MushroomClient client) : base(client)
951
+ {
952
+ Views = new ${className}Views(Client, () => Resource);
953
+ }
954
+
955
+ `;
956
+ }
957
+ else {
958
+ codeConnectors += ` public ${className}Connector(MushroomDriver.MushroomClient client) : base(client) { }
959
+
960
+ `;
961
+ }
962
+ for (const actionName in entity.actions) {
963
+ switch (actionName) {
964
+ case 'findMany':
965
+ codeConnectors += ` public System.Threading.Tasks.Task<System.Collections.Generic.List<${className}>> List(MushroomDriver.ListArg arg = null)
966
+ {
967
+ return InternalList(arg);
968
+ }
969
+
970
+ `;
971
+ break;
972
+ case 'findById':
973
+ codeConnectors += ` public System.Threading.Tasks.Task<${className}> FindById(MushroomDriver.FindByIdArg arg)
974
+ {
975
+ return InternalFindById(arg);
976
+ }
977
+
978
+ `;
979
+ break;
980
+ case 'createOne':
981
+ codeConnectors += ` public System.Threading.Tasks.Task<string> Create(MushroomDriver.CreateArg<${className}> arg)
982
+ {
983
+ return InternalCreate(arg);
984
+ }
985
+
986
+ `;
987
+ break;
988
+ case 'createMany':
989
+ codeConnectors += ` public System.Threading.Tasks.Task<System.Collections.Generic.List<string>> Create(MushroomDriver.BatchCreateArg<${className}> arg)
990
+ {
991
+ return InternalCreate(arg);
992
+ }
993
+
994
+ `;
995
+ break;
996
+ case 'updateOne':
997
+ codeConnectors += ` public System.Threading.Tasks.Task<string> Update(MushroomDriver.UpdateArg<${className}> arg)
998
+ {
999
+ return InternalUpdate(arg);
1000
+ }
1001
+
1002
+ `;
1003
+ break;
1004
+ case 'updateMany':
1005
+ codeConnectors += ` public System.Threading.Tasks.Task<System.Collections.Generic.List<string>> Update(MushroomDriver.BatchUpdateArg<${className}> arg)
1006
+ {
1007
+ return InternalUpdate(arg);
1008
+ }
1009
+
1010
+ `;
1011
+ break;
1012
+ case 'updatePartially':
1013
+ codeConnectors += ` public System.Threading.Tasks.Task<string> Update(MushroomDriver.PartialUpdateArg<${className}> arg)
1014
+ {
1015
+ return InternalUpdate(arg);
1016
+ }
1017
+
1018
+ public System.Threading.Tasks.Task<string> Update(MushroomDriver.PartialUpdateArg<System.Collections.Generic.Dictionary<string, object>> arg)
1019
+ {
1020
+ return InternalUpdate(arg);
1021
+ }
1022
+
1023
+ `;
1024
+ break;
1025
+ case 'deleteOne':
1026
+ codeConnectors += ` public System.Threading.Tasks.Task<long> Delete(MushroomDriver.DeleteArg arg)
1027
+ {
1028
+ return InternalDelete(arg);
1029
+ }
1030
+
1031
+ `;
1032
+ break;
1033
+ case 'deleteMany':
1034
+ codeConnectors += ` public System.Threading.Tasks.Task<long> Delete(MushroomDriver.BatchDeleteArg arg)
1035
+ {
1036
+ return InternalDelete(arg);
1037
+ }
1038
+
1039
+ `;
1040
+ break;
1041
+ default: {
1042
+ if (actionName.indexOf('_raw_http_method_'))
1043
+ break;
1044
+ const customMethod = toCSharpName(actionName.substring('_raw_http_method_'.length));
1045
+ codeConnectors += ` public async System.Threading.Tasks.Task<${className}${customMethod}Result> ${customMethod}(${className}${customMethod}Arg arg)
1046
+ {
1047
+ if (arg == null)
1048
+ throw new System.ArgumentNullException(nameof(arg));
1049
+
1050
+ var request = new MushroomDriver.MushroomRequest
1051
+ {
1052
+ RootApiUrl = Client.RootApiUrl,
1053
+ Url = Client.RootApiUrl + arg.BuildUrl(),
1054
+ Method = arg.Method
1055
+ };
1056
+ var headers = new System.Collections.Generic.Dictionary<string, string>
1057
+ {
1058
+ {"X-Requested-With", "Mushroom Driver " + MushroomDriver.MushroomConnector.Version}
1059
+ };
1060
+ if (arg.UseXHttpMethodOverride)
1061
+ {
1062
+ headers["X-Http-Method-Override"] = request.Method;
1063
+ request.Method = "POST";
1064
+ }
1065
+ request.Headers = headers;
1066
+ request.Data = arg.CustomData ?? arg.Data;
1067
+ var response = await MushroomDriver.MushroomConnector.Execute(request);
1068
+ var result = response.GetResult<${className}${customMethod}Result>();
1069
+ result.MushroomResponseMetadata = response.Metadata;
1070
+ return result;
1071
+ }
1072
+
1073
+ `;
1074
+ codeExtraClasses += ` ${accessModifier} partial class ${className}${customMethod}Result
1075
+ {
1076
+ public System.Collections.Generic.Dictionary<string, object> MushroomResponseMetadata { get; set; }
1077
+ }
1078
+
1079
+ ${accessModifier} partial class ${className}${customMethod}Body { }
1080
+
1081
+ ${accessModifier} partial class ${className}${customMethod}Arg : MushroomDriver.MushroomRequestArg
1082
+ {
1083
+ public override string BuildUrl()
1084
+ {
1085
+ BuildCustomUrl();
1086
+ return CustomUrl;
1087
+ }
1088
+
1089
+ partial void BuildCustomUrl();
1090
+
1091
+ private string OriginUrl => "${entityName}s/${actionName.substring('_raw_http_method_'.length)}";
1092
+
1093
+ private string CustomUrl { get; set; } = "${entityName}s/${actionName.substring('_raw_http_method_'.length)}";
1094
+
1095
+ public override string Method { get; } = "${actionName.substring('_raw_http_method_'.length)}";
1096
+
1097
+ public ${className}${customMethod}Body Data { get; set; }
1098
+
1099
+ public object CustomData { get; set; }
1100
+ }
1101
+
1102
+ `;
1103
+ break;
1104
+ }
1105
+ }
1106
+ }
1107
+ if (Object.keys(entity.views ?? {}).length) {
1108
+ codeConnectors += ` public ${className}Views Views { get; }
1109
+
1110
+ `;
1111
+ codeExtraClasses += ` ${accessModifier} partial class ${className}Views : MushroomDriver.MushroomViewConnector
1112
+ {
1113
+ protected System.Func<string> FnResource;
1114
+
1115
+ public ${className}Views(MushroomDriver.MushroomClient client, System.Func<string> fnResource) : base(client)
1116
+ {
1117
+ FnResource = fnResource;
1118
+ }
1119
+
1120
+ `;
1121
+ let viewExtraClass = '';
1122
+ for (const viewName in entity.views) {
1123
+ const viewMethodName = toCSharpName(viewName);
1124
+ let hasNoParamView = false;
1125
+ entity.views[viewName].forEach((view) => {
1126
+ const role = view.grant === '*' ? '' : `_${toCSharpName(view.grant)}`;
1127
+ const hasParameter = view.parameters && view.parameters.length;
1128
+ if (hasParameter) {
1129
+ codeExtraClasses += ` public System.Threading.Tasks.Task<System.Collections.Generic.List<${className}View_${viewMethodName}Result>> ${viewMethodName}(${className}View${role}_${viewMethodName}Arg arg)
1130
+ {
1131
+ return InternalExecuteView<${className}View_${viewMethodName}Result>(new MushroomDriver.ViewArg<${className}View${role}_${viewMethodName}Arg> {
1132
+ Parameters = arg,
1133
+ Resource = FnResource?.Invoke(),
1134
+ ViewName = "${viewName}"
1135
+ });
1136
+ }
1137
+
1138
+ `;
1139
+ viewExtraClass += ` ${accessModifier} partial class ${className}View${role}_${viewMethodName}Arg
1140
+ {
1141
+ `;
1142
+ view.parameters?.forEach((p) => {
1143
+ let type = getCSharpTypeFromMushroomType(source, p.type, p.validation && p.validation.required);
1144
+ if (p.isArray)
1145
+ type = `System.Collections.Generic.List<${type}>`;
1146
+ viewExtraClass += ` [Newtonsoft.Json.JsonProperty(PropertyName = "${p.field}", NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore${type === 'System.Datetime' ? ', DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore' : ''})]
1147
+ [System.Text.Json.Serialization.JsonPropertyName("${p.field}")]
1148
+ [System.Text.Json.Serialization.JsonIgnore(Condition = ${type === 'System.DateTime' ? 'System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingDefault' : 'System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull'})]
1149
+ public ${type} ${toCSharpName(p.field)} { get; set; }
1150
+
1151
+ `;
1152
+ });
1153
+ viewExtraClass += ` }
1154
+
1155
+ `;
1156
+ }
1157
+ else if (!hasNoParamView) {
1158
+ hasNoParamView = true;
1159
+ codeExtraClasses += ` public System.Threading.Tasks.Task<System.Collections.Generic.List<${className}View_${viewMethodName}Result>> ${viewMethodName}()
1160
+ {
1161
+ return InternalExecuteView<${className}View_${viewMethodName}Result>(new MushroomDriver.ViewArg {
1162
+ Resource = FnResource?.Invoke(),
1163
+ ViewName = "${viewName}"
1164
+ });
1165
+ }
1166
+
1167
+ `;
1168
+ }
1169
+ });
1170
+ viewExtraClass += ` ${accessModifier} partial class ${className}View_${viewMethodName}Result
1171
+ {
1172
+
1173
+ }
1174
+
1175
+ `;
1176
+ }
1177
+ codeExtraClasses += ` }
1178
+
1179
+ ${viewExtraClass}`;
1180
+ }
1181
+ codeConnectors += ' }\n\n';
1182
+ }
1183
+ if (out.strEnumClasses)
1184
+ strEnumClasses += out.strEnumClasses;
1185
+ const code = `// This file was generated by Mushroom CLI ${packageVersion} (https://www.npmjs.com/package/mushroom-cli), please do not modify
1186
+
1187
+ // Require package: Mushroom.Driver version 1.4.0 or later (https://www.nuget.org/packages/Mushroom.Driver/)
1188
+
1189
+ // ReSharper disable InconsistentNaming
1190
+ // ReSharper disable PartialTypeWithSinglePart
1191
+ // ReSharper disable PartialMethodWithSinglePart
1192
+ // ReSharper disable UnusedMember.Global
1193
+ // ReSharper disable UnusedMember.Local
1194
+ // ReSharper disable IdentifierTypo
1195
+ // ReSharper disable StringLiteralTypo
1196
+ // ReSharper disable CommentTypo
1197
+ // ReSharper disable AutoPropertyCanBeMadeGetOnly.Local
1198
+
1199
+
1200
+ using JsonPropertyAttribute = Newtonsoft.Json.JsonPropertyAttribute;
1201
+ using NullValueHandling = Newtonsoft.Json.NullValueHandling;
1202
+ using ${namespace}.Resources;
1203
+
1204
+ namespace ${namespace}
1205
+ {
1206
+ ${accessModifier} partial class API
1207
+ {
1208
+ static API()
1209
+ {
1210
+ CustomizeRootApiUrl();
1211
+ var client = new MushroomDriver.MushroomClient(_rootApiUrl);
1212
+ MushroomClient = client;
1213
+
1214
+ ${Array.isArray(aliasProject.features) && aliasProject.features.indexOf('auth') !== -1 ? 'Authentication = new MushroomDriver.Auth.Authentication(_rootApiUrl);' : ''}
1215
+ ${Array.isArray(aliasProject.features) && aliasProject.features.indexOf('file') !== -1 ? 'FileExtension = new MushroomDriver.File.FileExtension(_rootApiUrl);' : ''}
1216
+
1217
+ ${codeStaticCtor}
1218
+ }
1219
+
1220
+ static partial void CustomizeRootApiUrl();
1221
+
1222
+ private static string _rootApiUrl = ${JSON.stringify(common.getRootUrl(source))};
1223
+
1224
+ public static MushroomDriver.MushroomClient MushroomClient { get; }
1225
+
1226
+ ${Array.isArray(aliasProject.features) && aliasProject.features.indexOf('auth') !== -1 ? 'public static MushroomDriver.Auth.Authentication Authentication { get; }' : ''}
1227
+
1228
+ ${Array.isArray(aliasProject.features) && aliasProject.features.indexOf('file') !== -1 ? 'public static MushroomDriver.File.FileExtension FileExtension { get; }' : ''}
1229
+
1230
+ ${codeStaticProperties}
1231
+ }
1232
+
1233
+ /*${accessModifier} partial class API
1234
+ {
1235
+ static partial void CustomizeRootApiUrl()
1236
+ {
1237
+ _rootApiUrl = "your customized root api url";
1238
+ }
1239
+ }*/
1240
+
1241
+ ${codeConnectors}${codeExtraClasses}
1242
+ }
1243
+
1244
+ namespace ${namespace}.Resources
1245
+ {
1246
+ ${strClasses}
1247
+ }
1248
+
1249
+ namespace ${namespace}.Enums
1250
+ {
1251
+ ${strEnumClasses}
1252
+ }`;
1253
+ common.ensureFolder(aliasProject.output);
1254
+ fs.writeFileSync(aliasProject.output, code);
1255
+ common.logInfo(`Generated CSharp Driver for ${projectName}@${alias} to ${aliasProject.output}`);
1256
+ }