|
| 1 | +# CLI Binary Resolution (`pa` preferred, `power-apps` fallback) |
| 2 | + |
| 3 | +**This file is the single source of truth for which CLI binary to run and how to translate commands.** Every skill that runs a Power Apps CLI command MUST resolve the binary using the algorithm below **before** running any command, and MUST author commands in the canonical grouped **`pa`** form (see the mapping table). |
| 4 | + |
| 5 | +--- |
| 6 | + |
| 7 | +## Why two binaries |
| 8 | + |
| 9 | +`@microsoft/power-apps-cli` ships two executables from the **same package**: |
| 10 | + |
| 11 | +| Binary | Syntax | Example | |
| 12 | +| ------------ | ------- | ------------------------------------------ | |
| 13 | +| `pa` | grouped | `pa app add data-source --connector ...` | |
| 14 | +| `power-apps` | flat | `power-apps add-data-source -a ...` | |
| 15 | + |
| 16 | +Both are installed together, so a project's `node_modules/.bin/pa` shim exists **only if** the installed CLI version is new enough to include the grouped `pa` binary. Older projects have only `power-apps`. We therefore **prefer `pa`** and **fall back to `power-apps`**. |
| 17 | + |
| 18 | +**Two things differ between the binaries — the verb structure AND some flags:** |
| 19 | + |
| 20 | +1. **Verb structure** — grouped noun-verb (`pa app push`) vs flat (`power-apps push`). See the command mapping table. |
| 21 | +2. **Flag renames** — the grouped `pa` surface renames several customer-facing selector flags and **drops their short aliases** (the "Phase 2" `grouped_flag_renames` mechanism, now live). The flat `power-apps` surface keeps the original flags byte-identical. See the flag mapping table. |
| 22 | + |
| 23 | +When translating a canonical `pa` command to flat `power-apps`, you must convert **both** the verb path and any renamed flags. |
| 24 | + |
| 25 | +--- |
| 26 | + |
| 27 | +## Resolution algorithm (run once per session, then cache) |
| 28 | + |
| 29 | +Resolve from the **project root** (the directory containing `package.json` / `power.config.json`): |
| 30 | + |
| 31 | +```bash |
| 32 | +# Prefer the grouped `pa` binary; fall back to flat `power-apps`. |
| 33 | +# --no-install is REQUIRED: it stops npx from silently fetching a remote |
| 34 | +# package named `pa`/`power-apps` from the registry if no local shim exists. |
| 35 | +# Probe both the extensionless shim (bash/sh) and the `.cmd` shim that |
| 36 | +# package managers create on Windows, so a valid install is never missed. |
| 37 | +if [ -e node_modules/.bin/pa ] || [ -e node_modules/.bin/pa.cmd ]; then |
| 38 | + PA="npx --no-install pa" # grouped syntax → use the "pa" column below |
| 39 | + PA_KIND="pa" |
| 40 | +elif [ -e node_modules/.bin/power-apps ] || [ -e node_modules/.bin/power-apps.cmd ]; then |
| 41 | + PA="npx --no-install power-apps" # flat syntax → translate via the mapping table |
| 42 | + PA_KIND="power-apps" |
| 43 | +else |
| 44 | + # Neither shim present → the CLI is not installed yet. |
| 45 | + # Run `npm install` in the project root (per the normal scaffold flow), then re-probe. |
| 46 | + PA="" |
| 47 | + PA_KIND="none" |
| 48 | +fi |
| 49 | +``` |
| 50 | + |
| 51 | +Rules: |
| 52 | + |
| 53 | +1. **Probe by file presence only** — do not pin or parse a version. A shim (`.bin/pa` or, on Windows, `.bin/pa.cmd`) existing == the grouped binary is available. This is deterministic and cheaper than spawning `--version`. Always check the `.cmd` variant too: npm/pnpm/yarn/bun create `pa.cmd`/`power-apps.cmd` on Windows and an extensionless-only probe would misclassify a valid install as `none`. |
| 54 | +2. **Always use `npx --no-install`.** Never run a bare `npx pa ...`: if the local shim is missing, npx would try to download and execute an unrelated remote package named `pa`. `--no-install` fails closed instead. |
| 55 | +3. **Cache the result** in the project memory bank (`CLI Binary` row — see `memory-bank.md`) so subsequent skills/commands in the session don't re-probe. Re-probe only after an `npm install` that could have changed the installed CLI. |
| 56 | +4. **`none` → install first.** If neither shim exists, the CLI isn't installed; run the project's `npm install` (already part of the scaffold flow) and re-probe before running any command. |
| 57 | + |
| 58 | +--- |
| 59 | + |
| 60 | +## Authoring rule for skills |
| 61 | + |
| 62 | +- **Author every command in the canonical grouped `pa` form** (the left/`pa` column below), using the **renamed `pa` flags** from the flag mapping table, e.g. `pa app push`, `pa app add data-source --connector shared_office365 -c <conn-id>`. |
| 63 | +- Substitute the resolved `$PA` prefix (which already contains `npx --no-install`) for the binary at run time. When `PA_KIND=pa`, run the canonical command as-is: `$PA app push` → `npx --no-install pa app push`. When `PA_KIND=power-apps`, translate the verb path (and renamed flags) per the next rule before running: `$PA push` → `npx --no-install power-apps push`. |
| 64 | +- **If `PA_KIND` is `power-apps`, translate each grouped command to its flat equivalent before running it — convert BOTH the verb path AND any renamed flags.** The flat binary does **not** understand the grouped noun-verb form (`power-apps app push` is invalid — it must become `power-apps push`), and it does **not** accept the renamed long flags (`--connector` must become `--api-id`/`-a`, `--table` must become `--resource-name`/`-t`, etc.). |
| 65 | +- **Most flags are unchanged** — only the selector flags in the flag mapping table are renamed on `pa`. Connection ID (`-c`), dataset (`-d`), environment (`-e`), and display name (`-n` on `init`/`connection create`) are identical on both binaries. |
| 66 | + |
| 67 | +--- |
| 68 | + |
| 69 | +## Command mapping table (grouped `pa` ↔ flat `power-apps`) |
| 70 | + |
| 71 | +| Operation | Canonical (`pa`) | Flat (`power-apps`) | |
| 72 | +| ------------------------ | --------------------------------- | --------------------------------- | |
| 73 | +| Initialize project | `pa app init` | `power-apps init` | |
| 74 | +| Deploy / push | `pa app push` | `power-apps push` | |
| 75 | +| Local dev server | `pa app run` | `power-apps run` | |
| 76 | +| List code apps | `pa app list` | `power-apps list-codeapps` | |
| 77 | +| Add data source | `pa app add data-source` | `power-apps add-data-source` | |
| 78 | +| Add Dataverse API | `pa app add dataverse-api` | `power-apps add-dataverse-api` | |
| 79 | +| Add flow | `pa app add flow` | `power-apps add-flow` | |
| 80 | +| Remove data source | `pa app remove data-source` | `power-apps delete-data-source` | |
| 81 | +| Remove flow | `pa app remove flow` | `power-apps remove-flow` | |
| 82 | +| Refresh data source | `pa app refresh data-source` | `power-apps refresh-data-source` | |
| 83 | +| Find Dataverse API | `pa app find-dataverse-api` | `power-apps find-dataverse-api` | |
| 84 | +| List environment vars | `pa app list-environment-variables` | `power-apps list-environment-variables` | |
| 85 | +| List flows | `pa app list-flows` | `power-apps list-flows` | |
| 86 | +| List connections | `pa connection list` | `power-apps list-connections` | |
| 87 | +| List connection refs | `pa connection list-references` | `power-apps list-connection-references` | |
| 88 | +| Create connection | `pa connection create` | `power-apps create-connection` | |
| 89 | +| List connectors | `pa connector list` | `power-apps list-connectors` | |
| 90 | +| List datasets | `pa connector list-datasets` | `power-apps list-datasets` | |
| 91 | +| List tables | `pa connector list-tables` | `power-apps list-tables` | |
| 92 | +| List stored procedures | `pa connector list-procedures` | `power-apps list-sqlStoredProcedures` | |
| 93 | +| Sign in | `pa auth login` | `power-apps login` | |
| 94 | +| Sign out | `pa auth logout` | `power-apps logout` | |
| 95 | +| Auth status | `pa auth status` | `power-apps auth-status` | |
| 96 | +| Switch account | `pa auth switch` | `power-apps auth-switch` | |
| 97 | +| Telemetry enable | `pa telemetry enable` | `power-apps telemetry --enable` | |
| 98 | +| Telemetry disable | `pa telemetry disable` | `power-apps telemetry --disable` | |
| 99 | +| Telemetry status | `pa telemetry status` | `power-apps telemetry --show-settings` | |
| 100 | + |
| 101 | +> **Note:** the operations above differ only in verb structure. Renamed **flags** (which apply to several of these operations) are listed separately in the flag mapping table below. |
| 102 | +
|
| 103 | +--- |
| 104 | + |
| 105 | +## Flag mapping table (grouped `pa` ↔ flat `power-apps`) |
| 106 | + |
| 107 | +The grouped `pa` surface renames these customer-facing selector flags and **drops their short aliases**. The flat `power-apps` surface keeps the original flag names and aliases. All other flags are identical on both binaries. |
| 108 | + |
| 109 | +| Selector | Canonical (`pa`) | Flat (`power-apps`) | Used by | |
| 110 | +| ----------------------- | -------------------- | ---------------------------------- | --------------------------------------------------- | |
| 111 | +| Connector / API | `--connector` | `--api-id` (alias `-a`) | `add data-source`, `connector list-*`, `connection create` | |
| 112 | +| Table / resource | `--table` | `--resource-name` (alias `-t`) | `add data-source` | |
| 113 | +| Data source name | `--name` | `--data-source-name` (alias `-n`) | `add data-source`, `refresh data-source` | |
| 114 | +| SQL stored procedure | `--procedure` | `--sql-stored-procedure` (alias `-sp`) | `connector list-procedures` | |
| 115 | +| Connection reference | `--connection-ref` | `--connection-ref` (alias `-cr`) | `add data-source` (Dataverse) — **alias `-cr` dropped on `pa`, long flag unchanged** | |
| 116 | + |
| 117 | +**Unchanged on both binaries** (do NOT rewrite these): `--connection-id`/`-c`, `--dataset`/`-d`, `--environment-id`/`-e`, `--display-name`/`-n` (on `init` and `connection create`), `--solution-id`, `--search`, `--cloud`. |
| 118 | + |
| 119 | +> ⚠️ **`-n` is context-dependent.** On `add data-source`/`refresh data-source`, `-n` is the (renamed) `data-source-name` → `--name`. On `init` and `connection create`, `-n` is `display-name`, which is **not** renamed. Translate based on the verb, not the letter. |
| 120 | +
|
| 121 | +--- |
| 122 | + |
| 123 | +## `npx` prefix note |
| 124 | + |
| 125 | +Skill examples elsewhere in the plugin are written in the **canonical grouped `pa` form** (e.g. `pa app push`). These are authoring shorthand — read them as the **canonical operation**, resolve `$PA`, and run the resolved form with the required `npx --no-install` prefix: |
| 126 | + |
| 127 | +- resolved `pa` → `npx --no-install pa <noun> <verb> ...` |
| 128 | +- resolved `power-apps` → translate via the mapping table, then `npx --no-install power-apps <verb> ...` |
0 commit comments