@xrmforge/devkit 0.7.2 → 0.7.3
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/templates/AGENT.md
CHANGED
|
@@ -568,6 +568,29 @@ const customerId = formLookupId(form.customerid); // already clean: "a1b2c3d4-.
|
|
|
568
568
|
if (customerId === otherNormalizedId) { ... } // simple ===
|
|
569
569
|
```
|
|
570
570
|
|
|
571
|
+
### Typed repetition beats untyped loops
|
|
572
|
+
|
|
573
|
+
When multiple fields need the same operation (e.g. 8 address fields), write
|
|
574
|
+
8 typed lines instead of 1 loop with raw strings:
|
|
575
|
+
|
|
576
|
+
```typescript
|
|
577
|
+
// WRONG: DRY reflex, but raw strings bypass type safety
|
|
578
|
+
for (const f of ['address1_name', 'address1_line1', 'address1_city']) {
|
|
579
|
+
form.$unsafe(f)?.addOnChange(handler);
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
// CORRECT: more lines, but every field is compile-time validated
|
|
583
|
+
form.address1_name.addOnChange(handler);
|
|
584
|
+
form.address1_line1.addOnChange(handler);
|
|
585
|
+
form.address1_city.addOnChange(handler);
|
|
586
|
+
form.address1_postalcode.addOnChange(handler);
|
|
587
|
+
form.address1_country.addOnChange(handler);
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
8 typed lines are better than 1 loop with raw strings. The type system
|
|
591
|
+
catches renamed/removed fields at compile time. A loop with raw strings
|
|
592
|
+
only fails at runtime. DRY is a recommendation, type safety is mandatory.
|
|
593
|
+
|
|
571
594
|
**Rule of thumb:** If a helper function just wraps a single Xrm API call with a
|
|
572
595
|
string parameter, it MUST NOT exist. The typed API is shorter, safer, and provides
|
|
573
596
|
IDE autocomplete. Only keep shared helpers that contain actual domain logic
|
|
@@ -87,9 +87,14 @@ function collectTsFiles(dir) {
|
|
|
87
87
|
|
|
88
88
|
/**
|
|
89
89
|
* Check a pattern rule against all files.
|
|
90
|
+
* @param {string} label - Description of the check
|
|
91
|
+
* @param {string[]} files - Files to check
|
|
92
|
+
* @param {RegExp} regex - Pattern to match (violation)
|
|
93
|
+
* @param {string[]} excludeFiles - File paths to exclude
|
|
94
|
+
* @param {RegExp[]} excludePatterns - Line patterns to exclude (not violations even if regex matches)
|
|
90
95
|
* @returns Number of violations
|
|
91
96
|
*/
|
|
92
|
-
function checkPattern(label, files, regex, excludeFiles = []) {
|
|
97
|
+
function checkPattern(label, files, regex, excludeFiles = [], excludePatterns = []) {
|
|
93
98
|
const violations = [];
|
|
94
99
|
for (const file of files) {
|
|
95
100
|
const relPath = relative(process.cwd(), file);
|
|
@@ -100,6 +105,7 @@ function checkPattern(label, files, regex, excludeFiles = []) {
|
|
|
100
105
|
const line = lines[i];
|
|
101
106
|
const trimmed = line.trim();
|
|
102
107
|
if (trimmed.startsWith('//') || trimmed.startsWith('*') || trimmed.startsWith('/*')) continue;
|
|
108
|
+
if (excludePatterns.some((ep) => ep.test(trimmed))) continue;
|
|
103
109
|
if (regex.test(line)) {
|
|
104
110
|
violations.push(` ${relPath}:${i + 1}: ${trimmed}`);
|
|
105
111
|
}
|
|
@@ -214,11 +220,16 @@ checkPattern(
|
|
|
214
220
|
|
|
215
221
|
// ── Handler Pattern ──────────────────────────────────────────────────────────
|
|
216
222
|
|
|
217
|
-
// 3l. Exported handlers without wrapHandler
|
|
223
|
+
// 3l. Exported handlers without wrapHandler or wrapCommand
|
|
218
224
|
checkPattern(
|
|
219
|
-
'Exported handlers without wrapHandler',
|
|
225
|
+
'Exported handlers without wrapHandler/wrapCommand',
|
|
220
226
|
formFiles,
|
|
221
|
-
/^export\s+(const|async\s+function|function)\s+\w+(?!.*wrapHandler)/,
|
|
227
|
+
/^export\s+(const|async\s+function|function)\s+\w+(?!.*(?:wrapHandler|wrapCommand))/,
|
|
228
|
+
[],
|
|
229
|
+
[
|
|
230
|
+
// Re-exports: `export const form_OnLoad = onLoad;` (alias for a wrapped handler)
|
|
231
|
+
/^export\s+const\s+\w+\s*=\s*[a-zA-Z][a-zA-Z0-9]*\s*;/,
|
|
232
|
+
],
|
|
222
233
|
);
|
|
223
234
|
|
|
224
235
|
// ── Raw $select ──────────────────────────────────────────────────────────────
|