@memberjunction/codegen-lib 3.3.0 → 4.0.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 (92) hide show
  1. package/README.md +56 -1
  2. package/dist/Angular/angular-codegen.d.ts +1 -1
  3. package/dist/Angular/angular-codegen.d.ts.map +1 -1
  4. package/dist/Angular/angular-codegen.js +80 -136
  5. package/dist/Angular/angular-codegen.js.map +1 -1
  6. package/dist/Angular/entity-data-grid-related-entity-component.d.ts +1 -1
  7. package/dist/Angular/entity-data-grid-related-entity-component.js +6 -9
  8. package/dist/Angular/entity-data-grid-related-entity-component.js.map +1 -1
  9. package/dist/Angular/join-grid-related-entity-component.d.ts +1 -1
  10. package/dist/Angular/join-grid-related-entity-component.js +8 -36
  11. package/dist/Angular/join-grid-related-entity-component.js.map +1 -1
  12. package/dist/Angular/related-entity-components.js +13 -79
  13. package/dist/Angular/related-entity-components.js.map +1 -1
  14. package/dist/Angular/timeline-related-entity-component.d.ts +1 -1
  15. package/dist/Angular/timeline-related-entity-component.js +14 -38
  16. package/dist/Angular/timeline-related-entity-component.js.map +1 -1
  17. package/dist/Angular/user-view-grid-related-entity-component.d.ts +43 -0
  18. package/dist/Angular/user-view-grid-related-entity-component.d.ts.map +1 -0
  19. package/dist/Angular/user-view-grid-related-entity-component.js +85 -0
  20. package/dist/Angular/user-view-grid-related-entity-component.js.map +1 -0
  21. package/dist/Config/config.d.ts +79 -0
  22. package/dist/Config/config.d.ts.map +1 -1
  23. package/dist/Config/config.js +174 -172
  24. package/dist/Config/config.js.map +1 -1
  25. package/dist/Config/db-connection.d.ts +1 -1
  26. package/dist/Config/db-connection.d.ts.map +1 -1
  27. package/dist/Config/db-connection.js +6 -33
  28. package/dist/Config/db-connection.js.map +1 -1
  29. package/dist/Database/dbSchema.js +28 -35
  30. package/dist/Database/dbSchema.js.map +1 -1
  31. package/dist/Database/manage-metadata.d.ts +25 -9
  32. package/dist/Database/manage-metadata.d.ts.map +1 -1
  33. package/dist/Database/manage-metadata.js +438 -316
  34. package/dist/Database/manage-metadata.js.map +1 -1
  35. package/dist/Database/reorder-columns.d.ts +1 -1
  36. package/dist/Database/reorder-columns.d.ts.map +1 -1
  37. package/dist/Database/reorder-columns.js +1 -5
  38. package/dist/Database/reorder-columns.js.map +1 -1
  39. package/dist/Database/sql.d.ts +1 -1
  40. package/dist/Database/sql.d.ts.map +1 -1
  41. package/dist/Database/sql.js +67 -98
  42. package/dist/Database/sql.js.map +1 -1
  43. package/dist/Database/sql_codegen.d.ts +5 -2
  44. package/dist/Database/sql_codegen.d.ts.map +1 -1
  45. package/dist/Database/sql_codegen.js +344 -268
  46. package/dist/Database/sql_codegen.js.map +1 -1
  47. package/dist/Manifest/GenerateClassRegistrationsManifest.d.ts +110 -0
  48. package/dist/Manifest/GenerateClassRegistrationsManifest.d.ts.map +1 -0
  49. package/dist/Manifest/GenerateClassRegistrationsManifest.js +632 -0
  50. package/dist/Manifest/GenerateClassRegistrationsManifest.js.map +1 -0
  51. package/dist/Misc/action_subclasses_codegen.d.ts.map +1 -1
  52. package/dist/Misc/action_subclasses_codegen.js +15 -26
  53. package/dist/Misc/action_subclasses_codegen.js.map +1 -1
  54. package/dist/Misc/advanced_generation.d.ts +1 -1
  55. package/dist/Misc/advanced_generation.js +34 -40
  56. package/dist/Misc/advanced_generation.js.map +1 -1
  57. package/dist/Misc/createNewUser.d.ts +1 -1
  58. package/dist/Misc/createNewUser.js +22 -26
  59. package/dist/Misc/createNewUser.js.map +1 -1
  60. package/dist/Misc/entity_subclasses_codegen.d.ts +2 -2
  61. package/dist/Misc/entity_subclasses_codegen.d.ts.map +1 -1
  62. package/dist/Misc/entity_subclasses_codegen.js +33 -40
  63. package/dist/Misc/entity_subclasses_codegen.js.map +1 -1
  64. package/dist/Misc/graphql_server_codegen.js +36 -41
  65. package/dist/Misc/graphql_server_codegen.js.map +1 -1
  66. package/dist/Misc/runCommand.d.ts +1 -1
  67. package/dist/Misc/runCommand.js +13 -20
  68. package/dist/Misc/runCommand.js.map +1 -1
  69. package/dist/Misc/sql_logging.d.ts +7 -1
  70. package/dist/Misc/sql_logging.d.ts.map +1 -1
  71. package/dist/Misc/sql_logging.js +40 -53
  72. package/dist/Misc/sql_logging.js.map +1 -1
  73. package/dist/Misc/status_logging.js +45 -60
  74. package/dist/Misc/status_logging.js.map +1 -1
  75. package/dist/Misc/system_integrity.d.ts +1 -1
  76. package/dist/Misc/system_integrity.d.ts.map +1 -1
  77. package/dist/Misc/system_integrity.js +12 -16
  78. package/dist/Misc/system_integrity.js.map +1 -1
  79. package/dist/Misc/temp_batch_file.js +15 -22
  80. package/dist/Misc/temp_batch_file.js.map +1 -1
  81. package/dist/Misc/util.d.ts.map +1 -1
  82. package/dist/Misc/util.js +17 -28
  83. package/dist/Misc/util.js.map +1 -1
  84. package/dist/index.d.ts +21 -20
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/index.js +22 -40
  87. package/dist/index.js.map +1 -1
  88. package/dist/runCodeGen.d.ts +1 -0
  89. package/dist/runCodeGen.d.ts.map +1 -1
  90. package/dist/runCodeGen.js +151 -178
  91. package/dist/runCodeGen.js.map +1 -1
  92. package/package.json +24 -21
package/README.md CHANGED
@@ -542,6 +542,61 @@ type Customer {
542
542
 
543
543
  **Total: 500+ lines of production code from 6 lines of SQL.**
544
544
 
545
+ ### Class Registrations Manifest Generation
546
+
547
+ Generates an import manifest that prevents tree-shaking of `@RegisterClass` decorated classes. The tool walks an app's transitive dependency tree and produces a tailored manifest for each application.
548
+
549
+ **Why this matters:** Decorators like `@RegisterClass` only execute if their file is imported. Bundlers can tree-shake entire files that appear unused, silently breaking MemberJunction's class factory system. The manifest ensures all registered classes are imported.
550
+
551
+ **How it works:**
552
+ 1. Reads the app's `package.json` and walks the full transitive dependency tree
553
+ 2. Scans each dependency's `src/**/*.ts` for `@RegisterClass` decorators using the TypeScript Compiler API
554
+ 3. Generates a manifest file with `import` statements for every package that contains registered classes
555
+
556
+ **Per-app results (verified):**
557
+
558
+ | App | Deps Walked | Packages with @RegisterClass | Total Classes |
559
+ |-----|-------------|------------------------------|---------------|
560
+ | MJAPI | 985 | 54 | 715 |
561
+ | MJExplorer | 1179 | 17 | 721 |
562
+
563
+ **Programmatic usage:**
564
+ ```typescript
565
+ import { generateClassRegistrationsManifest } from '@memberjunction/codegen-lib';
566
+
567
+ const result = await generateClassRegistrationsManifest({
568
+ outputPath: './src/generated/class-registrations-manifest.ts',
569
+ appDir: './packages/MJAPI', // defaults to process.cwd()
570
+ filterBaseClasses: ['BaseEngine'], // optional filter
571
+ });
572
+
573
+ if (result.success) {
574
+ console.log(`${result.packages.length} packages, ${result.classes.length} classes`);
575
+ }
576
+ ```
577
+
578
+ **CLI usage (via MJCLI):**
579
+ ```bash
580
+ mj codegen manifest --output ./src/generated/class-registrations-manifest.ts
581
+ ```
582
+
583
+ See the [MJCLI README](../MJCLI/README.md) for full CLI documentation.
584
+
585
+ **Pre-built manifests for npm distribution:**
586
+
587
+ When MJ packages are installed via npm, consumers only receive `dist/` (no `src/`), so the manifest generator can't scan them. To solve this, MJ ships **pre-built manifests** inside the bootstrap packages:
588
+
589
+ - `@memberjunction/server-bootstrap` — 623 server-side classes from 54 packages
590
+ - `@memberjunction/ng-bootstrap` — 383 Angular classes from 14 packages
591
+
592
+ External consumers import the pre-built manifest for MJ classes, then generate a supplemental manifest for their own classes using `--exclude-packages @memberjunction`.
593
+
594
+ For complete setup instructions, CLI reference, and troubleshooting, see the **[Class Manifest Guide](CLASS_MANIFEST_GUIDE.md)**.
595
+
596
+ **Example output:**
597
+ - [MJAPI manifest (server-side)](EXAMPLE_MANIFEST_MJAPI.md) — 54 packages, 715 classes (AI providers, actions, encryption, scheduling, storage, etc.)
598
+ - [MJExplorer manifest (client-side)](EXAMPLE_MANIFEST_MJEXPLORER.md) — 17 packages, 721 classes (Angular components, dashboards, forms, etc.)
599
+
545
600
  ## API Reference
546
601
 
547
602
  ### Core Functions
@@ -552,7 +607,7 @@ await runCodeGen();
552
607
 
553
608
  // Generate specific components
554
609
  await generateEntitySubClasses(options);
555
- await generateAngularEntityCode(options);
610
+ await generateAngularEntityCode(options);
556
611
  await generateSQLScripts(options);
557
612
  await generateGraphQLServerCode(options);
558
613
  ```
@@ -1,5 +1,5 @@
1
1
  import { EntityInfo, EntityFieldInfo, GeneratedFormSectionType, UserInfo, EntityRelationshipInfo } from '@memberjunction/core';
2
- import { GenerationResult } from './related-entity-components';
2
+ import { GenerationResult } from './related-entity-components.js';
3
3
  /**
4
4
  * Represents metadata about an Angular form section that is generated for an entity
5
5
  */
@@ -1 +1 @@
1
- {"version":3,"file":"angular-codegen.d.ts","sourceRoot":"","sources":["../../src/Angular/angular-codegen.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"angular-codegen.d.ts","sourceRoot":"","sources":["../../src/Angular/angular-codegen.ts"],"names":[],"mappings":"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"}
@@ -1,84 +1,38 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.AngularClientGeneratorBase = exports.AngularFormSectionInfo = void 0;
7
- const core_1 = require("@memberjunction/core");
8
- const status_logging_1 = require("../Misc/status_logging");
9
- const fs_1 = __importDefault(require("fs"));
10
- const path_1 = __importDefault(require("path"));
11
- const config_1 = require("../Config/config");
12
- const related_entity_components_1 = require("./related-entity-components");
13
- const util_1 = require("../Misc/util");
1
+ import { GeneratedFormSectionType, EntityFieldTSType, EntityFieldValueListType, Metadata } from '@memberjunction/core';
2
+ import { logError, logStatus } from '../Misc/status_logging.js';
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import { mjCoreSchema, outputOptionValue, configInfo } from '../Config/config.js';
6
+ import { RelatedEntityDisplayComponentGeneratorBase } from './related-entity-components.js';
7
+ import { sortBySequenceAndCreatedAt } from '../Misc/util.js';
14
8
  /**
15
9
  * Represents metadata about an Angular form section that is generated for an entity
16
10
  */
17
- class AngularFormSectionInfo {
18
- /**
19
- * The type of form section (e.g., Top, Category, Details)
20
- */
21
- Type;
22
- /**
23
- * The display name of the section
24
- */
25
- Name;
26
- /**
27
- * The generated HTML code for the section (panel or tab)
28
- */
29
- TabCode;
30
- /**
31
- * The TypeScript class name for the section component
32
- */
33
- ClassName;
34
- /**
35
- * The filename where the section component will be saved
36
- */
37
- FileName;
38
- /**
39
- * The complete TypeScript component code for the section
40
- */
41
- ComponentCode;
42
- /**
43
- * Array of entity fields that belong to this section
44
- */
45
- Fields;
46
- /**
47
- * The filename without the .ts extension
48
- */
49
- FileNameWithoutExtension;
50
- /**
51
- * The class name of the entity this section belongs to
52
- */
53
- EntityClassName;
54
- /**
55
- * Indicates if this section represents a related entity tab
56
- */
57
- IsRelatedEntity = false;
58
- /**
59
- * Specifies where related entity tabs should be displayed relative to field tabs
60
- */
61
- RelatedEntityDisplayLocation = 'After Field Tabs';
62
- /**
63
- * The generation result for related entity components
64
- */
65
- GeneratedOutput;
66
- /**
67
- * The minimum sequence number from fields in this section (used for sorting)
68
- */
69
- MinSequence;
70
- /**
71
- * The unique camelCase key used for this section in the sectionsExpanded object
72
- */
73
- UniqueKey;
11
+ export class AngularFormSectionInfo {
12
+ constructor() {
13
+ /**
14
+ * Indicates if this section represents a related entity tab
15
+ */
16
+ this.IsRelatedEntity = false;
17
+ /**
18
+ * Specifies where related entity tabs should be displayed relative to field tabs
19
+ */
20
+ this.RelatedEntityDisplayLocation = 'After Field Tabs';
21
+ }
74
22
  }
75
- exports.AngularFormSectionInfo = AngularFormSectionInfo;
76
23
  /**
77
24
  * Base class for generating Angular client code for MemberJunction entities.
78
25
  * This class handles the generation of Angular components, forms, and modules based on entity metadata.
79
26
  * You can sub-class this class to create your own Angular client code generator logic.
80
27
  */
81
- class AngularClientGeneratorBase {
28
+ export class AngularClientGeneratorBase {
29
+ constructor() {
30
+ /**
31
+ * Base name used for generating sub-module names
32
+ * @protected
33
+ */
34
+ this.subModule_BaseName = 'GeneratedForms_SubModule_';
35
+ }
82
36
  /**
83
37
  * Main entry point for generating Angular code for a collection of entities
84
38
  * @param entities Array of EntityInfo objects to generate Angular code for
@@ -89,24 +43,24 @@ class AngularClientGeneratorBase {
89
43
  */
90
44
  async generateAngularCode(entities, directory, modulePrefix, contextUser) {
91
45
  try {
92
- const entityPath = path_1.default.join(directory, 'Entities');
46
+ const entityPath = path.join(directory, 'Entities');
93
47
  //const classMapEntries: string[] = [];
94
48
  const componentImports = [];
95
49
  const relatedEntityModuleImports = [];
96
50
  const componentNames = [];
97
51
  const sections = [];
98
- if (!fs_1.default.existsSync(entityPath))
99
- fs_1.default.mkdirSync(entityPath, { recursive: true }); // create the directory if it doesn't exist
52
+ if (!fs.existsSync(entityPath))
53
+ fs.mkdirSync(entityPath, { recursive: true }); // create the directory if it doesn't exist
100
54
  for (let i = 0; i < entities.length; ++i) {
101
55
  const entity = entities[i];
102
56
  if (entity.PrimaryKeys && entity.PrimaryKeys.length > 0 && entity.IncludeInAPI) {
103
- const thisEntityPath = path_1.default.join(entityPath, entity.ClassName);
104
- if (!fs_1.default.existsSync(thisEntityPath))
105
- fs_1.default.mkdirSync(thisEntityPath, { recursive: true }); // create the directory if it doesn't exist
57
+ const thisEntityPath = path.join(entityPath, entity.ClassName);
58
+ if (!fs.existsSync(thisEntityPath))
59
+ fs.mkdirSync(thisEntityPath, { recursive: true }); // create the directory if it doesn't exist
106
60
  const { htmlCode, additionalSections, relatedEntitySections } = await this.generateSingleEntityHTMLForAngular(entity, contextUser);
107
61
  const tsCode = this.generateSingleEntityTypeScriptForAngular(entity, additionalSections, relatedEntitySections);
108
- fs_1.default.writeFileSync(path_1.default.join(thisEntityPath, `${entity.ClassName.toLowerCase()}.form.component.ts`), tsCode);
109
- fs_1.default.writeFileSync(path_1.default.join(thisEntityPath, `${entity.ClassName.toLowerCase()}.form.component.html`), htmlCode);
62
+ fs.writeFileSync(path.join(thisEntityPath, `${entity.ClassName.toLowerCase()}.form.component.ts`), tsCode);
63
+ fs.writeFileSync(path.join(thisEntityPath, `${entity.ClassName.toLowerCase()}.form.component.html`), htmlCode);
110
64
  // Sections are now inline in HTML templates, no separate files needed
111
65
  // Just track them for module generation purposes
112
66
  if (additionalSections.length > 0) {
@@ -115,7 +69,7 @@ class AngularClientGeneratorBase {
115
69
  });
116
70
  }
117
71
  const componentName = `${entity.ClassName}FormComponent`;
118
- componentImports.push(`import { ${componentName}, Load${componentName} } from "./Entities/${entity.ClassName}/${entity.ClassName.toLowerCase()}.form.component";`);
72
+ componentImports.push(`import { ${componentName} } from "./Entities/${entity.ClassName}/${entity.ClassName.toLowerCase()}.form.component";`);
119
73
  const currentComponentDistinctRelatedEntityClassNames = [];
120
74
  relatedEntitySections.forEach(s => s.GeneratedOutput.Component.ImportItems.forEach(i => {
121
75
  if (!currentComponentDistinctRelatedEntityClassNames.find(ii => ii.itemClassName === i.ClassName))
@@ -140,16 +94,16 @@ class AngularClientGeneratorBase {
140
94
  // now the imports are good
141
95
  }
142
96
  else {
143
- (0, status_logging_1.logStatus)(` Entity ${entity.Name} does not have a primary key or is not included in the API, skipping code generation for this entity`);
97
+ logStatus(` Entity ${entity.Name} does not have a primary key or is not included in the API, skipping code generation for this entity`);
144
98
  }
145
99
  }
146
- const maxComponentsPerModule = (0, config_1.outputOptionValue)('Angular', 'maxComponentsPerModule', 25);
100
+ const maxComponentsPerModule = outputOptionValue('Angular', 'maxComponentsPerModule', 25);
147
101
  const moduleCode = this.generateAngularModule(componentImports, componentNames, relatedEntityModuleImports, sections, modulePrefix, maxComponentsPerModule);
148
- fs_1.default.writeFileSync(path_1.default.join(directory, 'generated-forms.module.ts'), moduleCode);
102
+ fs.writeFileSync(path.join(directory, 'generated-forms.module.ts'), moduleCode);
149
103
  return true;
150
104
  }
151
105
  catch (err) {
152
- (0, status_logging_1.logError)(err);
106
+ logError(err);
153
107
  return false;
154
108
  }
155
109
  }
@@ -205,14 +159,9 @@ ${relatedEntityModuleImports.filter(remi => remi.library.trim().toLowerCase() !=
205
159
  .join('\n')}
206
160
  ${moduleCode}
207
161
 
208
- export function Load${modulePrefix}GeneratedForms() {
209
- // This function doesn't do much, but it calls each generated form's loader function
210
- // which in turn calls the sections for that generated form. Ultimately, those bits of
211
- // code do NOTHING - the point is to prevent the code from being eliminated during tree shaking
212
- // since it is dynamically instantiated on demand, and the Angular compiler has no way to know that,
213
- // in production builds tree shaking will eliminate the code unless we do this
214
- ${componentNames.map(c => `Load${c.componentName}();`).join('\n ')}
215
- }
162
+ // Note: LoadXXXGeneratedForms() functions have been removed. Tree-shaking prevention
163
+ // is now handled by the pre-built class registration manifest system.
164
+ // See packages/CodeGenLib/CLASS_MANIFEST_GUIDE.md for details.
216
165
  `;
217
166
  }
218
167
  /**
@@ -274,11 +223,6 @@ export class ${modulePrefix}GeneratedFormsModule { }`;
274
223
  // so we need to combine the two into a single return value and send back to the caller
275
224
  return subModules.join('\n\n') + '\n\n' + masterModuleCode;
276
225
  }
277
- /**
278
- * Base name used for generating sub-module names
279
- * @protected
280
- */
281
- subModule_BaseName = 'GeneratedForms_SubModule_';
282
226
  /**
283
227
  * Get the base name for the sub-modules. Override this method to change the base name.
284
228
  * @returns The base name for sub-modules (default: 'GeneratedForms_SubModule_')
@@ -355,7 +299,7 @@ export class ${this.SubModuleBaseName}${moduleNumber} { }
355
299
  relatedEntitySections.filter(s => s.GeneratedOutput && s.GeneratedOutput.CodeOutput.length > 0)
356
300
  .map(s => s.GeneratedOutput.CodeOutput.split("\n").map(l => ` ${l}`).join("\n")).join('\n') : '';
357
301
  // Generate unique keys for all sections FIRST, then use them everywhere
358
- const sectionsWithoutTop = additionalSections.filter(s => s.Type !== core_1.GeneratedFormSectionType.Top && s.Name);
302
+ const sectionsWithoutTop = additionalSections.filter(s => s.Type !== GeneratedFormSectionType.Top && s.Name);
359
303
  const allSections = [...sectionsWithoutTop, ...relatedEntitySections];
360
304
  // Assign unique keys to each section
361
305
  const usedKeys = new Set();
@@ -390,13 +334,15 @@ export class ${this.SubModuleBaseName}${moduleNumber} { }
390
334
  const sectionInitCode = sectionInitEntries.length > 0
391
335
  ? `\n\n override async ngOnInit() {\n await super.ngOnInit();\n this.initSections([\n${sectionInitEntries.join(',\n')}\n ]);\n }`
392
336
  : '';
337
+ const entityPackageName = configInfo.entityPackageName || 'mj_generatedentities';
393
338
  return `import { Component } from '@angular/core';
394
- import { ${entityObjectClass}Entity } from '${entity.SchemaName === config_1.mjCoreSchema ? '@memberjunction/core-entities' : 'mj_generatedentities'}';
339
+ import { ${entityObjectClass}Entity } from '${entity.SchemaName === mjCoreSchema ? '@memberjunction/core-entities' : entityPackageName}';
395
340
  import { RegisterClass } from '@memberjunction/global';
396
341
  import { BaseFormComponent } from '@memberjunction/ng-base-forms';
397
342
  ${generationImports.length > 0 ? generationImports + '\n' : ''}
398
343
  @RegisterClass(BaseFormComponent, '${entity.Name}') // Tell MemberJunction about this class
399
344
  @Component({
345
+ standalone: false,
400
346
  selector: 'gen-${entity.ClassName.toLowerCase()}-form',
401
347
  templateUrl: './${entity.ClassName.toLowerCase()}.form.component.html'
402
348
  })
@@ -404,9 +350,6 @@ export class ${entity.ClassName}FormComponent extends BaseFormComponent {
404
350
  public record!: ${entityObjectClass}Entity;${generationInjectedCode.length > 0 ? '\n' + generationInjectedCode : ''}${sectionInitCode}
405
351
  }
406
352
 
407
- export function Load${entity.ClassName}FormComponent() {
408
- // does nothing, but called to prevent tree-shaking from eliminating this component from the build
409
- }
410
353
  `;
411
354
  }
412
355
  /**
@@ -415,7 +358,7 @@ export function Load${entity.ClassName}FormComponent() {
415
358
  * @returns True if the entity has top area fields, false otherwise
416
359
  */
417
360
  entityHasTopArea(entity) {
418
- return entity.Fields.some(f => f.GeneratedFormSectionType === core_1.GeneratedFormSectionType.Top);
361
+ return entity.Fields.some(f => f.GeneratedFormSectionType === GeneratedFormSectionType.Top);
419
362
  }
420
363
  /**
421
364
  * Generates HTML for the top area section of an entity form
@@ -468,23 +411,23 @@ export function Load${entity.ClassName}FormComponent() {
468
411
  generateAngularAdditionalSections(entity, startIndex, categoryIcons) {
469
412
  const sections = [];
470
413
  let index = startIndex;
471
- const sortedFields = (0, util_1.sortBySequenceAndCreatedAt)(entity.Fields);
414
+ const sortedFields = sortBySequenceAndCreatedAt(entity.Fields);
472
415
  for (const field of sortedFields) {
473
416
  if (field.IncludeInGeneratedForm) {
474
- if (field.GeneratedFormSectionType === core_1.GeneratedFormSectionType.Category && field.Category && field.Category !== '' && field.IncludeInGeneratedForm)
475
- this.AddSectionIfNeeded(entity, sections, core_1.GeneratedFormSectionType.Category, field.Category, field.Sequence);
476
- else if (field.GeneratedFormSectionType === core_1.GeneratedFormSectionType.Details)
477
- this.AddSectionIfNeeded(entity, sections, core_1.GeneratedFormSectionType.Details, "Details", field.Sequence);
478
- else if (field.GeneratedFormSectionType === core_1.GeneratedFormSectionType.Top)
479
- this.AddSectionIfNeeded(entity, sections, core_1.GeneratedFormSectionType.Top, "Top", field.Sequence);
417
+ if (field.GeneratedFormSectionType === GeneratedFormSectionType.Category && field.Category && field.Category !== '' && field.IncludeInGeneratedForm)
418
+ this.AddSectionIfNeeded(entity, sections, GeneratedFormSectionType.Category, field.Category, field.Sequence);
419
+ else if (field.GeneratedFormSectionType === GeneratedFormSectionType.Details)
420
+ this.AddSectionIfNeeded(entity, sections, GeneratedFormSectionType.Details, "Details", field.Sequence);
421
+ else if (field.GeneratedFormSectionType === GeneratedFormSectionType.Top)
422
+ this.AddSectionIfNeeded(entity, sections, GeneratedFormSectionType.Top, "Top", field.Sequence);
480
423
  }
481
424
  }
482
425
  // Sort sections by minimum sequence (Top sections first, System sections last, then by MinSequence)
483
426
  sections.sort((a, b) => {
484
427
  // Top sections always first
485
- if (a.Type === core_1.GeneratedFormSectionType.Top)
428
+ if (a.Type === GeneratedFormSectionType.Top)
486
429
  return -1;
487
- if (b.Type === core_1.GeneratedFormSectionType.Top)
430
+ if (b.Type === GeneratedFormSectionType.Top)
488
431
  return 1;
489
432
  // System sections always last (after related entities)
490
433
  const aIsSystem = a.Name.toLowerCase() === 'system' || a.Name.toLowerCase() === 'system metadata';
@@ -502,14 +445,14 @@ export function Load${entity.ClassName}FormComponent() {
502
445
  let sectionIndex = 0;
503
446
  for (const section of sections) {
504
447
  let sectionName = '';
505
- if (section.Type === core_1.GeneratedFormSectionType.Top) {
448
+ if (section.Type === GeneratedFormSectionType.Top) {
506
449
  section.TabCode = this.generateTopAreaHTMLForAngular(entity);
507
450
  sectionName = 'top-area';
508
451
  }
509
452
  else {
510
- if (section.Type === core_1.GeneratedFormSectionType.Category)
453
+ if (section.Type === GeneratedFormSectionType.Category)
511
454
  sectionName = this.stripWhiteSpace(section.Name.toLowerCase());
512
- else if (section.Type === core_1.GeneratedFormSectionType.Details)
455
+ else if (section.Type === GeneratedFormSectionType.Details)
513
456
  sectionName = 'details';
514
457
  // Generate collapsible panel HTML inline instead of using separate components
515
458
  const formHTML = this.generateSectionHTMLForAngular(entity, section);
@@ -539,7 +482,7 @@ ${indentedFormHTML}
539
482
  </mj-collapsible-panel>`;
540
483
  sectionIndex++;
541
484
  }
542
- if (section.Type !== core_1.GeneratedFormSectionType.Top)
485
+ if (section.Type !== GeneratedFormSectionType.Top)
543
486
  index++; // don't increment the tab index for TOP AREA, becuse it won't be rendered as a tab
544
487
  }
545
488
  return sections;
@@ -554,19 +497,19 @@ ${indentedFormHTML}
554
497
  let html = '';
555
498
  // figure out which fields will be in this section first
556
499
  section.Fields = [];
557
- const sortedFields = (0, util_1.sortBySequenceAndCreatedAt)(entity.Fields);
500
+ const sortedFields = sortBySequenceAndCreatedAt(entity.Fields);
558
501
  for (const field of sortedFields) {
559
502
  if (field.IncludeInGeneratedForm) {
560
503
  let bMatch = false;
561
- if (field.GeneratedFormSectionType === core_1.GeneratedFormSectionType.Top && section.Type === core_1.GeneratedFormSectionType.Top) {
504
+ if (field.GeneratedFormSectionType === GeneratedFormSectionType.Top && section.Type === GeneratedFormSectionType.Top) {
562
505
  // match, include the field in the output
563
506
  bMatch = true;
564
507
  }
565
- else if (field.GeneratedFormSectionType === core_1.GeneratedFormSectionType.Category && field.Category && section.Name && field.Category.trim().toLowerCase() === section.Name.trim().toLowerCase()) {
508
+ else if (field.GeneratedFormSectionType === GeneratedFormSectionType.Category && field.Category && section.Name && field.Category.trim().toLowerCase() === section.Name.trim().toLowerCase()) {
566
509
  // match, include the field in the output
567
510
  bMatch = true;
568
511
  }
569
- else if (field.GeneratedFormSectionType === core_1.GeneratedFormSectionType.Details && section.Type === core_1.GeneratedFormSectionType.Details) {
512
+ else if (field.GeneratedFormSectionType === GeneratedFormSectionType.Details && section.Type === GeneratedFormSectionType.Details) {
570
513
  // match, include the field in the output
571
514
  bMatch = true;
572
515
  }
@@ -581,26 +524,26 @@ ${indentedFormHTML}
581
524
  if (!field.ReadOnly) {
582
525
  // first, check to see if we have a ValueListType != None, if so, generate a dropdown.
583
526
  // If value list type is ListOrUserEntry, then generate a combobox, if ValueListType = List, then generate a dropdown
584
- if (field.ValueListTypeEnum !== core_1.EntityFieldValueListType.None) {
527
+ if (field.ValueListTypeEnum !== EntityFieldValueListType.None) {
585
528
  // build the possible values list
586
- if (field.ValueListTypeEnum === core_1.EntityFieldValueListType.ListOrUserEntry) {
529
+ if (field.ValueListTypeEnum === EntityFieldValueListType.ListOrUserEntry) {
587
530
  // combo box
588
531
  editControl = `combobox`;
589
532
  }
590
- else if (field.ValueListTypeEnum === core_1.EntityFieldValueListType.List) {
533
+ else if (field.ValueListTypeEnum === EntityFieldValueListType.List) {
591
534
  // dropdown
592
535
  editControl = `dropdownlist`;
593
536
  }
594
537
  }
595
538
  else {
596
539
  // no value list, generate a text box, checkbox, or date picker
597
- if (field.TSType === core_1.EntityFieldTSType.Boolean)
540
+ if (field.TSType === EntityFieldTSType.Boolean)
598
541
  editControl = `checkbox`;
599
- else if (field.TSType === core_1.EntityFieldTSType.Date)
542
+ else if (field.TSType === EntityFieldTSType.Date)
600
543
  editControl = `datepicker`;
601
- else if (field.TSType === core_1.EntityFieldTSType.Number)
544
+ else if (field.TSType === EntityFieldTSType.Number)
602
545
  editControl = `numerictextbox`;
603
- else if (field.TSType === core_1.EntityFieldTSType.String) {
546
+ else if (field.TSType === EntityFieldTSType.String) {
604
547
  if (field.Length < 0 || field.MaxLength > 100) // length < 0 means nvarchar(max) or similar, so use textarea
605
548
  editControl = `textarea`;
606
549
  else
@@ -663,7 +606,7 @@ ${indentedFormHTML}
663
606
  // if the fkeyField has wrapping [] then remove them
664
607
  fkeyField = fkeyField.trim().replace('[', '').replace(']', '');
665
608
  // let's get the actual entityInfo for the related entity so we can get the field and see if it has a display name
666
- const md = new core_1.Metadata();
609
+ const md = new Metadata();
667
610
  const re = md.EntityByID(relatedEntity.RelatedEntityID);
668
611
  const f = re.Fields.find(f => f.Name.trim().toLowerCase() === fkeyField.trim().toLowerCase());
669
612
  if (f)
@@ -681,7 +624,7 @@ ${indentedFormHTML}
681
624
  * @returns Promise resolving to array of related entity tab sections
682
625
  */
683
626
  async generateRelatedEntityTabs(entity, startIndex, contextUser) {
684
- const md = new core_1.Metadata();
627
+ const md = new Metadata();
685
628
  const tabs = [];
686
629
  // Sort related entities by Sequence (user's explicit ordering), then by RelatedEntity name (stable tiebreaker)
687
630
  const sortedRelatedEntities = entity.RelatedEntities
@@ -716,7 +659,7 @@ ${indentedFormHTML}
716
659
  }
717
660
  // Calculate section key before generation (may be replaced later if duplicate)
718
661
  const sectionKey = this.camelCase(tabName);
719
- const component = await related_entity_components_1.RelatedEntityDisplayComponentGeneratorBase.GetComponent(relatedEntity, contextUser);
662
+ const component = await RelatedEntityDisplayComponentGeneratorBase.GetComponent(relatedEntity, contextUser);
720
663
  const generateResults = await component.Generate({
721
664
  Entity: entity,
722
665
  RelationshipInfo: relatedEntity,
@@ -739,12 +682,14 @@ ${indentedFormHTML}
739
682
  [formContext]="formContext"
740
683
  [badgeCount]="GetSectionRowCount('${sectionKey}')"
741
684
  [defaultExpanded]="false">
742
- <div *ngIf="record.IsSaved">
685
+ @if (record.IsSaved) {
686
+ <div>
743
687
  ${componentCodeWithIndent}
744
688
  </div>
689
+ }
745
690
  </mj-collapsible-panel>`;
746
691
  tabs.push({
747
- Type: core_1.GeneratedFormSectionType.Category,
692
+ Type: GeneratedFormSectionType.Category,
748
693
  IsRelatedEntity: true,
749
694
  RelatedEntityDisplayLocation: relatedEntity.DisplayLocation,
750
695
  Name: tabName,
@@ -959,7 +904,7 @@ ${this.innerCollapsiblePanelsHTML(additionalSections, relatedEntitySections)}
959
904
  */
960
905
  innerCollapsiblePanelsHTML(additionalSections, relatedEntitySections) {
961
906
  // Filter out Top sections as they're handled separately
962
- const sectionsToRender = additionalSections.filter(s => s.Type !== core_1.GeneratedFormSectionType.Top);
907
+ const sectionsToRender = additionalSections.filter(s => s.Type !== GeneratedFormSectionType.Top);
963
908
  // Order: before-panels, field-panels, after-panels
964
909
  // The RecordFormContainer handles the related-entity-grid wrapper via named slots
965
910
  const beforePanels = relatedEntitySections.filter(s => s.RelatedEntityDisplayLocation === 'Before Field Tabs');
@@ -1002,7 +947,7 @@ ${this.innerCollapsiblePanelsHTML(additionalSections, relatedEntitySections)}
1002
947
  const relatedEntityAfterFieldTabs = relatedEntitySections.filter(s => s.RelatedEntityDisplayLocation === 'After Field Tabs');
1003
948
  return ` <mj-tabstrip (TabSelected)="onTabSelect($event)" (ResizeContainer)="InvokeManualResize()">
1004
949
  ${relatedEntityBeforeFieldTabs ? relatedEntityBeforeFieldTabs.map(s => s.TabCode).join('\n') : ''}
1005
- ${additionalSections ? additionalSections.filter(s => s.Type !== core_1.GeneratedFormSectionType.Top).map(s => s.TabCode).join('\n ') : ''}
950
+ ${additionalSections ? additionalSections.filter(s => s.Type !== GeneratedFormSectionType.Top).map(s => s.TabCode).join('\n ') : ''}
1006
951
  ${relatedEntityAfterFieldTabs ? relatedEntityAfterFieldTabs.map(s => s.TabCode).join('\n') : ''}
1007
952
  </mj-tabstrip>`;
1008
953
  }
@@ -1022,5 +967,4 @@ ${this.innerCollapsiblePanelsHTML(additionalSections, relatedEntitySections)}
1022
967
  return htmlCode;
1023
968
  }
1024
969
  }
1025
- exports.AngularClientGeneratorBase = AngularClientGeneratorBase;
1026
970
  //# sourceMappingURL=angular-codegen.js.map