@mohsinonxrm/pptb-fetchxml-studio 1.3.1 → 1.4.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.
- package/CHANGELOG.md +441 -0
- package/README.md +73 -7
- package/SECURITY.md +13 -0
- package/dist/assets/{index-pm_Z7bpf.js → index-BoFrKby3.js} +42 -42
- package/dist/index.html +1 -1
- package/icons/icon-insider.svg +16 -0
- package/icons/icon.svg +12 -0
- package/npm-shrinkwrap.json +8 -8
- package/package.json +13 -5
- package/pptb.config.json +46 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to FetchXML Studio will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [1.4.0] - 2026-07-01
|
|
11
|
+
|
|
12
|
+
### ✨ Added
|
|
13
|
+
|
|
14
|
+
#### Tool-to-Tool (T2T) invocation
|
|
15
|
+
|
|
16
|
+
FetchXML Studio now participates in PPTB Tool-to-Tool (T2T) invocation in both directions. This feature was iterated through the `1.2.2-beta.*` and `1.2.3-beta.*` prereleases (detailed below); `1.4.0` is its first stable release. All T2T behavior is capability-gated and feature-detected, so standalone use and hosts without invocation/discovery support are unaffected. `features.minAPI` stays `1.2.2`.
|
|
17
|
+
|
|
18
|
+
- **Send to Tool (caller)** — Send the current FetchXML (plus root entity) to another PPTB tool. Targets are discovered automatically via the capability registry (`invocation.findToolsByCapability("fetchxml")`); the "Send to Tool" dropdown lists installed tools that declare the `fetchxml` capability, excluding FetchXML Studio itself (matched on the runtime tool id from `getToolContext()`). One-way, fire-and-forget handoff via `launchTool(..., { noReturn: true })`.
|
|
19
|
+
- **Callee (inbound prefill + return)** — When launched by another tool, FetchXML Studio consumes the inbound launch context to pre-populate the builder (resolution priority `fetchXml` → `viewRef` → `entityLogicalName`; the root entity is always derived from the FetchXML). A "Return FetchXML" button (shown only when launched as a callee) returns `{ fetchXml }` to the caller via `returnData()`.
|
|
20
|
+
- **Contract** — `pptb.config.json` declares `capabilities: ["fetchxml"]`, a `prefill` schema, and a `returnTopic`.
|
|
21
|
+
|
|
22
|
+
### 🏗️ Technical
|
|
23
|
+
|
|
24
|
+
- Depends on `@pptb/types` `1.2.3` (stable). New modules: `src/features/fetchxml/api/invocation.ts`, `src/shared/hooks/useLaunchContext.ts`, `src/shared/hooks/useSendToTools.ts`, `src/features/fetchxml/ui/Toolbar/SendToToolButton.tsx`. See the `1.2.x-beta.*` entries below for the full iteration history.
|
|
25
|
+
|
|
26
|
+
## [1.3.1] - 2026-05-30
|
|
27
|
+
|
|
28
|
+
### 🔧 Fixed
|
|
29
|
+
|
|
30
|
+
- **Double sort arrows on results grid column headers** (#22, #35) — The Fluent UI v9 `DataGrid` component renders its own sort indicator when `sortable` is set without a controlled `sortState`. This caused both Fluent's built-in arrow and the custom `renderHeaderCell` multi-sort arrow to render simultaneously. Fixed by passing a controlled `sortState` sentinel value (`sortColumn: "__sort_managed_externally__"`) that never matches any real column ID, preventing Fluent from rendering its internal indicator. The custom FetchXML-driven sort arrows in the column headers are now the sole source of truth.
|
|
31
|
+
|
|
32
|
+
- **"Parse to Tree" injects incorrect primary key for activity entities** (#37) — Standard entities follow the `${entityname}id` naming convention (e.g. `accountid`, `contactid`), but activity entities (`email`, `task`, `phonecall`, `fax`, `letter`, `appointment`, and custom activities) all inherit from `activitypointer` and use `activityid` as their primary key. The previous code hardcoded the `${entityname}id` pattern everywhere, causing `emailid`, `taskid`, etc. to be injected into the FetchXML query tree — attributes that do not exist in Dataverse. Fixed by threading `EntityMetadata.PrimaryIdAttribute` (the authoritative value from the Dataverse metadata API) through the full call chain. No fallback pattern or guessing — the primary key is only injected when the metadata is available.
|
|
33
|
+
|
|
34
|
+
### 🏗️ Technical
|
|
35
|
+
|
|
36
|
+
- `fetchxml.ts` — `generateFetchXml(fetchNode, primaryIdAttribute?)` accepts the PK from the caller; only injects the primary ID attribute when explicitly provided.
|
|
37
|
+
- `layoutxml.ts` — `generateLayoutFromFetchXml(fetchQuery, primaryIdAttribute?, attributeTypeMap?)` — PK is now optional; stored in `LayoutXmlConfig.primaryIdAttribute` when provided.
|
|
38
|
+
- `builderStore.tsx` — `ViewLoadInfo` now includes `originalFetchXml: string`; `SYNC_LAYOUT_WITH_FETCHXML` action and `syncLayoutWithFetchXml()` both accept `primaryIdAttribute?`; the store no longer derives or guesses the primary key itself.
|
|
39
|
+
- `ResultsGrid.tsx` — `primaryIdAttribute` prop replaces the old `${entityName}id` `useMemo`; `sortState` sentinel eliminates the double-arrow rendering.
|
|
40
|
+
- `PreviewTabs.tsx` — threads `primaryIdAttribute?` down to `ResultsGrid`.
|
|
41
|
+
- `AppShell.tsx` — passes `entityMetadata.PrimaryIdAttribute` to all call sites: `generateFetchXml`, `syncLayoutWithFetchXml`, `setLoadedView` (via `originalFetchXml`), and `<PreviewTabs>`.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## [1.3.0] - 2026-05-29
|
|
46
|
+
|
|
47
|
+
### ✨ Added
|
|
48
|
+
|
|
49
|
+
#### Code Generation Panel (#38)
|
|
50
|
+
- **Code tab** — New tab in the right pane (alongside FetchXML, LayoutXML, Results) with a tabbed panel that generates ready-to-use code from the current query in seven formats. Async formats (C# QueryExpression, SQL) run in parallel and cancel automatically when the query changes.
|
|
51
|
+
|
|
52
|
+
#### C# QueryExpression (#39, #40)
|
|
53
|
+
- Converts FetchXML to a full `QueryExpression` SDK object graph via the Dataverse `FetchXmlToQueryExpression` Web API function.
|
|
54
|
+
- Emits `ColumnSet`, `FilterExpression`, `ConditionExpression`, `LinkEntity`, `OrderExpression`, `XrmAttributeExpression`, `PagingInfo`, `TopCount`, `Distinct`, and `NoLock`.
|
|
55
|
+
- Full aggregate query support — `XrmAggregateType` (Count, CountColumn, Sum, Avg, Min, Max) and `XrmDateTimeGrouping` (Day, Week, Month, Quarter, Year, FiscalPeriod, FiscalYear).
|
|
56
|
+
- Correctly resolves all Dataverse API enum values returned as strings (`ConditionOperator`, `JoinOperator`, `LogicalOperator`, `OrderType`, `XrmAggregateType`, `XrmDateTimeGrouping`) via a shared `resolveEnum()` helper.
|
|
57
|
+
- Correctly unwraps .NET-serialized condition values (`{ "Type": "System.Int32", "Value": 0 }`) to C# integer / string / GUID literals via `unwrapODataValue()`.
|
|
58
|
+
|
|
59
|
+
#### C# FetchExpression (#43)
|
|
60
|
+
- Wraps the FetchXML in `new FetchExpression(@"...")` using a C# verbatim string literal for multi-line XML.
|
|
61
|
+
|
|
62
|
+
#### JavaScript (#43)
|
|
63
|
+
- Generates an `Xrm.WebApi.retrieveMultipleRecords` call for model-driven app JS, PCF components, and browser console.
|
|
64
|
+
|
|
65
|
+
#### pac CLI (#43)
|
|
66
|
+
- Generates a `pac org fetch --xml "..."` command for the Power Platform CLI.
|
|
67
|
+
|
|
68
|
+
#### Power Automate (#43)
|
|
69
|
+
- Field-by-field form mirroring the Dataverse "List rows" connector UI — not a plain code dump.
|
|
70
|
+
- Displays Table name, Select Columns, Filter Rows, Sort By, Top Count, and Fetch Xml Query fields with individual copy buttons and flash confirmation feedback.
|
|
71
|
+
- Table name resolved from `EntityDefinitions` metadata (already cached from entity selection) — accurate OData entity set name, not a heuristic pluralisation.
|
|
72
|
+
|
|
73
|
+
#### Web API (#43)
|
|
74
|
+
- Full OData URL with URL-encoded FetchXML, required request headers, a `curl` snippet, and a PowerShell `Invoke-RestMethod` example.
|
|
75
|
+
- Entity set name resolved from the same metadata cache as the Power Automate tab.
|
|
76
|
+
|
|
77
|
+
#### SQL (#39)
|
|
78
|
+
- T-SQL generated via the Dataverse `FetchXMLToSQL` Web API function (undocumented — labelled "Preview" with a tooltip warning).
|
|
79
|
+
- Robust response-property fallback parsing handles multiple possible response key names.
|
|
80
|
+
|
|
81
|
+
### 🏗️ Technical
|
|
82
|
+
|
|
83
|
+
- Added `src/features/fetchxml/engine/` — new code-generation module:
|
|
84
|
+
- `queryExpressionTypes.ts` — TypeScript interfaces mirroring the Dataverse QE JSON schema; all enum fields typed as `number | string` to match actual API wire responses.
|
|
85
|
+
- `queryExpressionCodegen.ts` — C# SDK code emitter with `resolveEnum()` and `unwrapODataValue()` helpers for robust handling of string-name enums and .NET-serialized value wrappers.
|
|
86
|
+
- `fetchxmlCodeGenerators.ts` — Sync code generators (FetchExpression, JavaScript, pac CLI, Power Automate spec, Web API); pure functions with no API calls required.
|
|
87
|
+
- Added `src/features/fetchxml/ui/RightPane/PowerAutomatePane.tsx` — field-by-field form component (3-column grid: label | input | copy button) with "N of N populated" badge and "Copy all" action.
|
|
88
|
+
- Added `src/features/fetchxml/ui/RightPane/CodePanel.tsx` — 7-tab code generation panel; async tabs run in parallel with abort-on-change cancellation.
|
|
89
|
+
- `PreviewTabs.tsx` — Added Code tab with `Code20Regular` icon.
|
|
90
|
+
- `pptbClient.ts` — Added `fetchXmlToQueryExpression` (calls `FetchXmlToQueryExpression` Dataverse function) and `fetchXmlToSQL` (calls `FetchXMLToSQL`) with multi-property fallback response parsing.
|
|
91
|
+
|
|
92
|
+
## [1.2.3-beta.3] - 2026-07-01
|
|
93
|
+
|
|
94
|
+
### 🏗️ Technical
|
|
95
|
+
|
|
96
|
+
- Upgraded `@pptb/types` `1.2.3-beta.0` → `1.2.3` (stable) ahead of merging the T2T branch into `dev`. Types are compile-time only, so there is **no runtime change** — the API surface FetchXML Studio uses (capability discovery, `launchTool` `noReturn`, `getToolContext`) is identical in the stable release. `features.minAPI` stays at `1.2.2`; discovery remains feature-detected and degrades gracefully on older hosts.
|
|
97
|
+
|
|
98
|
+
## [1.2.3-beta.2] - 2026-07-01
|
|
99
|
+
|
|
100
|
+
### 🐛 Fixed
|
|
101
|
+
|
|
102
|
+
- **Send to Tool no longer spins forever.** The launch is now fire-and-forget — previously the button awaited `launchTool`, whose promise doesn't resolve until the callee window closes, so the spinner stayed up for the whole session (reported when sending FXS → Bulk Data Studio). This is purely a caller-side fix; a callee does **not** need to declare a `returnTopic` to avoid it.
|
|
103
|
+
- **Always shows a "Send to Tool" dropdown.** Previously a single discovered tool collapsed the toolbar control into a button labelled with that tool's name; it now consistently reads "Send to Tool" and lists the target(s) in the menu.
|
|
104
|
+
- **Each target shows its tool id on its own line** beneath the display name in the menu.
|
|
105
|
+
- **FetchXML Studio no longer lists itself** as a target. Self-exclusion now matches on the runtime tool id from `getToolContext()` (with the npm package id as a fallback), since discovery reports the runtime id (e.g. `npm-mohsinonxrm-pptb-fetchxml-studio`) rather than the npm package name.
|
|
106
|
+
|
|
107
|
+
## [1.2.3-beta.1] - 2026-06-17
|
|
108
|
+
|
|
109
|
+
### ✨ Added
|
|
110
|
+
|
|
111
|
+
#### Tool-to-Tool (T2T) — capability-based tool discovery
|
|
112
|
+
|
|
113
|
+
The "Send to Tool" target list is now populated automatically via the PPTB capability registry instead of a manually maintained list. Requires **`@pptb/types` ≥ 1.2.3-beta.0** and a host that exposes capability discovery.
|
|
114
|
+
|
|
115
|
+
- **Automatic discovery** — FetchXML Studio calls `toolboxAPI.invocation.findToolsByCapability("fetchxml")` to find installed tools that declare the `fetchxml` capability, excludes itself, and lists them in the Send to Tool button (single button for one match, dropdown for several). Hidden when no matches or when the host lacks discovery — feature-detected at runtime, so older hosts degrade gracefully.
|
|
116
|
+
- **One-way send** — Launches now pass `noReturn: true`, the dedicated flag for the "Send To" pattern, which suppresses the callee's "Return to [Caller]" banner since FXS isn't waiting for data back.
|
|
117
|
+
|
|
118
|
+
### 🔧 Changed
|
|
119
|
+
|
|
120
|
+
- **Removed the manual "Tool Integration" settings.** The Settings → Tool Integration section and the `targetTools` display setting are gone; discovery replaces them entirely.
|
|
121
|
+
|
|
122
|
+
### 🏗️ Technical
|
|
123
|
+
|
|
124
|
+
- Bumped `@pptb/types` `1.2.2-beta.1` → `1.2.3-beta.0`, which now types `invocation.findToolsByCapability` / `getKnownCapabilityTags`, the `capabilities` field on `InvocationConfig`, the `CapabilityTag`/`KnownCapabilityTag` types, and `launchTool`'s `noReturn` option. Removed the local `InvocationAPI` interface in `invocation.ts` in favor of the now-published host types.
|
|
125
|
+
- `src/features/fetchxml/api/invocation.ts` — Added `DiscoveredTool` + `discoverFetchXmlTools()` (feature-detected; filters out our own id; defaults `name` to `id`); added `noReturn: true` to `sendFetchXmlToTool`.
|
|
126
|
+
- `src/shared/hooks/useSendToTools.ts` — New hook; discovers send targets once on mount.
|
|
127
|
+
- `src/app/AppShell.tsx` — Uses `useSendToTools`; Send to Tool slot now gated on `isT2TSupported() && sendToTools.length > 0`.
|
|
128
|
+
- `src/features/fetchxml/ui/Toolbar/SendToToolButton.tsx` — Prop changed from `targetTools: string[]` to `tools: DiscoveredTool[]`; labels use the discovered tool name.
|
|
129
|
+
- `src/features/fetchxml/ui/Settings/SettingsDrawer.tsx` — Removed the Tool Integration section, its handlers/state/styles, and now-unused imports.
|
|
130
|
+
- `src/features/fetchxml/model/displaySettings.ts` — Removed `targetTools` from `DisplaySettings` and the defaults.
|
|
131
|
+
|
|
132
|
+
## [1.2.2-beta.2] - 2026-06-16
|
|
133
|
+
|
|
134
|
+
### ✨ Added
|
|
135
|
+
|
|
136
|
+
#### Tool-to-Tool (T2T) Invocation — Callee (prefill + return)
|
|
137
|
+
|
|
138
|
+
FetchXML Studio can now be *launched by* another PPTB tool, pre-populated with an inbound query, and hand a query back. Completes the round-trip alongside the existing caller support.
|
|
139
|
+
|
|
140
|
+
- **Inbound prefill** — On launch via T2T, FetchXML Studio reads its launch context and pre-populates the builder. Resolution priority is `fetchXml` → `viewRef` → `entityLogicalName`: a `fetchXml` string is loaded directly; a `viewRef` has its FetchXML retrieved from the referenced `savedquery`/`userquery`; and a bare `entityLogicalName` starts a fresh query on that entity. When `fetchXml` is present the root entity is **derived from the FetchXML itself** and any `entityLogicalName` hint is ignored, because a mismatched value would break this metadata-driven tool's lookups.
|
|
141
|
+
- **Return FetchXML button** — When launched as a callee, a "Return FetchXML" button appears in the FetchXML toolbar. It returns `{ fetchXml }` (the current editor-or-tree query) to the caller via `returnData()`, which the host resolves as the caller's `launchTool(...)` result. This is intentionally separate from the host-injected "Return to [Caller]" banner, which only navigates back and resolves the caller's promise with `null`.
|
|
142
|
+
- **`pptb.config.json`** — Added the `fetchxml` capability tag (for discovery via `findToolsByCapability`) and a `returnTopic` describing the `{ fetchXml }` return shape. Relaxed the prefill contract so `entityLogicalName` is optional/hint-only.
|
|
143
|
+
|
|
144
|
+
### 🏗️ Technical
|
|
145
|
+
|
|
146
|
+
- `src/features/fetchxml/api/invocation.ts` — Added callee helpers: `getLaunchContext()`, `resolveLaunchPrefill(context)` (returns a `{ kind: "fetchxml" | "entity" }` action following the `fetchXml` → `viewRef` → `entityLogicalName` priority; resolves `viewRef` by reusing the `dataverseAPI.queryData` view-read route filtered to a single record), `returnDataToInvokingTool(data)`, and `returnFetchXmlToInvokingTool(fetchXml)`. Added `FetchXmlStudioLaunchPrefill` type and `LaunchPrefillAction` union.
|
|
147
|
+
- `src/shared/hooks/useLaunchContext.ts` — New hook. Calls `getLaunchContext()` once on mount and exposes `{ loading, isCallee, context }` so detection happens in one place.
|
|
148
|
+
- `src/app/AppShell.tsx` — Consumes the prefill exactly once on launch (loads incoming FetchXML via `builder.loadFetchXml`), and passes `isCallee` to `PreviewTabs`.
|
|
149
|
+
- `src/features/fetchxml/ui/RightPane/PreviewTabs.tsx` — Added `isCallee?` prop and a `ReturnFetchXmlButton` (gated on `isCallee`) rendered next to Execute; uses a `getCurrentXml()` helper that returns the live editor buffer when in editor mode.
|
|
150
|
+
|
|
151
|
+
### 🔧 Changed
|
|
152
|
+
|
|
153
|
+
- **"Send to Tool" button visibility** — The caller button is now hidden entirely unless at least one target tool is configured under Settings → Tool Integration (previously it rendered as a disabled button with a tooltip). The two T2T toolbar actions are now strictly capability-gated and never change meaning by mode: **Return FetchXML** shows only when launched as a callee (`isCallee`); **Send to Tool** shows only when targets are configured.
|
|
154
|
+
|
|
155
|
+
## [1.2.2-beta.1] - 2026-05-25
|
|
156
|
+
|
|
157
|
+
### ✨ Added
|
|
158
|
+
|
|
159
|
+
#### Tool-to-Tool (T2T) Invocation — Caller
|
|
160
|
+
|
|
161
|
+
FetchXML Studio can now send the active query to any other PPTB tool that accepts a FetchXML prefill payload. Requires **PPTB host ≥ 1.2.2**.
|
|
162
|
+
|
|
163
|
+
- **Send to Tool button** — A new "Send to Tool" button appears in the toolbar (alongside Save View) whenever the PPTB host exposes the `toolboxAPI.invocation` API. Three interaction modes depending on how many target tools are configured:
|
|
164
|
+
- *No tools configured* — Button is disabled with a tooltip pointing to Settings → Tool Integration.
|
|
165
|
+
- *One tool configured* — Single button; click launches the tool directly.
|
|
166
|
+
- *Multiple tools configured* — Dropdown menu listing all configured tools; click an item to launch.
|
|
167
|
+
- **Settings → Tool Integration section** — New section in the Settings drawer to manage the list of target tool npm package IDs (e.g. `@linked365/pptb-bulk-data-studio`). Supports add (text input + Enter/Add button) and remove (× button per item). The list is persisted via `toolboxAPI.settings` alongside other display preferences.
|
|
168
|
+
- **Active connection forwarding** — The caller automatically retrieves the currently active Dataverse connection and forwards its ID as `primaryConnectionId` when launching the target tool, so the callee opens against the same environment.
|
|
169
|
+
- **`pptb.config.json`** — Added PPTB callee contract file at the repository root. Declares the prefill schema this tool accepts when *receiving* a T2T invocation from another tool (see [Callee Contract](#-callee-contract-pptbconfigjson) in the README). `viewRef` is modelled as a Dataverse EntityReference: required fields `id` (UUID string) and `entityLogicalName` (enum: `"savedquery"` | `"userquery"`).
|
|
170
|
+
|
|
171
|
+
### 🏗️ Technical
|
|
172
|
+
|
|
173
|
+
- `src/features/fetchxml/api/invocation.ts` — New module. Defines a local `InvocationAPI` interface (mirrors the PPTB host API not yet in `@pptb/types`) and exposes `isT2TSupported()` and `sendFetchXmlToTool(targetToolId, { fetchXml, entityLogicalName })`.
|
|
174
|
+
- `src/features/fetchxml/ui/Toolbar/SendToToolButton.tsx` — New toolbar component. Handles the disabled / single / multi-tool rendering variants; calls `sendFetchXmlToTool`; surfaces errors via `toolboxAPI.utils.showNotification`.
|
|
175
|
+
- `src/features/fetchxml/model/displaySettings.ts` — Added `targetTools: string[]` (default `[]`) to `DisplaySettings` interface and `defaultDisplaySettings`.
|
|
176
|
+
- `src/features/fetchxml/ui/Settings/SettingsDrawer.tsx` — Added Tool Integration section with add/remove UI. Added `Input`, `Field`, `Add20Regular`, `Dismiss16Regular`, `PlugConnected20Regular` to imports.
|
|
177
|
+
- `src/features/fetchxml/ui/RightPane/PreviewTabs.tsx` — Added `sendToToolButton?: ReactNode` prop; rendered unconditionally (all tabs) next to `saveViewButton`.
|
|
178
|
+
- `src/app/AppShell.tsx` — Imports `SendToToolButton` + `isT2TSupported`; passes `sendToToolButton` prop to `PreviewTabs` gated on `isT2TSupported()`.
|
|
179
|
+
- `package.json` — `features.minAPI` bumped from `1.2.0` → `1.2.2` to reflect the new PPTB host requirement. `scheduler` added to `devDependencies` (required peer dep of `@fluentui/react-context-selector` that was missing from the install tree).
|
|
180
|
+
|
|
181
|
+
#### Packaging fixes (resolves #33)
|
|
182
|
+
|
|
183
|
+
- **`icon` path corrected** — `"icon"` field in `package.json` was missing the `icons/` directory prefix (`"icon-insider.svg"` → `"icons/icon-insider.svg"`). Icon was not resolvable by PPTB at install time.
|
|
184
|
+
- **`files` array expanded** — Added `"icons"`, `"index.html"`, `"LICENSE"`, `"README.md"`, `"CHANGELOG.md"`, `"SECURITY.md"` alongside the existing `"dist"` and `"npm-shrinkwrap.json"` entries. Previously the `icons/` folder (referenced by the `"icon"` field) and all root-level docs were absent from the published package.
|
|
185
|
+
- **Production source maps disabled** — Added `sourcemap: false` to `vite.config.ts` `build` options. Monaco worker source maps were silently adding ~17 MB to the package; disabling them brings the published size down to ~3–4 MB.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## [1.2.1] - 2026-04-07
|
|
190
|
+
|
|
191
|
+
### ✨ Added
|
|
192
|
+
|
|
193
|
+
- **Copy button in editor mode** — The FetchXML editor toolbar now includes a Copy button when in editor mode, making it consistent with the read-only toolbar. Previously Copy was only available when the editor was not in edit mode.
|
|
194
|
+
|
|
195
|
+
### 🔧 Fixed
|
|
196
|
+
|
|
197
|
+
- **Results grid column overlap** — Column widths are now estimated dynamically from header text (capped at 400 px) so adjacent columns no longer overlap on first render. All cells use `TableCellLayout truncate` for clean overflow.
|
|
198
|
+
- **Results grid header/row misalignment** — Removed a stray CSS class from `DataGridBody` that was causing header and row widths to drift out of sync when the grid had overflowing content.
|
|
199
|
+
- **Alias validation in property editors** — Typing an invalid alias character (space, hyphen, special character) in `AttributeEditor` or `LinkEntityEditor` now sanitizes the value in real time: invalid characters are stripped, and a leading digit is prefixed with `_`.
|
|
200
|
+
- **Alias validation in parser** — When parsing FetchXML (both *Parse to Tree* and *Execute*), invalid aliases are now automatically sanitized. A parse warning describes the correction (e.g. *"Alias 'this is id' had invalid characters and was corrected to 'thisisid'."*) instead of silently forwarding the invalid alias to Dataverse where it would cause an API error.
|
|
201
|
+
- **Execute blocked when alias warnings are present** — Clicking Execute in editor mode now validates the XML completely before sending it to Dataverse. If parse warnings exist (e.g. an invalid alias that wasn't auto-corrected via *Parse to Tree*), execution is blocked and the warning is surfaced in a message bar above the editor with a hint to use *Parse to Tree* to auto-correct. Previously the bad alias was silently sent to Dataverse and the error appeared in the Results tab.
|
|
202
|
+
- **Editor state preserved across tab switches** — Switching from the FetchXML tab to Results or LayoutXML and back no longer resets editor mode or discards the edited XML. The editor component is now always mounted (hidden via `display: none` when not active) so Monaco state — editor mode toggle, cursor position, edit buffer — is fully preserved.
|
|
203
|
+
- **Validate contradictory messages** — *Validate* no longer shows both a "Valid" success message and warnings simultaneously. When warnings are present, validate now shows each warning plus an "Action required" notice and stops — the "Valid" success message is only shown when there are zero warnings.
|
|
204
|
+
- **Parse to Tree corrections shown as informational** — Auto-corrected alias warnings from *Parse to Tree* are now shown with `intent="info"` (blue) rather than `intent="warning"` (yellow), correctly communicating that the tool has already resolved the problem.
|
|
205
|
+
- **Execute API errors surfaced** — Dataverse API errors that occur during query execution are now captured and displayed in a message bar in the Results tab. Previously they were only visible in the browser console.
|
|
206
|
+
|
|
207
|
+
### 🏗️ Technical
|
|
208
|
+
|
|
209
|
+
- Added `src/features/fetchxml/model/aliasUtils.ts` — `isValidAlias()` and `sanitizeAlias()` shared utilities enforcing the Dataverse alias constraint (`[A-Za-z_][A-Za-z0-9_]*`).
|
|
210
|
+
- `fetchxmlParser.ts` — `parseAttribute` and `parseLinkEntity` now import `sanitizeAlias`; invalid aliases are corrected in place and described in the parse warning rather than propagated as-is.
|
|
211
|
+
- `PreviewTabs.tsx` — `FetchXmlEditor` is always mounted; `handleExecute` blocks on parse warnings; navigating back to the FetchXML tab clears any stale editor validation error banner.
|
|
212
|
+
- `AppShell.tsx` — `handleExecute` accepts an optional `xmlOverride` (used when editor mode is active); `executeError` state threads Dataverse API errors back to the `PreviewTabs` message bar.
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## [1.2.0] - 2026-04-03
|
|
217
|
+
|
|
218
|
+
### ✨ Added
|
|
219
|
+
|
|
220
|
+
#### Query Scope Settings
|
|
221
|
+
- **Entity Scope Mode** — New setting (persisted across sessions) to control which entities appear in the entity dropdown:
|
|
222
|
+
- **Publisher + Solution** — Select a publisher, then narrow to specific solutions; only entities belonging to those solutions are shown
|
|
223
|
+
- **Solution Only** — Skip the publisher step and pick solutions directly
|
|
224
|
+
- **All Entities** — Show every entity in the environment (no solution filter)
|
|
225
|
+
- **Advanced Find Only toggle** — When enabled (default), entities and attributes are limited to those marked `IsValidForAdvancedFind = true`, matching the classic Advanced Find behavior. Disabling shows all entities and attributes — including system and developer-only tables — useful for building admin or integration queries. The filter is applied locally so toggling is instant with no additional API call.
|
|
226
|
+
- Scope mode and Advanced Find preference are persisted individually via `toolboxAPI.settings` and survive across sessions.
|
|
227
|
+
|
|
228
|
+
#### Monaco Editor — Local Bundling
|
|
229
|
+
- Monaco is now fully bundled in `dist/` instead of being fetched from a CDN at runtime.
|
|
230
|
+
- Eliminates CSP errors and ensures line numbers, syntax highlighting, and all editor features work correctly in the PPTB host environment without network access to external CDNs.
|
|
231
|
+
|
|
232
|
+
### 🔧 Fixed
|
|
233
|
+
|
|
234
|
+
- **Internal solutions in Solution-only mode** — Solutions from `isreadonly = true` publishers (Microsoft, system publishers) are now excluded from the solution picker, consistent with what Publisher + Solution mode shows. Previously some Microsoft-owned visible solutions appeared in the list.
|
|
235
|
+
- **Parse-to-tree no longer resets the entity** — Pasting FetchXML into the editor and clicking "Parse to Tree" no longer wipes the selected entity. The validation that auto-clears the entity selection now only fires when there is an active solution filter in place (i.e. specific solutions have been selected) and the entity has dropped out of scope — not when the entity was set programmatically via the XML editor.
|
|
236
|
+
- **Entity list cache race condition** — `loadAllEntities` no longer accepts an `advancedFindOnly` parameter. It always fetches all entities from the server (no `$filter=IsValidForAdvancedFind eq true`). The Advanced Find filter is now applied locally in the EntitySelector `memo`. This eliminates a bug where an earlier `advancedFindOnly=true` load could poison the cache and cause subsequent `advancedFindOnly=false` calls to silently return the wrong (filtered) set.
|
|
237
|
+
- **Privilege check console noise** — `checkPrivilegeByName` errors for privileges that don't exist in the environment (e.g. `prvDeleteGitorganization` for system tables) are now logged as `console.warn` instead of `console.error`. The UI behavior is unchanged.
|
|
238
|
+
- **CSP exception** — Removed the invalid `*.crm*.dynamics.com` wildcard from `cspExceptions` (browsers reject multi-depth subdomain wildcards). The only `connect-src` exception kept is `https://*.dynamics.com`.
|
|
239
|
+
|
|
240
|
+
### 🏗️ Technical
|
|
241
|
+
|
|
242
|
+
- `useAccessMode` preloads only the AF-valid entity metadata cache (`allEntityMetadataCache`) on startup — used by publisher-solution and solution-only modes. The all-entities cache is populated lazily the first time "All Entities" scope mode is used.
|
|
243
|
+
- `loadAllEntities` / `useLazyMetadata.loadEntities` signatures simplified (no `advancedFindOnly` param — always fetches everything).
|
|
244
|
+
- `vite.config.ts` — `manualChunks` splits Monaco into its own chunk (`monaco-editor-*.js`, ~3.7 MB; `monaco-editor-*.css`, ~145 kB).
|
|
245
|
+
- TypeScript strict compile: **zero errors** (`tsc -b --noEmit`).
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## [1.1.0] - 2026-03-23
|
|
250
|
+
|
|
251
|
+
### ⬆️ Upgraded
|
|
252
|
+
|
|
253
|
+
- **`@pptb/types` 1.0.7 → 1.2.0** — now the authoritative source for all PPTB host API types (`window.dataverseAPI`, `window.toolboxAPI`). Added to `tsconfig.app.json` `types` array so global augmentations apply project-wide without per-file triple-slash references.
|
|
254
|
+
- **`features.minAPI`** set to `"1.2.0"` in `package.json` to enforce the correct PPTB host version at install time.
|
|
255
|
+
|
|
256
|
+
### ✨ Added
|
|
257
|
+
|
|
258
|
+
#### Native File Save Dialog
|
|
259
|
+
- Both export paths (local ExcelJS export and Dataverse `ExportToExcel` action) now use `window.toolboxAPI.fileSystem.saveFile` when running inside the PPTB desktop host, presenting a native OS save-file dialog instead of a forced browser blob download.
|
|
260
|
+
- Graceful fallback to browser blob/anchor download when running in standalone or dev context (i.e. when `window.toolboxAPI` is not available).
|
|
261
|
+
|
|
262
|
+
#### Connection Environment Awareness
|
|
263
|
+
- `PptbContext` now exposes `environment?: "Dev" | "Test" | "UAT" | "Production"` sourced from the active `DataverseConnection`.
|
|
264
|
+
- Subscribes to `connection:updated`, `connection:created`, and `connection:deleted` PPTB events to keep the field in sync dynamically.
|
|
265
|
+
|
|
266
|
+
#### Package Manifest Hardening
|
|
267
|
+
- Added top-level `"icon"` field pointing to `icons/icon.svg` (replacing deprecated `configurations.iconUrl`).
|
|
268
|
+
- `"features"` block added: `{ "multiConnection": "none", "minAPI": "1.2.0" }`.
|
|
269
|
+
- `cspExceptions` migrated from plain-string arrays to the required object format with `domain` + `exceptionReason` fields (+ `optional: true` on style-src).
|
|
270
|
+
- Added `"validate": "pptb-validate"` npm script for pre-publish manifest validation.
|
|
271
|
+
- Added `"finalize-package": "npm run build && npm shrinkwrap"` convenience script.
|
|
272
|
+
|
|
273
|
+
### ♻️ Refactored
|
|
274
|
+
|
|
275
|
+
#### `pptbClient.ts`
|
|
276
|
+
- Removed the entire hand-written `declare global { interface Window { dataverseAPI?: { ... } } }` block (~60 lines). The `window.dataverseAPI` global is now typed entirely by `@pptb/types`.
|
|
277
|
+
- Added local `DataverseFetchXmlResponse` interface to capture OData response annotations beyond what `@pptb/types` `FetchXmlResult` declares (`@Microsoft.Dynamics.CRM.totalrecordcount`, `morerecords`, `pagingcookie`, `totalrecordcountlimitexceeded`). These are OData wire annotations returned directly by Dataverse — not fabricated by PPTB — so the cast is safe at runtime.
|
|
278
|
+
- `downloadBase64File()` changed from `void` to `async Promise<void>`; uses `fileSystem.saveFile` when available.
|
|
279
|
+
|
|
280
|
+
#### `usePptbContext.ts`
|
|
281
|
+
- Removed the entire hand-written `declare global { interface Window { toolboxAPI?: { ... } } }` block. The `window.toolboxAPI` global is now typed entirely by `@pptb/types`.
|
|
282
|
+
- `PptbContext` interface: removed legacy `organizationId?: string` (not present in `DataverseConnection` v1.2.0 types); replaced with `environment?: "Dev" | "Test" | "UAT" | "Production"`.
|
|
283
|
+
|
|
284
|
+
#### `excelExport.ts`
|
|
285
|
+
- `downloadExcelFile()` changed from `void` to `async Promise<void>`; uses `fileSystem.saveFile` when available.
|
|
286
|
+
|
|
287
|
+
#### `AppShell.tsx`
|
|
288
|
+
- Both download call sites updated with `await` to match the new async signatures.
|
|
289
|
+
|
|
290
|
+
### 🔧 Technical
|
|
291
|
+
|
|
292
|
+
- TypeScript strict compile: **zero errors** (`tsc -b --noEmit`).
|
|
293
|
+
- `pptb-validate`: **✔ Validation passed**.
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## [1.0.6] - 2026-01-14
|
|
298
|
+
|
|
299
|
+
### ✨ Added
|
|
300
|
+
|
|
301
|
+
#### Select Attributes Dialog (#12)
|
|
302
|
+
- **Bulk Attribute Selection**: New "Select Attributes" modal dialog for efficient multi-attribute selection
|
|
303
|
+
- Accessible from entity and link-entity context menus in the tree view
|
|
304
|
+
- Works on root entity, link-entities, and nested link-entities at any level
|
|
305
|
+
- **Smart Selection Grid**: DataGrid showing all available entity attributes
|
|
306
|
+
- Three sortable columns: Logical Name, Display Name, and Data Type
|
|
307
|
+
- Pre-selects currently selected attributes with checkboxes
|
|
308
|
+
- Multi-select support for bulk add/remove operations
|
|
309
|
+
- **Search & Filter**: Integrated SearchBox for quick attribute filtering
|
|
310
|
+
- Filters across all columns (logical name, display name, data type)
|
|
311
|
+
- Real-time filtering as you type
|
|
312
|
+
- **Fixed Headers**: Column headers remain visible while scrolling through attributes
|
|
313
|
+
- **Confirmation Required**: Changes only applied when user clicks Apply button
|
|
314
|
+
- Cancel button discards changes without affecting the tree
|
|
315
|
+
- **Smart Updates**: Intelligently adds new attributes and removes deselected ones
|
|
316
|
+
- Preserves existing attributes that remain selected
|
|
317
|
+
- Maintains attribute order and properties
|
|
318
|
+
- **Performance**: Leverages metadata cache for fast attribute loading
|
|
319
|
+
- Falls back to API loading if attributes not cached
|
|
320
|
+
- Shows only attributes valid for Advanced Find
|
|
321
|
+
|
|
322
|
+
### 🔧 Technical
|
|
323
|
+
|
|
324
|
+
- Added `SelectAttributesDialog` component with FluentUI DataGrid
|
|
325
|
+
- New `UPDATE_ATTRIBUTES` action in builderStore for bulk attribute operations
|
|
326
|
+
- Enhanced TreeView with dialog state management and attribute loading
|
|
327
|
+
- Integrated with existing metadata caching system
|
|
328
|
+
|
|
329
|
+
## [1.0.0] - 2024-12-15
|
|
330
|
+
|
|
331
|
+
### 🎉 Initial Release
|
|
332
|
+
|
|
333
|
+
FetchXML Studio v1.0.0 - A powerful FetchXML query builder for Power Platform ToolBox.
|
|
334
|
+
|
|
335
|
+
### ✨ Features
|
|
336
|
+
|
|
337
|
+
#### Query Builder
|
|
338
|
+
- Tree-based visual query builder with hierarchical FetchXML structure
|
|
339
|
+
- Full entity, attribute, filter, order, and link-entity support
|
|
340
|
+
- Context-aware properties panel for each node type
|
|
341
|
+
- Nested filter groups with AND/OR logic
|
|
342
|
+
- Support for all FetchXML operators (60+ operators)
|
|
343
|
+
- Aggregate queries with groupby and distinct
|
|
344
|
+
- Query hints for performance optimization
|
|
345
|
+
|
|
346
|
+
#### Relationships & Joins
|
|
347
|
+
- Relationship picker with 1:N, N:1, N:N categorization
|
|
348
|
+
- Inner and outer join support
|
|
349
|
+
- Filter link-entity for any/all/not any/not all scenarios
|
|
350
|
+
- Value-of conditions for cross-entity comparisons
|
|
351
|
+
- Entity name conditions for outer join filtering
|
|
352
|
+
|
|
353
|
+
#### Results Grid
|
|
354
|
+
- Virtualized DataGrid for large datasets (react-window)
|
|
355
|
+
- Rich cell rendering for lookups, option sets, dates, currency
|
|
356
|
+
- Multi-column sorting (click + Shift+click)
|
|
357
|
+
- Row selection (single and multi-select)
|
|
358
|
+
- Resizable and reorderable columns
|
|
359
|
+
- Formatted values with raw value toggle
|
|
360
|
+
|
|
361
|
+
#### FetchXML Editor
|
|
362
|
+
- Monaco editor with XML syntax highlighting
|
|
363
|
+
- Bi-directional editing (visual ↔ XML)
|
|
364
|
+
- Parse FetchXML to visual builder
|
|
365
|
+
- Copy to clipboard
|
|
366
|
+
- LayoutXML preview tab
|
|
367
|
+
|
|
368
|
+
#### Views
|
|
369
|
+
- Load system and personal views
|
|
370
|
+
- Optimized view execution via SavedQuery/UserQuery APIs
|
|
371
|
+
- Save queries as personal views
|
|
372
|
+
- Update existing views
|
|
373
|
+
- Solution-aware save (add to solution)
|
|
374
|
+
|
|
375
|
+
#### Data Operations
|
|
376
|
+
- Export to Excel with native data types
|
|
377
|
+
- Delete selected records
|
|
378
|
+
- Bulk delete jobs (async)
|
|
379
|
+
- Run on-demand workflows on selection
|
|
380
|
+
- Batch progress tracking with ETA
|
|
381
|
+
|
|
382
|
+
#### User Experience
|
|
383
|
+
- Dark/Light theme support (follows PPTB theme)
|
|
384
|
+
- Lazy metadata loading
|
|
385
|
+
- Intelligent caching (per-session)
|
|
386
|
+
- Resizable split panes
|
|
387
|
+
- Keyboard shortcuts (Ctrl+Enter to execute)
|
|
388
|
+
|
|
389
|
+
#### Security
|
|
390
|
+
- Privilege-aware operations
|
|
391
|
+
- Export/Delete privilege checks
|
|
392
|
+
- Bulk delete privilege validation
|
|
393
|
+
- Workflow execution privilege checks
|
|
394
|
+
|
|
395
|
+
### 🏗️ Technical
|
|
396
|
+
|
|
397
|
+
- Built with React 19 and TypeScript 5.9
|
|
398
|
+
- Fluent UI v9 components
|
|
399
|
+
- Monaco Editor integration
|
|
400
|
+
- ExcelJS for native Excel export
|
|
401
|
+
- Vite build tooling
|
|
402
|
+
- Power Platform ToolBox integration via @pptb/types
|
|
403
|
+
|
|
404
|
+
### 📚 Documentation
|
|
405
|
+
|
|
406
|
+
- Comprehensive README with feature overview
|
|
407
|
+
- Debug logging system documentation
|
|
408
|
+
- Project structure guide
|
|
409
|
+
- Contributing guidelines
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
## Development History
|
|
414
|
+
|
|
415
|
+
### Pre-release commits (dev branch)
|
|
416
|
+
|
|
417
|
+
- `feat: Beta release enhancements - Settings, Export, and UX improvements`
|
|
418
|
+
- `feat(preview): add LayoutXML tab to preview pane`
|
|
419
|
+
- `feat(commands): add record action commands - delete, bulk delete, workflow`
|
|
420
|
+
- `feat(columns): Add/Edit Columns panels with related entity support`
|
|
421
|
+
- `feat(export): add Export to Excel with status feedback and privilege check`
|
|
422
|
+
- `feat(paging): fix paging with cookies and page size support`
|
|
423
|
+
- `feat(grid): multi-entity metadata & column display name fixes`
|
|
424
|
+
- `feat(builder): Sprint 1 - Foundation & Layout improvements`
|
|
425
|
+
- `feat(save): implement Save View functionality`
|
|
426
|
+
- `feat(sort): Add multi-column sort with FetchXML integration`
|
|
427
|
+
- `feat(results): Add Column from Results Grid`
|
|
428
|
+
- `feat(views): Load view LayoutXML for column configuration`
|
|
429
|
+
- `feat(layout): Add column resize and reorder`
|
|
430
|
+
- `feat(layout): Add LayoutXML foundation`
|
|
431
|
+
- `feat(filter): Add filter link-entity support for any/not any/all scenarios`
|
|
432
|
+
- `feat(condition): Add valueof cross-entity comparison`
|
|
433
|
+
- `feat(condition): Add valueof same-row column comparison`
|
|
434
|
+
- `feat(condition): Add entityname support for outer join filtering`
|
|
435
|
+
- `feat(views): Add Load View picker and optimized view execution`
|
|
436
|
+
- `feat(parser): Add FetchXML parser with Monaco editor dialog`
|
|
437
|
+
- `feat: Implement Phases 1-4 - DataGrid UI polish`
|
|
438
|
+
- `feat: add filter consistency, cascading validation, and global metadata caching`
|
|
439
|
+
- `feat(entity-selector): implement advanced filtering with publisher/solution multiselect`
|
|
440
|
+
- `feat(ui): add resizable panes with visual grip indicators and command bar`
|
|
441
|
+
- `Initial commit - setup main branch`
|
package/README.md
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
A powerful, modern FetchXML query builder and data explorer for [Power Platform ToolBox](https://github.com/PowerPlatformToolBox/desktop-app). Inspired by the XrmToolBox FetchXML Builder, reimagined with React 18, Fluent UI v9, and seamless Dataverse integration.
|
|
4
4
|
|
|
5
|
-

|
|
6
6
|

|
|
7
7
|

|
|
8
8
|

|
|
9
|
-

|
|
10
10
|
|
|
11
11
|
## ✨ Features
|
|
12
12
|
|
|
@@ -73,8 +73,13 @@ A powerful, modern FetchXML query builder and data explorer for [Power Platform
|
|
|
73
73
|
- **Query scope settings** — Control which entities appear in the entity picker: *Publisher + Solution* (full filter), *Solution Only*, or *All Entities* (no filter). Persisted across sessions.
|
|
74
74
|
- **Advanced Find Only toggle** — When on (default), limits entities and attributes to those marked `IsValidForAdvancedFind = true`. Disable to access all entities including system and developer tables. Filter is applied locally — toggling is instant with no additional API call.
|
|
75
75
|
|
|
76
|
+
### 🔗 Tool-to-Tool (T2T) Integration
|
|
77
|
+
- **Send to Tool button** — Launch another PPTB tool directly from FetchXML Studio, pre-loading it with the current FetchXML query and active Dataverse connection (one-way handoff).
|
|
78
|
+
- **Automatic tool discovery** — Targets are discovered via the PPTB capability registry — installed tools that declare the `fetchxml` capability. The Send to Tool control always renders as a dropdown listing the discovered tools (even a single match). No configuration needed.
|
|
79
|
+
- **Active connection forwarding** — The active Dataverse connection is forwarded automatically so the target tool opens against the same environment.
|
|
80
|
+
- **Inbound prefill** — FetchXML Studio also accepts incoming T2T invocations from other tools (see [Callee Contract](#-callee-contract-pptbconfigjson) below).
|
|
81
|
+
|
|
76
82
|
### 🔒 Privilege-Aware
|
|
77
|
-
- **Security checks** — Validates user privileges before every destructive or restricted operation
|
|
78
83
|
- **Export privilege check** — Only shows Dataverse export option if user has access
|
|
79
84
|
- **Delete privilege check** — Validates entity-specific delete permissions before enabling delete actions
|
|
80
85
|
- **Bulk delete privilege check** — Validates `prvBulkDelete` before surfacing bulk delete
|
|
@@ -85,7 +90,7 @@ A powerful, modern FetchXML query builder and data explorer for [Power Platform
|
|
|
85
90
|
|
|
86
91
|
```
|
|
87
92
|
┌─────────────────────────────────────────────────────────────────────────┐
|
|
88
|
-
│ [Entity Selector ▼] [Load View ▼] [Save View]
|
|
93
|
+
│ [Entity Selector ▼] [Load View ▼] [Save View] [Send to Tool ▼] [⚙] │
|
|
89
94
|
├──────────────────────┬──────────────────────────────────────────────────┤
|
|
90
95
|
│ │ [FetchXML] [LayoutXML] [Results] [Code] [▶ Execute]│
|
|
91
96
|
│ Query Tree ├──────────────────────────────────────────────────┤
|
|
@@ -179,7 +184,7 @@ disableAllDebug();
|
|
|
179
184
|
| **Monaco Editor** | 0.54 | VS Code XML editor for FetchXML authoring |
|
|
180
185
|
| **react-window** | 2 | Virtualized list rendering for large datasets |
|
|
181
186
|
| **ExcelJS** | 4.4 | Native `.xlsx` generation with typed cells |
|
|
182
|
-
| **@pptb/types** | 1.2.
|
|
187
|
+
| **@pptb/types** | 1.2.3 | Power Platform ToolBox host API types (`window.dataverseAPI`, `window.toolboxAPI`) |
|
|
183
188
|
|
|
184
189
|
## 📁 Project Structure
|
|
185
190
|
|
|
@@ -192,7 +197,8 @@ src/
|
|
|
192
197
|
│ │ ├── pptbClient.ts # window.dataverseAPI wrapper (all Dataverse ops)
|
|
193
198
|
│ │ ├── dataverseMetadata.ts # Lazy metadata loading with cache + dedup
|
|
194
199
|
│ │ ├── excelExport.ts # Local ExcelJS export with native types
|
|
195
|
-
│ │
|
|
200
|
+
│ │ ├── formattedValues.ts # OData @FormattedValue annotation helpers
|
|
201
|
+
│ │ └── invocation.ts # T2T caller API (isT2TSupported, sendFetchXmlToTool)
|
|
196
202
|
│ ├── model/
|
|
197
203
|
│ │ ├── nodes.ts # FetchXML node TypeScript definitions
|
|
198
204
|
│ │ ├── fetchxml.ts # FetchXML XML generation
|
|
@@ -215,7 +221,9 @@ src/
|
|
|
215
221
|
│ │ └── editors/ # Node-specific property editors
|
|
216
222
|
│ ├── RightPane/ # Monaco editor, LayoutXML viewer, results grid,
|
|
217
223
|
│ │ # code generation panel, Power Automate pane
|
|
218
|
-
│ ├── Toolbar/ # Entity selector, load view picker, save button
|
|
224
|
+
│ ├── Toolbar/ # Entity selector, load view picker, save button,
|
|
225
|
+
│ │ # send-to-tool button
|
|
226
|
+
|
|
219
227
|
│ ├── Dialogs/ # Save view, select attributes, delete, bulk
|
|
220
228
|
│ │ # delete, workflow picker, solution picker
|
|
221
229
|
│ └── Settings/ # Settings drawer (display preferences)
|
|
@@ -253,6 +261,64 @@ src/
|
|
|
253
261
|
| Filter link-entity (any/all) | ✅ |
|
|
254
262
|
| Query hints | ✅ |
|
|
255
263
|
|
|
264
|
+
## 🔗 Callee Contract (`pptb.config.json`)
|
|
265
|
+
|
|
266
|
+
FetchXML Studio declares a PPTB [Inter-Tool Invocation](https://github.com/PowerPlatformToolBox/desktop-app) callee contract in `pptb.config.json` at the repository root, and declares the `fetchxml` capability so callers can discover it. Any other PPTB tool can launch FetchXML Studio and pre-populate it by passing a prefill payload that matches the following schema:
|
|
267
|
+
|
|
268
|
+
```json
|
|
269
|
+
{
|
|
270
|
+
"fetchXml": "<fetch><entity name=\"account\">...</entity></fetch>"
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
| Field | Type | Required | Description |
|
|
275
|
+
|---|---|---|---|
|
|
276
|
+
| `fetchXml` | `string` | One of these three | Full serialized FetchXML query string. The root entity is parsed from this. |
|
|
277
|
+
| `viewRef` | `object` | One of these three | EntityReference to an existing view. The FetchXML is retrieved from the view record. |
|
|
278
|
+
| `entityLogicalName` | `string` | One of these three | Root entity logical name (e.g. `"account"`). Starts a fresh query on that entity. **Ignored when `fetchXml` is present** — the root entity is then derived from the FetchXML, since a mismatched value would break this metadata-driven tool's lookups. |
|
|
279
|
+
| `viewRef.id` | `string` (uuid) | Required if viewRef | GUID of the view record |
|
|
280
|
+
| `viewRef.entityLogicalName` | `"savedquery"` \| `"userquery"` | Required if viewRef | Dataverse entity logical name — `savedquery` = system/public view, `userquery` = personal view |
|
|
281
|
+
|
|
282
|
+
Resolution priority at runtime: **`fetchXml` → `viewRef` → `entityLogicalName`**. With no prefill (a standalone launch) the tool opens empty.
|
|
283
|
+
|
|
284
|
+
### Returning a query to the caller
|
|
285
|
+
|
|
286
|
+
When FetchXML Studio is launched by another tool, a **Return FetchXML** button appears in the FetchXML toolbar. Clicking it returns the current query to the caller:
|
|
287
|
+
|
|
288
|
+
```json
|
|
289
|
+
{ "fetchXml": "<fetch>...</fetch>" }
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
The caller receives this as the resolved value of `launchTool(...)`. This is distinct from the host-injected "Return to [Caller]" banner, which simply navigates back and resolves the caller's promise with `null` (no data).
|
|
293
|
+
|
|
294
|
+
### Sending a query from another PPTB tool
|
|
295
|
+
|
|
296
|
+
To launch FetchXML Studio from your own PPTB tool with a pre-loaded query:
|
|
297
|
+
|
|
298
|
+
```typescript
|
|
299
|
+
const result = await window.toolboxAPI.invocation.launchTool(
|
|
300
|
+
"@mohsinonxrm/pptb-fetchxml-studio",
|
|
301
|
+
{ fetchXml: "<fetch><entity name=\"account\"><attribute name=\"name\"/></entity></fetch>" },
|
|
302
|
+
{ primaryConnectionId: connection?.id ?? null },
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
// If the user clicks "Return FetchXML", result is { fetchXml }.
|
|
306
|
+
// If they close the window or click the host's back banner, result is null.
|
|
307
|
+
const editedFetchXml = (result as { fetchXml?: string } | null)?.fetchXml;
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Sending a query to another tool (Send to Tool)
|
|
311
|
+
|
|
312
|
+
FetchXML Studio discovers send targets automatically — no configuration needed. It calls the host capability registry (`toolboxAPI.invocation.findToolsByCapability("fetchxml")`) to find installed tools that declare the `fetchxml` capability in their own `pptb.config.json`, and lists them in a **Send to Tool** button (a single button for one match, a dropdown picker for several). The button is hidden when no other `fetchxml`-capable tools are installed, or on hosts that don't support capability discovery.
|
|
313
|
+
|
|
314
|
+
The launch is one-way (`noReturn: true`) — FetchXML Studio hands the current query off and does not wait for data back. Any tool that wants to appear here only needs to declare:
|
|
315
|
+
|
|
316
|
+
```json
|
|
317
|
+
{ "invocation": { "version": "1.0.0", "capabilities": ["fetchxml"], "prefill": { "properties": { "fetchXml": { "type": "string" } } } } }
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
256
322
|
## 🤝 Contributing
|
|
257
323
|
|
|
258
324
|
Contributions are welcome! Please feel free to submit a Pull Request.
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Reporting a Vulnerability
|
|
4
|
+
|
|
5
|
+
Please do **not** open a public issue.
|
|
6
|
+
Use GitHub Security Advisories: <https://github.com/mohsinonxrm/pptb-mxrm-fetchxml-studio/security/advisories/new>
|
|
7
|
+
|
|
8
|
+
## Scope
|
|
9
|
+
|
|
10
|
+
- Authentication flows
|
|
11
|
+
- Token handling
|
|
12
|
+
- Dataverse request logging
|
|
13
|
+
- Dependency vulnerabilities
|