@xrmforge/devkit 0.7.0 → 0.7.1

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.
@@ -484,22 +484,60 @@ each attribute to its control. `mock.getControl(Fields.Name)` works out of the b
484
484
 
485
485
  ## Pattern Recognition: Legacy to XrmForge
486
486
 
487
+ ### Xrm API Patterns
487
488
  | Legacy Pattern | XrmForge Replacement |
488
489
  |---|---|
489
- | `getAttribute("name")` | `form.name` (via typedForm) or `getAttribute(Fields.Name)` |
490
+ | `getAttribute("name")` | `form.name` (via typedForm) |
490
491
  | `getControl("name")` | `form.$control(Fields.Name)` |
491
- | `getValue() === 595300000` | `form.statuscode.getValue() === StatusCode.Active` |
492
- | `Xrm.WebApi.retrieveRecord("account", id)` | `Xrm.WebApi.retrieveRecord(EntityNames.Account, id)` |
493
- | `"?$select=name,revenue"` | `select(AccountFields.Name, AccountFields.Revenue)` |
494
- | `value[0].id.replace("{","")` | `formLookupId(form.customerid)` |
495
492
  | `Xrm.Page.getAttribute(...)` | `form.fieldname` (via typedForm) |
496
493
  | `var formContext` (global) | `const form = typedForm<MyForm>(ctx.getFormContext())` |
497
494
  | `function form_OnLoad(ctx)` | `export const onLoad = wrapHandler(...)` |
495
+ | `Xrm.WebApi.retrieveRecord("account", id)` | `Xrm.WebApi.retrieveRecord(EntityNames.Account, id)` |
496
+ | `"?$select=name,revenue"` | `select(AccountFields.Name, AccountFields.Revenue)` |
497
+ | `value[0].id.replace("{","")` | `formLookupId(form.customerid)` |
498
498
  | `ExecuteFunctionCall("name", ...)` | `import { Name } from '../../generated/actions/global.js'` |
499
499
  | `setFormNotification(msg, 'ERROR', id)` | `setFormNotification(msg, FormNotificationLevel.Error, id)` |
500
+ | `getValue() === 595300000` | `form.statuscode.getValue() === StatusCode.Active` |
500
501
  | `86400000` | `const MS_PER_DAY = 24 * 60 * 60 * 1000` |
501
502
  | `'[Kurzbeschreibung]'` | `pickLang(languageId, MESSAGES).placeholder` |
502
503
 
504
+ ### Legacy Helper Functions (DO NOT recreate, use typedForm instead)
505
+
506
+ These helper wrappers are common in legacy code. They destroy type safety.
507
+ Never recreate them. Use the typed API directly.
508
+
509
+ | Legacy Helper | XrmForge Replacement |
510
+ |---|---|
511
+ | `GetValue(fieldName)` | `form.fieldname.getValue()` (typed via typedForm) |
512
+ | `SetValue(fieldName, value)` | `form.fieldname.setValue(value)` (typed via typedForm) |
513
+ | `SetDisabled(attributeName, disabled)` | `form.$control(Fields.X).setDisabled(disabled)` |
514
+ | `SetVisible(attributeName, visible)` | `form.$control(Fields.X).setVisible(visible)` |
515
+ | `SetRequiredLevel(attributeName, level)` | `form.$context.getAttribute(Fields.X).setRequiredLevel(RequiredLevel.Required)` |
516
+ | `AddOnChange(attributeName, callback)` | `form.$context.getAttribute(Fields.X).addOnChange(cb)` |
517
+ | `AddPreSearch(controlName, callback)` | `(form.$control(Fields.X) as Xrm.Controls.LookupControl).addPreSearch(cb)` |
518
+ | `GetLookupValueId(fieldName)` | `formLookupId(form.fieldname)` |
519
+ | `SetLookupValue(field, id, type, name)` | `form.fieldname.setValue([{ id, entityType, name }])` |
520
+ | `GetId()` | `form.$context.data.entity.getId()` |
521
+ | `GetEntityName()` | `form.$context.data.entity.getEntityName()` |
522
+ | `GetFormType()` | `form.$context.ui.getFormType()` |
523
+ | `GetIsDirty()` | `form.$context.data.entity.getIsDirty()` |
524
+ | `IsNullOrEmpty(value)` | `value == null \|\| value === ''` (inline) |
525
+ | `IsAttributeNullOrEmpty(field)` | `form.fieldname.getValue() == null` |
526
+ | `GetUserId()` | `Xrm.Utility.getGlobalContext().userSettings.userId` |
527
+ | `GetUserLanguageId()` | `Xrm.Utility.getGlobalContext().userSettings.languageId` |
528
+ | `OpenForm(entityName, id)` | `Xrm.Navigation.openForm({ entityName: EntityNames.X, entityId: id })` |
529
+ | `OpenAlertDialog(text)` | `Xrm.Navigation.openAlertDialog({ text })` |
530
+ | `OpenConfirmDialog(text, ...)` | `Xrm.Navigation.openConfirmDialog({ text, title, ... })` |
531
+ | `ShowProgressIndicator(msg)` | `Xrm.Utility.showProgressIndicator(msg)` |
532
+ | `CloseProgressIndicator()` | `Xrm.Utility.closeProgressIndicator()` |
533
+ | `SetNotification(attr, msg)` | `form.$context.getControl(Fields.X).setNotification(msg, NOTIFICATION_IDS.x)` |
534
+ | `SetSectionDisabled(tab, sec, off)` | `form.$context.ui.tabs.get(Tabs.X).sections.get(Sections.Y).setVisible(!off)` |
535
+
536
+ **Rule of thumb:** If a helper function just wraps a single Xrm API call with a
537
+ string parameter, it MUST NOT exist. The typed API is shorter, safer, and provides
538
+ IDE autocomplete. Only keep shared helpers that contain actual domain logic
539
+ (calculations, WebApi queries, multi-step workflows).
540
+
503
541
  ## @types/xrm Pitfalls (known issues)
504
542
 
505
543
  1. **Form Interface:** Do NOT use `interface extends Xrm.FormContext`. Use `Omit` pattern.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xrmforge/devkit",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "description": "Build orchestration and project tooling for Dynamics 365 WebResources",
5
5
  "keywords": [
6
6
  "dynamics-365",