okai 0.0.24 → 0.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cs-ast.js CHANGED
@@ -15,6 +15,25 @@ export class CSharpAst {
15
15
  "undefined": sys("string"),
16
16
  "bigint": sys("long"),
17
17
  "any": sysObj,
18
+ "ArrayBuffer": sys("byte[]"),
19
+ "SharedArrayBuffer": sys("byte[]"),
20
+ "Int8Array": sys("sbyte[]"),
21
+ "UInt8Array": sys("byte[]"),
22
+ "Uint8ClampedArray": sys("byte[]"),
23
+ "Int16Array": sys("short[]"),
24
+ "UInt16Array": sys("ushort[]"),
25
+ "Int32Array": sys("int[]"),
26
+ "UInt32Array": sys("uint[]"),
27
+ "Float16Array": sys("float[]"),
28
+ "Float32Array": sys("float[]"),
29
+ "Float64Array": sys("double[]"),
30
+ "BigInt64Array": sys("long[]"),
31
+ "BigUInt64Array": sys("long[]"),
32
+ "Array": { name: "List", genericArgs: [], namespace: "System.Collections.Generic" },
33
+ "Map": { name: "Dictionary", genericArgs: [], namespace: "System.Collections.Generic" },
34
+ "WeakMap": { name: "Dictionary", genericArgs: [], namespace: "System.Collections.Generic" },
35
+ "Set": { name: "HashSet", genericArgs: [], namespace: "System.Collections.Generic" },
36
+ "WeakSet": { name: "HashSet", genericArgs: [], namespace: "System.Collections.Generic" },
18
37
  };
19
38
  decimalTypeProps = [
20
39
  "price", "cost", "amount", "total", "salary", "balance", "rate", "discount", "tax", "fee"
@@ -181,24 +200,15 @@ export class CSharpAst {
181
200
  ].map(x => x.toLowerCase());
182
201
  ignoreReadValidators = this.requestPropAttrs.filter(x => x.startsWith('validate')).map(x => x.toLowerCase());
183
202
  ignoreDeleteValidators = this.requestPropAttrs.filter(x => x.startsWith('validate')).map(x => x.toLowerCase());
184
- unwrap(type) {
185
- if (type.endsWith("?")) {
186
- return type.substring(0, type.length - 1);
187
- }
188
- return type;
189
- }
190
- nullable(type) {
191
- return type.endsWith('?') ? type : `${type}?`;
192
- }
193
203
  isEnum(type) {
194
- type = this.unwrap(type);
204
+ type = unwrap(type);
195
205
  return this.ast.enums.some(x => x.name === type) || this.result.types.find(x => x.name === type && x.isEnum);
196
206
  }
197
207
  isValueType(type) {
198
- type = this.unwrap(type);
208
+ type = unwrap(type);
199
209
  return this.valueTypes.includes(type) || this.isEnum(type);
200
210
  }
201
- ast = { classes: [], interfaces: [], enums: [] };
211
+ ast = { references: [], classes: [], interfaces: [], enums: [] };
202
212
  result = {
203
213
  config: {},
204
214
  namespaces: [],
@@ -213,6 +223,13 @@ export class CSharpAst {
213
223
  const elType = this.csharpType(type.substring(0, type.length - 2), propName);
214
224
  return Object.assign({}, elType, { name: elType.name + '[]' });
215
225
  }
226
+ if (type.endsWith('>')) {
227
+ const start = type.indexOf('<');
228
+ const genericArgs = type.substring(start + 1, type.length - 1).split(',').map(x => this.csharpType(x.trim()).name);
229
+ const baseType = this.csharpType(type.substring(0, start), propName);
230
+ const ret = Object.assign({}, baseType, { genericArgs });
231
+ return ret;
232
+ }
216
233
  if (propName) {
217
234
  if (type === "number") {
218
235
  if (this.decimalTypeProps.some(x => propName.toLowerCase().includes(x))) {
@@ -269,16 +286,20 @@ export class CSharpAst {
269
286
  const type = this.csharpType(p.type, p.name);
270
287
  const prop = {
271
288
  name: this.toCsName(p.name),
272
- type: p.optional ? this.nullable(type.name) : type.name,
289
+ type: p.optional ? nullable(type.name) : type.name,
273
290
  };
274
291
  if (type.namespace) {
275
292
  prop.namespace = type.namespace;
276
293
  }
294
+ if (type.genericArgs) {
295
+ prop.genericArgs = type.genericArgs;
296
+ }
277
297
  if (p.comment) {
278
298
  prop.description = p.comment;
279
299
  }
280
300
  if (prop.name === 'Id') {
281
301
  prop.isPrimaryKey = true;
302
+ prop.isRequired = true;
282
303
  }
283
304
  const valueType = this.isValueType(prop.type);
284
305
  if (valueType) {
@@ -365,196 +386,6 @@ export class CSharpAst {
365
386
  get typesWithReferences() {
366
387
  return this.result.types.filter(x => !x.isEnum && !x.isInterface && x.properties?.some(x => x.attributes?.some(x => x.name === 'Reference')));
367
388
  }
368
- replaceReferences(references) {
369
- // The most important types are the ones with the most references
370
- const refCount = (t) => t.properties?.filter(p => this.result.types.find(x => x.name === p.type && p.namespace === 'MyApp')).length || 0;
371
- const importantTypes = this.result.types.sort((x, y) => refCount(y) - refCount(x));
372
- for (const type of this.result.types) {
373
- if (references.includes(type.name)) {
374
- const importantType = importantTypes.find(x => x.properties?.some(p => p.type === type.name));
375
- if (importantType) {
376
- const newName = `${importantType.name}${type.name}`;
377
- this.replaceReference(type.name, newName);
378
- }
379
- }
380
- }
381
- }
382
- replaceReference(fromType, toType) {
383
- for (const type of this.result.types) {
384
- if (type.name === fromType) {
385
- type.name = toType;
386
- }
387
- if (type.properties) {
388
- for (const prop of type.properties) {
389
- if (prop.type === fromType) {
390
- prop.type = toType;
391
- }
392
- if (prop.name === fromType) {
393
- prop.name = toType;
394
- }
395
- if (prop.name === `${fromType}Id`) {
396
- prop.name = `${toType}Id`;
397
- }
398
- }
399
- }
400
- }
401
- }
402
- replaceIds() {
403
- for (const type of this.classes) {
404
- const idProp = type.properties?.find(x => x.name === `${type.name}Id`);
405
- if (idProp) {
406
- type.properties?.forEach(x => delete x.isPrimaryKey);
407
- idProp.name = 'Id';
408
- idProp.isPrimaryKey = true;
409
- }
410
- // If using a shortened id for the type e.g. (PerformanceReview, ReviewId)
411
- const firstProp = type.properties?.[0];
412
- if (firstProp?.name.endsWith('Id') && type.name.includes(firstProp.name.substring(0, firstProp.name.length - 2))) {
413
- firstProp.name = 'Id';
414
- firstProp.isPrimaryKey = true;
415
- }
416
- }
417
- const anyIntPks = this.classes.some(x => x.properties?.some(p => p.isPrimaryKey && this.integerTypes.includes(p.type)));
418
- if (!anyIntPks) {
419
- for (const type of this.classes) {
420
- const idProp = type.properties?.find(x => x.isPrimaryKey);
421
- if (idProp) {
422
- idProp.type = 'int';
423
- }
424
- }
425
- }
426
- }
427
- convertReferenceTypes() {
428
- for (const type of this.classes) {
429
- for (let i = 0; i < type.properties.length; i++) {
430
- const p = type.properties[i];
431
- const refType = this.result.types.find(x => x.name === p.type && x.namespace === 'MyApp' && !x.isEnum);
432
- if (refType) {
433
- const fkId = `${p.name}Id`;
434
- let idProp = refType.properties?.find(x => x.name === 'Id');
435
- if (!idProp) {
436
- idProp = { name: 'Id', type: 'int', isPrimaryKey: true, isValueType: true, namespace: 'System' };
437
- refType.properties?.unshift(idProp);
438
- }
439
- // Only add if FK Id prop does not already exist
440
- if (!type.properties.find(x => x.name === fkId)) {
441
- const fkProp = {
442
- name: fkId,
443
- type: idProp.type,
444
- namespace: idProp.namespace,
445
- attributes: [{
446
- name: "References",
447
- constructorArgs: [{
448
- name: "type",
449
- type: "Type",
450
- value: `typeof(${p.type})`
451
- }],
452
- args: []
453
- }]
454
- };
455
- type.properties.splice(i, 0, fkProp);
456
- }
457
- if (!p.attributes)
458
- p.attributes = [];
459
- p.attributes.push({ name: "Reference" });
460
- i++; // Skip over added fk prop
461
- }
462
- }
463
- }
464
- }
465
- convertArrayReferenceTypes() {
466
- for (const type of this.classes) {
467
- for (const prop of type.properties) {
468
- if (prop.type.endsWith('[]')) {
469
- const elType = prop.type.substring(0, prop.type.length - 2);
470
- const refType = this.result.types.find(x => x.name === elType && x.namespace === 'MyApp' && !x.isEnum);
471
- if (refType && refType.properties?.find(x => x.name === 'Id' || x.isPrimaryKey)) {
472
- prop.namespace = 'System.Collections.Generic';
473
- prop.genericArgs = [elType];
474
- prop.type = 'List`1';
475
- if (!prop.attributes)
476
- prop.attributes = [];
477
- prop.attributes.push({ name: "Reference" });
478
- let fkProp = refType.properties.find(x => x.name === `${type.name}Id`);
479
- if (!fkProp) {
480
- fkProp = {
481
- name: `${type.name}Id`,
482
- type: 'int',
483
- isValueType: true,
484
- namespace: 'System',
485
- attributes: [{
486
- name: "References",
487
- constructorArgs: [{
488
- name: "type",
489
- type: "Type",
490
- value: `typeof(${type.name})`
491
- }]
492
- }]
493
- };
494
- // Insert fk prop after last `*Id` prop
495
- const lastIdPropIndex = refType.properties.findLastIndex(x => x.name.endsWith('Id'));
496
- if (lastIdPropIndex >= 0) {
497
- refType.properties.splice(lastIdPropIndex + 1, 0, fkProp);
498
- }
499
- else {
500
- refType.properties.push(fkProp);
501
- }
502
- }
503
- }
504
- }
505
- }
506
- }
507
- }
508
- convertArraysToLists() {
509
- for (const type of this.classes) {
510
- for (const prop of type.properties) {
511
- const optional = prop.type.endsWith('?');
512
- let propType = this.unwrap(prop.type);
513
- if (propType.endsWith('[]')) {
514
- const elType = propType.substring(0, propType.length - 2);
515
- prop.namespace = 'System.Collections.Generic';
516
- prop.genericArgs = [elType];
517
- prop.type = 'List`1' + (optional ? '?' : '');
518
- }
519
- }
520
- }
521
- }
522
- addMissingReferencesToForeignKeyProps() {
523
- for (const type of this.typesWithPrimaryKeys) {
524
- for (const prop of type.properties) {
525
- if (prop.name.endsWith('Id') && !prop.isPrimaryKey && !prop.attributes?.some(x => x.name.startsWith('Reference'))) {
526
- const refTypeName = prop.name.substring(0, prop.name.length - 2);
527
- const refType = this.result.types.find(x => x.name === refTypeName && x.namespace === 'MyApp' && !x.isEnum);
528
- if (refType) {
529
- if (!prop.attributes)
530
- prop.attributes = [];
531
- prop.attributes.push({
532
- name: "References",
533
- constructorArgs: [{
534
- name: "type",
535
- type: "Type",
536
- value: `typeof(${refTypeName})`
537
- }]
538
- });
539
- }
540
- }
541
- }
542
- }
543
- }
544
- addAutoIncrementAttrs() {
545
- for (const type of this.classes) {
546
- for (const prop of type.properties) {
547
- if (prop.isPrimaryKey) {
548
- if (prop.type === 'int' || prop.type === 'long' || prop.type === 'Int32' || prop.type === 'Int64') {
549
- if (!prop.attributes)
550
- prop.attributes = [];
551
- const attr = { name: "AutoIncrement" };
552
- prop.attributes.push(attr);
553
- }
554
- }
555
- }
556
- }
557
- }
558
389
  onlyAttrs(attrs, only) {
559
390
  if (!attrs)
560
391
  return;
@@ -683,7 +514,7 @@ export class CSharpAst {
683
514
  properties: pk
684
515
  ? [
685
516
  Object.assign({}, pk, {
686
- type: this.nullable(pk.type),
517
+ type: nullable(pk.type),
687
518
  attributes: this.attrsFor("Read", "Prop", pk.attributes),
688
519
  }),
689
520
  idsProp
@@ -804,7 +635,7 @@ export class CSharpAst {
804
635
  properties: type.properties?.filter(x => !x.attributes?.some(x => this.ignoreUpdateProps.includes(x.name.toLowerCase()))).map(x => Object.assign({}, x, {
805
636
  type: x.isPrimaryKey
806
637
  ? x.type
807
- : `${this.nullable(x.type)}`,
638
+ : `${nullable(x.type)}`,
808
639
  attributes: this.attrsFor("Update", "Prop", x.attributes),
809
640
  })),
810
641
  attributes: this.attrsFor("Update", "Type", type.attributes),
@@ -857,7 +688,7 @@ export class CSharpAst {
857
688
  properties: pk
858
689
  ? [
859
690
  Object.assign({}, pk, {
860
- type: this.nullable(pk.type),
691
+ type: nullable(pk.type),
861
692
  attributes: this.attrsFor("Delete", "Prop", pk.attributes),
862
693
  }),
863
694
  idsProp
@@ -885,6 +716,8 @@ export class CSharpAst {
885
716
  this.result.operations.push(deleteApi);
886
717
  }
887
718
  }
719
+ this.filterModelAttributes();
720
+ return this.result;
888
721
  }
889
722
  filterModelAttributes() {
890
723
  for (const type of this.classes) {
@@ -898,68 +731,6 @@ export class CSharpAst {
898
731
  });
899
732
  }
900
733
  }
901
- // Add Icon for BuiltIn UIs and AutoQueryGrid to known type names
902
- addIconsToKnownTypes() {
903
- for (const type of this.typesWithPrimaryKeys) {
904
- const icon = Icons[type.name];
905
- if (icon) {
906
- if (!type.attributes)
907
- type.attributes = [];
908
- const existingIcon = type.attributes.find(x => x.name === 'Icon');
909
- if (existingIcon) {
910
- // remove empty icon
911
- if (existingIcon.constructorArgs?.[0]?.value === '') {
912
- type.attributes = type.attributes.filter(x => x !== existingIcon);
913
- }
914
- return;
915
- }
916
- type.attributes.push({
917
- name: "Icon",
918
- args: [{ name: "Svg", type: "string", value: icon }]
919
- });
920
- }
921
- }
922
- }
923
- // Hide Reference Properties from AutoQueryGrid Grid View
924
- hideReferenceProperties() {
925
- for (const type of this.typesWithReferences) {
926
- for (const prop of type.properties.filter(x => x.attributes?.some(x => x.name === 'Reference'))) {
927
- if (!prop.attributes)
928
- prop.attributes = [];
929
- //[Format(FormatMethods.Hidden)]
930
- prop.attributes.push({
931
- name: "Format",
932
- constructorArgs: [{ name: "method", type: "constant", value: "FormatMethods.Hidden" }]
933
- });
934
- }
935
- }
936
- }
937
- // Replace User Tables and FKs with AuditBase tables and
938
- replaceUserReferencesWithAuditTables() {
939
- for (const type of this.typesWithPrimaryKeys) {
940
- const removeProps = [];
941
- for (const prop of type.properties) {
942
- if (prop.name === 'UserId') {
943
- removeProps.push(prop.name);
944
- }
945
- if (prop.attributes?.some(a => a.name === 'Reference' && a.constructorArgs?.some(x => x.value === 'typeof(User)'))) {
946
- removeProps.push(prop.name);
947
- }
948
- if (prop.type === 'User') {
949
- removeProps.push(prop.name);
950
- }
951
- if (prop.genericArgs && prop.genericArgs.includes('User')) {
952
- removeProps.push(prop.name);
953
- }
954
- }
955
- if (removeProps.length) {
956
- type.properties = type.properties.filter(x => !removeProps.includes(x.name));
957
- type.inherits = { name: "AuditBase", namespace: "ServiceStack" };
958
- }
959
- }
960
- // Remove User Table
961
- this.result.types = this.result.types.filter(x => x.name !== 'User');
962
- }
963
734
  parseTypes() {
964
735
  this.ast.classes.forEach(c => {
965
736
  const name = toPascalCase(c.name);
@@ -973,23 +744,12 @@ export class CSharpAst {
973
744
  return;
974
745
  this.addMetadataEnum(e);
975
746
  });
976
- this.replaceReferences(['Service']);
977
- this.replaceIds();
978
- this.convertReferenceTypes();
979
- this.convertArrayReferenceTypes();
980
- this.convertArraysToLists();
981
- this.addMissingReferencesToForeignKeyProps();
982
- this.addAutoIncrementAttrs();
983
- this.addIconsToKnownTypes();
984
- this.hideReferenceProperties();
985
- this.replaceUserReferencesWithAuditTables();
986
- this.createAutoCrudApis();
987
- this.filterModelAttributes();
988
747
  }
989
748
  parse(ast) {
990
749
  const classes = ast.classes.concat(ast.interfaces);
991
750
  const enums = ast.enums;
992
751
  this.ast = {
752
+ references: [],
993
753
  classes: classes,
994
754
  interfaces: [],
995
755
  enums: enums ?? [],
@@ -1012,7 +772,290 @@ export class CSharpAst {
1012
772
  return this.result;
1013
773
  }
1014
774
  }
1015
- export function toMetadataTypes(ast) {
1016
- const generator = new CSharpAst();
1017
- return generator.parse(ast);
775
+ export const Transforms = {
776
+ Default: [
777
+ convertReferenceTypes,
778
+ convertArrayReferenceTypes,
779
+ convertArraysToLists,
780
+ addMissingReferencesToForeignKeyProps,
781
+ addAutoIncrementAttrs,
782
+ addIconsToKnownTypes,
783
+ hideReferenceProperties,
784
+ ],
785
+ };
786
+ export function toMetadataTypes(ast, transforms) {
787
+ const gen = new CSharpAst();
788
+ gen.parse(ast);
789
+ if (!transforms)
790
+ transforms = Transforms.Default;
791
+ for (const transform of transforms) {
792
+ transform(gen);
793
+ }
794
+ return gen.createAutoCrudApis();
795
+ }
796
+ export function unwrap(type) {
797
+ if (type.endsWith("?")) {
798
+ return type.substring(0, type.length - 1);
799
+ }
800
+ return type;
801
+ }
802
+ export function nullable(type) {
803
+ return type.endsWith('?') ? type : `${type}?`;
804
+ }
805
+ export function replaceReference(gen, fromType, toType) {
806
+ for (const type of gen.result.types) {
807
+ if (type.name === fromType) {
808
+ type.name = toType;
809
+ }
810
+ if (type.properties) {
811
+ for (const prop of type.properties) {
812
+ if (prop.type === fromType) {
813
+ prop.type = toType;
814
+ }
815
+ if (prop.name === fromType) {
816
+ prop.name = toType;
817
+ }
818
+ if (prop.name === `${fromType}Id`) {
819
+ prop.name = `${toType}Id`;
820
+ }
821
+ }
822
+ }
823
+ }
824
+ }
825
+ export function replaceServiceReferences(gen) {
826
+ replaceReferences(gen, ['Service']);
827
+ }
828
+ export function replaceReferences(gen, references) {
829
+ // The most important types are the ones with the most references
830
+ const refCount = (t) => t.properties?.filter(p => gen.result.types.find(x => x.name === p.type && p.namespace === 'MyApp')).length || 0;
831
+ const importantTypes = gen.result.types.sort((x, y) => refCount(y) - refCount(x));
832
+ for (const type of gen.result.types) {
833
+ if (references.includes(type.name)) {
834
+ const importantType = importantTypes.find(x => x.properties?.some(p => p.type === type.name));
835
+ if (importantType) {
836
+ const newName = `${importantType.name}${type.name}`;
837
+ replaceReference(gen, type.name, newName);
838
+ }
839
+ }
840
+ }
841
+ }
842
+ export function replaceIds(gen) {
843
+ for (const type of gen.classes) {
844
+ const idProp = type.properties?.find(x => x.name === `${type.name}Id`);
845
+ if (idProp) {
846
+ type.properties?.forEach(x => delete x.isPrimaryKey);
847
+ idProp.name = 'Id';
848
+ idProp.isPrimaryKey = true;
849
+ }
850
+ // If using a shortened id for the type e.g. (PerformanceReview, ReviewId)
851
+ const firstProp = type.properties?.[0];
852
+ if (firstProp?.name.endsWith('Id') && type.name.includes(firstProp.name.substring(0, firstProp.name.length - 2))) {
853
+ firstProp.name = 'Id';
854
+ firstProp.isPrimaryKey = true;
855
+ }
856
+ }
857
+ // Replace all string Ids with int Ids
858
+ const anyIntPks = gen.classes.some(x => x.properties?.some(p => p.isPrimaryKey && gen.integerTypes.includes(p.type)));
859
+ if (!anyIntPks) {
860
+ for (const type of gen.classes) {
861
+ const idProp = type.properties?.find(x => x.isPrimaryKey);
862
+ if (idProp) {
863
+ idProp.type = 'int';
864
+ }
865
+ }
866
+ }
867
+ }
868
+ export function convertReferenceTypes(gen) {
869
+ for (const type of gen.classes) {
870
+ for (let i = 0; i < type.properties.length; i++) {
871
+ const p = type.properties[i];
872
+ const refType = gen.result.types.find(x => x.name === p.type && x.namespace === 'MyApp' && !x.isEnum);
873
+ if (refType) {
874
+ const fkId = `${p.name}Id`;
875
+ let idProp = refType.properties?.find(x => x.name === 'Id');
876
+ if (!idProp) {
877
+ idProp = { name: 'Id', type: 'int', isPrimaryKey: true, isRequired: true, isValueType: true, namespace: 'System' };
878
+ refType.properties?.unshift(idProp);
879
+ }
880
+ // Only add if FK Id prop does not already exist
881
+ if (!type.properties.find(x => x.name === fkId)) {
882
+ const fkProp = {
883
+ name: fkId,
884
+ type: idProp.type,
885
+ namespace: idProp.namespace,
886
+ attributes: [{
887
+ name: "References",
888
+ constructorArgs: [{
889
+ name: "type",
890
+ type: "Type",
891
+ value: `typeof(${p.type})`
892
+ }],
893
+ args: []
894
+ }]
895
+ };
896
+ type.properties.splice(i, 0, fkProp);
897
+ }
898
+ if (!p.attributes)
899
+ p.attributes = [];
900
+ p.attributes.push({ name: "Reference" });
901
+ i++; // Skip over added fk prop
902
+ }
903
+ }
904
+ }
905
+ }
906
+ export function convertArrayReferenceTypes(gen) {
907
+ for (const type of gen.classes) {
908
+ for (const prop of type.properties) {
909
+ if (prop.type.endsWith('[]')) {
910
+ const elType = prop.type.substring(0, prop.type.length - 2);
911
+ const refType = gen.result.types.find(x => x.name === elType && x.namespace === 'MyApp' && !x.isEnum);
912
+ if (refType && refType.properties?.find(x => x.name === 'Id' || x.isPrimaryKey)) {
913
+ prop.namespace = 'System.Collections.Generic';
914
+ prop.genericArgs = [elType];
915
+ prop.type = 'List`1';
916
+ if (!prop.attributes)
917
+ prop.attributes = [];
918
+ prop.attributes.push({ name: "Reference" });
919
+ let fkProp = refType.properties.find(x => x.name === `${type.name}Id`);
920
+ if (!fkProp) {
921
+ fkProp = {
922
+ name: `${type.name}Id`,
923
+ type: 'int',
924
+ isValueType: true,
925
+ namespace: 'System',
926
+ attributes: [{
927
+ name: "References",
928
+ constructorArgs: [{
929
+ name: "type",
930
+ type: "Type",
931
+ value: `typeof(${type.name})`
932
+ }]
933
+ }]
934
+ };
935
+ // Insert fk prop after last `*Id` prop
936
+ const lastIdPropIndex = refType.properties.findLastIndex(x => x.name.endsWith('Id'));
937
+ if (lastIdPropIndex >= 0) {
938
+ refType.properties.splice(lastIdPropIndex + 1, 0, fkProp);
939
+ }
940
+ else {
941
+ refType.properties.push(fkProp);
942
+ }
943
+ }
944
+ }
945
+ }
946
+ }
947
+ }
948
+ }
949
+ export function convertArraysToLists(gen) {
950
+ for (const type of gen.classes) {
951
+ for (const prop of type.properties) {
952
+ const optional = prop.type.endsWith('?');
953
+ let propType = unwrap(prop.type);
954
+ if (propType.endsWith('[]')) {
955
+ const elType = propType.substring(0, propType.length - 2);
956
+ prop.namespace = 'System.Collections.Generic';
957
+ prop.genericArgs = [elType];
958
+ prop.type = 'List`1' + (optional ? '?' : '');
959
+ }
960
+ }
961
+ }
962
+ }
963
+ export function addMissingReferencesToForeignKeyProps(gen) {
964
+ for (const type of gen.typesWithPrimaryKeys) {
965
+ for (const prop of type.properties) {
966
+ if (prop.name.endsWith('Id') && !prop.isPrimaryKey && !prop.attributes?.some(x => x.name.startsWith('Reference'))) {
967
+ const refTypeName = prop.name.substring(0, prop.name.length - 2);
968
+ const refType = gen.result.types.find(x => x.name === refTypeName && x.namespace === 'MyApp' && !x.isEnum);
969
+ if (refType) {
970
+ if (!prop.attributes)
971
+ prop.attributes = [];
972
+ prop.attributes.push({
973
+ name: "References",
974
+ constructorArgs: [{
975
+ name: "type",
976
+ type: "Type",
977
+ value: `typeof(${refTypeName})`
978
+ }]
979
+ });
980
+ }
981
+ }
982
+ }
983
+ }
984
+ }
985
+ export function addAutoIncrementAttrs(gen) {
986
+ for (const type of gen.classes) {
987
+ for (const prop of type.properties) {
988
+ const hasPkAttr = prop.attributes?.some(x => ['primarykey', 'autoincrement', 'autoid'].includes(x.name.toLowerCase()));
989
+ if (prop.isPrimaryKey && !hasPkAttr) {
990
+ if (prop.type === 'int' || prop.type === 'long' || prop.type === 'Int32' || prop.type === 'Int64') {
991
+ if (!prop.attributes)
992
+ prop.attributes = [];
993
+ const attr = { name: "AutoIncrement" };
994
+ prop.attributes.push(attr);
995
+ }
996
+ }
997
+ }
998
+ }
999
+ }
1000
+ // Add Icon for BuiltIn UIs and AutoQueryGrid to known type names
1001
+ export function addIconsToKnownTypes(gen) {
1002
+ for (const type of gen.typesWithPrimaryKeys) {
1003
+ const icon = Icons[type.name];
1004
+ if (icon) {
1005
+ if (!type.attributes)
1006
+ type.attributes = [];
1007
+ const existingIcon = type.attributes.find(x => x.name === 'Icon');
1008
+ if (existingIcon) {
1009
+ // remove empty icon
1010
+ if (existingIcon.constructorArgs?.[0]?.value === '') {
1011
+ type.attributes = type.attributes.filter(x => x !== existingIcon);
1012
+ }
1013
+ return;
1014
+ }
1015
+ type.attributes.push({
1016
+ name: "Icon",
1017
+ args: [{ name: "Svg", type: "string", value: icon }]
1018
+ });
1019
+ }
1020
+ }
1021
+ }
1022
+ // Hide Reference Properties from AutoQueryGrid Grid View
1023
+ export function hideReferenceProperties(gen) {
1024
+ for (const type of gen.typesWithReferences) {
1025
+ for (const prop of type.properties.filter(x => x.attributes?.some(x => x.name === 'Reference'))) {
1026
+ if (!prop.attributes)
1027
+ prop.attributes = [];
1028
+ //[Format(FormatMethods.Hidden)]
1029
+ prop.attributes.push({
1030
+ name: "Format",
1031
+ constructorArgs: [{ name: "method", type: "constant", value: "FormatMethods.Hidden" }]
1032
+ });
1033
+ }
1034
+ }
1035
+ }
1036
+ // Replace User Tables and FKs with AuditBase tables and
1037
+ export function replaceUserReferencesWithAuditTables(gen) {
1038
+ for (const type of gen.typesWithPrimaryKeys) {
1039
+ const removeProps = [];
1040
+ for (const prop of type.properties) {
1041
+ if (prop.name === 'UserId') {
1042
+ removeProps.push(prop.name);
1043
+ }
1044
+ if (prop.attributes?.some(a => a.name === 'Reference' && a.constructorArgs?.some(x => x.value === 'typeof(User)'))) {
1045
+ removeProps.push(prop.name);
1046
+ }
1047
+ if (prop.type === 'User') {
1048
+ removeProps.push(prop.name);
1049
+ }
1050
+ if (prop.genericArgs && prop.genericArgs.includes('User')) {
1051
+ removeProps.push(prop.name);
1052
+ }
1053
+ }
1054
+ if (removeProps.length) {
1055
+ type.properties = type.properties.filter(x => !removeProps.includes(x.name));
1056
+ type.inherits = { name: "AuditBase", namespace: "ServiceStack" };
1057
+ }
1058
+ }
1059
+ // Remove User Table
1060
+ gen.result.types = gen.result.types.filter(x => x.name !== 'User');
1018
1061
  }