add-connector ยท diff

git:20261007.8ed5100 to git:20261008.c6994b2

120 added, 42 removed. Audit A to A.

---
name: add-connector
description: Use when adding a Power Platform connector to an Expo/React Native Power Apps mobile app and no dedicated mobile connector skill exists.
user-invocable: true
allowed-tools: Read, Edit, Write, Grep, Glob, Bash, AskUserQuestion, Skill
model: sonnet
---
> **Plugin check**: Run `node "${PLUGIN_ROOT}/scripts/check-version.js"` - if it outputs a message, show it to the user before proceeding.
**๐Ÿ“‹ Shared instructions: [shared-instructions.md](${PLUGIN_ROOT}/shared/shared-instructions.md)** | **Connector reference: [connector-reference.md](${PLUGIN_ROOT}/shared/connector-reference.md)** โ€” read both first.
# Add Connector (Generic)
+ **App root:** before any project read or command, execute
+ [app-working-directory.md](${PLUGIN_ROOT}/shared/references/app-working-directory.md).
+ Use its resolved absolute `working_dir` for every shell call and file tool,
+ including referenced commands and delegated skills; never inherit a prior `cd`.
+
+ **Invocation scope:** follow [Data-source invocation scope](../../shared/shared-instructions.md#data-source-invocation-scope)
+ before the workflow below. This skill owns connector bindings and generated
+ services, not a full-app plan or screen implementation.
+
+ For a standalone request, approve the current data-source delta before each
+ mutation: the exact connector, environment, binding, and dataset/table or
+ procedure as applicable. Connection creation needs explicit approval too.
+ An approved child reuses only its owner's current scope; a missing choice may
+ be resolved read-only, but a changed scope returns to that owner.
+ For `--plan-only` or a planning-phase handoff, return the proposed bindings and
+ unresolved choices before connection creation or `pa app add data-source`.
+ Do not update the app plan, memory-bank, configuration, or generated files on
+ that path; missing discovery access is not permission to create a connection.
+
+ Action connectors do not imply Dataverse Data Model changes.
+
+ **Cloud flows are not supported by mobile skills.** For a request to add,
+ refresh, invoke, or remove a cloud-flow binding, report
+ `BLOCKED: cloud-flow integration is not supported` and return before discovery
+ or mutation. Do not treat a flow as a connector data source.
+
+ **Removal branch:** after resolving invocation scope, if `--remove` or the approved scope
+ requests removal, execute
+ [data-source-removal.md](../../shared/references/data-source-removal.md) and return.
+ Do not run Steps 1-6, connection creation, or `add-data-source` for a removal.
+
+ **Refresh branch:** after resolving invocation scope, `--refresh` or an approved retained-source
+ refresh executes [Refresh a retained source](../../shared/references/data-source-removal.md#refresh-a-retained-source)
+ and returns before Steps 1-6. Preserve the exact `--data-source-name` and approved
+ binding identity; do not create connections or run `add-data-source`.
+
Fallback skill for any connector not covered by a dedicated `/add-*` skill. For common connectors, prefer the dedicated skills:
- `/add-dataverse` โ€” Dataverse tables
- `/add-sharepoint` โ€” SharePoint Online
(More dedicated skills will land in v1: `/add-teams`, `/add-excel`, `/add-onedrive`, `/add-azuredevops`, `/add-office365`.)
The native host runtime (`@microsoft/power-apps-native-host`) handles connector routing, connection resolution, and OAuth consent through `PowerAppsProvider` in `app/_layout.tsx` โ€” no separate executor wiring is needed.
## Workflow
1. Check Memory Bank โ†’ 2. Identify Connector โ†’ 3. Add Connector โ†’ 4. Inspect & Configure โ†’ 5. Build โ†’ 6. Update Memory Bank
---
### Step 1 โ€” Check Memory Bank
**Telemetry checkpoint: `validate_connector_project`**
Check for `memory-bank.md` per [shared-instructions.md](${PLUGIN_ROOT}/shared/shared-instructions.md).
Also confirm we're inside a Power Apps mobile app:
```bash
- test -f power.config.json && test -f app.config.js
+ cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
+ if [ ! -f power.config.json ] || [ ! -f app.config.js ]; then
+ echo "BLOCKED: working_dir is not an initialized app" >&2
+ exit 1
+ fi
```
If either is missing, instruct the user to run `/create-mobile-app` first and stop.
### Step 2 โ€” Identify Connector
**Telemetry checkpoint: `resolve_connector_request`**
**If `$ARGUMENTS` is provided or the caller already specified the connector**, use it directly and skip the question below.
Otherwise, ask the user which connector they want to add. Browse available connectors: [Connector Reference](https://learn.microsoft.com/en-us/connectors/connector-reference/).
- **Before proceeding, check if the connector has a dedicated skill. If it does, delegate immediately and STOP:**
+ Classify the requested operation before matching the delegation table. Dataverse
+ actions/functions follow the discovery-only branch below directly, skipping
+ connection lookup and data-source generation, never the table CRUD workflow.
+ If the operation is ambiguous, ask before delegating.
+ Use aliases only for routing; pass the exact discovered API ID to CLI commands.
+ **Dataverse actions/functions: discover and return here.**
+
+ ```bash
+ cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
+ $PA app find-dataverse-api --search '<operation-name>' --json
+ ```
+
+ Surface the matching metadata and STOP this leaf with a clear note that this
+ plugin adds Dataverse table CRUD, not actions/functions. Do not enter Step 3,
+ invoke `/list-connections`, or generate a table service on this branch.
+ If the user actually needs table CRUD, use the delegation table below.
+
+ **Then check if this operation has a dedicated skill. If it does, delegate and STOP:**
+
| Connector API name | Delegate to |
| ----------------------- | ------------------ |
- | `sharepointonline` | `/add-sharepoint` |
- | `commondataservice` | `/add-dataverse` |
+ | `sharepointonline`, `shared_sharepointonline` | `/add-sharepoint` |
+ | `dataverse`, `commondataservice`, `shared_commondataservice`, `commondataserviceforapps`, `shared_commondataserviceforapps` (table CRUD only) | `/add-dataverse` |
- Invoke the appropriate skill with the same `$ARGUMENTS` and **do not continue this skill's workflow**.
+ Invoke the appropriate skill with the same `$ARGUMENTS`, absolute `working_dir`,
+ current request, owner/phase/scope, and proposal-only mode. **Do not continue this
+ skill's workflow** or infer execution approval from this routing decision.
Common connector API names:
- `sharepointonline`, `teams`, `excelonlinebusiness`, `onedriveforbusiness`
- `azuredevops`, `azureblob`, `azurequeues`
- `office365`, `office365users`, `office365groups`
- `sql`, `commondataservice`
- **Cloud flows are supported by the Power Apps CLI, but they are not connector data sources.** If the user wants to invoke an existing Power Automate cloud flow from the app, use the flow-specific commands instead of `pa app add data-source`:
-
- ```bash
- $PA app list-flows --search '<flow-name-or-keyword>' --json
- $PA app add flow --flow-id <flow-guid> --non-interactive
- ```
-
- To remove a flow later (only when the user asks; `pa` needs `--force` for a non-interactive removal):
-
- ```bash
- $PA app remove flow --flow-id <flow-guid> --force --non-interactive
- ```
-
- After `pa app add flow`, continue at Step 4 and inspect the generated service/model files the same way as connector data sources.
-
### Step 3 โ€” Add Connector
**Telemetry checkpoint: `generate_connector_data_source`**
- **First, get the connection ID or connection reference** (see [connector-reference.md](${PLUGIN_ROOT}/shared/connector-reference.md)):
+ **First, preserve or resolve the connection binding** using
+ [connector-reference.md](../../shared/connector-reference.md#step-1--get-a-connection):
- Run the `/list-connections` skill with the connector API ID (for example `shared_office365users`). Capture the exact `connectionId` from `pa connection create`, or the `connectionRef` from `pa connection list-references` if the caller is solution-aware. If creation cannot complete in the CLI, direct the user to create one using the environment-specific Connections URL โ€” construct it from the active environment ID in context (from `power.config.json` `environmentId` or a prior step):
+ - Supplied `--connection-id` (or approved caller `connectionId`): reuse that exact
+ ID for the confirmed connector/environment; skip `/list-connections` and creation.
+ - Supplied `--connection-ref` (or approved caller `connectionRef`): preserve that
+ reference for generation; skip `/list-connections` and creation. Do not replace
+ it with a newly selected ID.
+ - Missing binding only: invoke `/list-connections` with the connector API ID
+ and current scoped context to resolve the missing value. Conflicting, blank,
+ or ambiguous supplied values return to the owner instead of creating a fallback.
+
+ The commands below show the connection-ID path. For a reference binding,
+ replace `--connection-id <connectionId>` with
+ `--connection-ref '<connectionRef>'` on `add-data-source` only. Reuse supplied
+ dataset/table/procedure choices and skip their discovery. If discovery is still
+ needed and requires an ID, obtain the backing ID for the approved reference or
+ the missing concrete choices; do not create another connection or pass an
+ unsupported reference flag to a picker command.
+
+ If creation was needed but cannot complete in the CLI, direct the user to the
+ environment-specific Connections URL from `power.config.json` `environmentId`:
`https://make.powerapps.com/environments/<environment-id>/connections` โ†’ **+ New connection** โ†’ search for the connector โ†’ Create.
**Classify the connector before running `pa app add data-source`:**
| Connector shape | Examples | Required discovery | Add command |
| --- | --- | --- | --- |
| Action-style connector | Teams, Office 365 Users, Outlook, Azure DevOps | None after connection lookup | `$PA app add data-source --connector <apiId> --connection-id <connectionId>` |
| Table-based connector | Excel Online, OneDrive for Business, Azure Blob, SQL, SharePoint if not delegated | `connection list-datasets`, then `connection list-tables` | `$PA app add data-source --connector <apiId> --connection-id <connectionId> --dataset '<dataset>' --table '<table>'` |
| SQL stored procedure | SQL Server | `connection list-datasets`, then `connection list-procedures` if needed | `$PA app add data-source --connector shared_sql --connection-id <connectionId> --dataset '<database>' --procedure '<procedure>'` |
**For action-style connectors, print before starting:**
> "โ†’ Running `pa app add data-source` for <connector>. ~10โ€“30 seconds (writes generated services + connector schemas)."
Then run:
```bash
+ cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
$PA app add data-source --connector <apiId> --connection-id <connectionId>
```
**For table-based connectors, discover datasets and tables first:**
```bash
+ cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
$PA connection list-datasets --connector <apiId> --connection-id <connectionId> --json
$PA connection list-tables --connector <apiId> --connection-id <connectionId> --dataset '<dataset>' --json
```
- Present the datasets/tables to the user if they did not specify them. Add one data source per selected table:
+ Present the datasets/tables to the user if they did not specify them. Approve
+ the exact selected bindings before generation, or reuse matching current owner
+ approval; proposal-only discovery returns without adding sources.
+ Add one data source per approved table:
```bash
+ cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
$PA app add data-source --connector <apiId> --connection-id <connectionId> --dataset '<dataset>' --table '<table>'
```
**For SQL stored procedures, discover procedures only when the user asks to invoke a stored procedure rather than a table:**
```bash
+ cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
$PA connection list-procedures --connection-id <connectionId> --dataset '<database>' --json
- $PA app add data-source --connector shared_sql --connection-id <connectionId> --dataset '<database>' --procedure '<procedure>'
```
- **For Dataverse actions/functions rather than tables, discovery is available but this plugin only adds Dataverse table CRUD:**
+ Approve the exact procedure binding before generation if it was not already in
+ the current approved scope; proposal-only discovery returns without adding it.
```bash
- $PA app find-dataverse-api --search '<operation-name>' --json
+ cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
+ $PA app add data-source --connector shared_sql --connection-id <connectionId> --dataset '<database>' --procedure '<procedure>'
```
- Surface the matching operation metadata and STOP with a clear note that this plugin can add Dataverse table CRUD through `/add-dataverse`, but does not add Dataverse actions/functions.
-
- If the user actually needs Dataverse table CRUD, stop and delegate to `/add-dataverse`; do not add Dataverse tables from this generic connector skill.
-
**Parameter reference:**
- `--connector` โ€” connector API ID (often `shared_<connector>`, e.g., `shared_office365users`). Use the exact value provided by the caller or connector docs.
- `--connection-id` / `-c` โ€” required for non-Dataverse connectors unless using `--connection-ref`. Get from `pa connection create`, the maker portal, or caller context.
- `--connection-ref` โ€” optional connection reference name when adding into a solution-aware app.
- `--dataset` / `-d` โ€” required for table-based datasources (for example SharePoint site URL, Excel file/location, SQL database).
- `--table` โ€” table/list/resource name for table-based datasources.
- `--procedure` โ€” SQL stored procedure name when adding a stored procedure instead of a table.
- `--non-interactive` โ€” use only on commands whose required options are fully supplied and whose implementation supports non-interactive omission of optional prompts. Do not add `--environment-id` to app-root verbs once `power.config.json` exists.
- `--solution-id` / `-s` โ€” optional solution identifier when the data source should be added to a specific solution.
### Step 4 โ€” Inspect & Configure
After adding, inspect the generated files. **Generated service files can be very large** โ€” use `Grep` to find specific methods instead of reading the entire file:
```
- Grep pattern="async \w+" path="src/generated/services/<Connector>Service.ts"
+ Grep pattern="async \w+" path="<working_dir>/src/generated/services/<Connector>Service.ts"
```
Files to check:
- `src/generated/services/<Connector>Service.ts` โ€” available operations and their parameters
- `src/generated/models/<Connector>Model.ts` โ€” TypeScript interfaces (if generated)
- `.power/schemas/<connector>/` โ€” connector schema and configuration
For each method the user needs:
1. Grep for the method name to find its signature
2. Read just that method's section (use `offset` and `limit` parameters on Read)
3. Identify required vs optional parameters and response type
- Help the user write code using the generated service methods.
+ Return the needed method signatures and usage guidance to the user or current
+ owner. Do not change screens or launch another app workflow. Report generated
+ service availability separately from consumer integration.
### Step 5 โ€” Build
**Telemetry checkpoint: `validate_connector_integration`**
**Print before starting:**
> "โ†’ Regenerating connector schemas + running tsc to verify the new connector wires in cleanly (~10โ€“20 seconds)."
`pa app add data-source` (Step 3) wrote new files into `.power/schemas/<connector>/`. The `connectorSchemas.ts` consumed by `app/_layout.tsx` is now stale โ€” regenerate it before type-checking so the new connector is wired into the runtime schema map:
```bash
+ cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
npm run generate-schemas
npx --no-install tsc --noEmit
```
- Fix TypeScript errors before proceeding. Common gotcha: the new generated service may import a peer dependency you don't have installed yet โ€” if so, `npx --no-install expo install <missing-package>` (NOT plain `npm install`, so versions stay Expo-compatible).
+ Fix TypeScript errors before proceeding. If a generated service requires a missing
+ dependency, inspect its package contents before choosing a repair. Do not install
+ native packages absent from the template. Return a JS-only dependency requirement
+ to the orchestrator for the approved exact-version
+ [JavaScript dependency plan](../../shared/references/javascript-dependency-planning.md);
+ for a standalone call obtain that approval before installation. Do not
+ install an unplanned package merely to silence TypeScript.
Do NOT deploy yet โ€” that's `/deploy`'s job after all data sources are added.
### Step 6 โ€” Update Memory Bank
Update `memory-bank.md` with: connector added, configured operations, build status.
- ## Remove a data source or flow
-
- If the user asks to remove a connector/table/stored procedure that this skill added, use the matching Power Apps CLI command with explicit arguments. The user's request is the confirmation: `pa` refuses a non-interactive removal without `--force` (drop `--force` on `power-apps`-only projects โ€” see [cli-binary.md](${PLUGIN_ROOT}/shared/cli-binary.md)):
+ ## Remove a data source
- ```bash
- $PA app remove data-source --connector <apiId> --name '<data-source-or-table-name>' --force --non-interactive
- $PA app remove data-source --connector shared_sql --name '<procedure>' --procedure '<procedure>' --force --non-interactive
- $PA app remove flow --flow-id <flow-guid> --force --non-interactive
- ```
+ Apply the data-source invocation scope first for removals too. Identify consuming
+ screens/services before deleting a dependency. Standalone removal must stop if
+ it would leave broken consumers; report the required consumer work separately
+ rather than automatically invoking another workflow.
- Then run `npm run generate-schemas` and `npx --no-install tsc --noEmit` before reporting success.
+ Read and execute
+ [data-source-removal.md](../../shared/references/data-source-removal.md) for the
+ supported command, scope preflight, generated/config cleanup checks, and
+ inventory reconciliation. This also covers sources originally added outside
+ this skill; use the actual registered identity rather than assuming its name.
## Runtime connector handling
The native host runtime handles all connector routing automatically via `PowerAppsProvider` in `app/_layout.tsx`. When a screen calls a generated service method:
1. `PowerAppsProvider` resolves the connection from `connectionReferences` in `power.config.json`
2. If the connection requires OAuth consent, `ConnectionSetupScreen` is shown automatically
3. `NativePowerAppsBridge` dispatches the call with the correct auth token
No separate executor or provider wiring is needed โ€” Dataverse and non-Dataverse connectors use the same unified pipeline.
## Notes
- Generated files in `src/generated/` are produced directly by `pa app add data-source`. Differences in behavior come from runtime wiring in this mobile plugin.
- This skill never modifies `app.config.js` or `playerConfig.ts` โ€” connector discovery is dynamic at runtime.