@luquimbo/bi-superpowers 1.0.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.
Files changed (193) hide show
  1. package/.claude-plugin/plugin.json +8 -0
  2. package/.mcp.json +25 -0
  3. package/AGENTS.md +244 -0
  4. package/CHANGELOG.md +265 -0
  5. package/LICENSE +21 -0
  6. package/README.md +211 -0
  7. package/bin/build-plugin.js +30 -0
  8. package/bin/cli.js +1064 -0
  9. package/bin/commands/add.js +533 -0
  10. package/bin/commands/add.test.js +77 -0
  11. package/bin/commands/build-desktop.js +166 -0
  12. package/bin/commands/changelog.js +443 -0
  13. package/bin/commands/diff.js +325 -0
  14. package/bin/commands/lint.js +419 -0
  15. package/bin/commands/lint.test.js +103 -0
  16. package/bin/commands/mcp-setup.js +246 -0
  17. package/bin/commands/pull.js +287 -0
  18. package/bin/commands/pull.test.js +36 -0
  19. package/bin/commands/push.js +231 -0
  20. package/bin/commands/push.test.js +14 -0
  21. package/bin/commands/search.js +344 -0
  22. package/bin/commands/search.test.js +115 -0
  23. package/bin/commands/setup.js +545 -0
  24. package/bin/commands/setup.test.js +46 -0
  25. package/bin/commands/sync-profile.js +405 -0
  26. package/bin/commands/sync-profile.test.js +14 -0
  27. package/bin/commands/sync-source.js +418 -0
  28. package/bin/commands/sync-source.test.js +14 -0
  29. package/bin/commands/watch.js +206 -0
  30. package/bin/lib/generators/claude-plugin.js +266 -0
  31. package/bin/lib/generators/claude-plugin.test.js +110 -0
  32. package/bin/lib/generators/index.js +116 -0
  33. package/bin/lib/generators/shared.js +282 -0
  34. package/bin/lib/licensing/index.js +35 -0
  35. package/bin/lib/licensing/storage.js +364 -0
  36. package/bin/lib/licensing/storage.test.js +55 -0
  37. package/bin/lib/licensing/validator.js +213 -0
  38. package/bin/lib/licensing/validator.test.js +137 -0
  39. package/bin/lib/microsoft-mcp.js +176 -0
  40. package/bin/lib/microsoft-mcp.test.js +106 -0
  41. package/bin/lib/skills.js +84 -0
  42. package/bin/mcp/powerbi-modeling-launcher.js +38 -0
  43. package/bin/postinstall.js +44 -0
  44. package/bin/utils/errors.js +159 -0
  45. package/bin/utils/git.js +298 -0
  46. package/bin/utils/logger.js +142 -0
  47. package/bin/utils/mcp-detect.js +274 -0
  48. package/bin/utils/mcp-detect.test.js +105 -0
  49. package/bin/utils/pbix.js +305 -0
  50. package/bin/utils/pbix.test.js +37 -0
  51. package/bin/utils/profiles.js +312 -0
  52. package/bin/utils/projects.js +168 -0
  53. package/bin/utils/readline.js +206 -0
  54. package/bin/utils/readline.test.js +47 -0
  55. package/bin/utils/tui.js +314 -0
  56. package/bin/utils/tui.test.js +127 -0
  57. package/commands/contributions.md +265 -0
  58. package/commands/data-model-design.md +468 -0
  59. package/commands/dax-doctor.md +248 -0
  60. package/commands/fabric-scripts.md +452 -0
  61. package/commands/migration-assistant.md +290 -0
  62. package/commands/model-documenter.md +242 -0
  63. package/commands/pbi-connect.md +239 -0
  64. package/commands/project-kickoff.md +905 -0
  65. package/commands/report-layout.md +296 -0
  66. package/commands/rls-design.md +533 -0
  67. package/commands/theme-tweaker.md +624 -0
  68. package/config.example.json +23 -0
  69. package/config.json +23 -0
  70. package/desktop-extension/manifest.json +37 -0
  71. package/desktop-extension/package.json +10 -0
  72. package/desktop-extension/server.js +95 -0
  73. package/docs/openrouter-free-models.md +92 -0
  74. package/library/examples/README.md +151 -0
  75. package/library/examples/finance-reporting/README.md +351 -0
  76. package/library/examples/finance-reporting/data-model.md +267 -0
  77. package/library/examples/finance-reporting/measures.dax +557 -0
  78. package/library/examples/hr-analytics/README.md +371 -0
  79. package/library/examples/hr-analytics/data-model.md +315 -0
  80. package/library/examples/hr-analytics/measures.dax +460 -0
  81. package/library/examples/marketing-analytics/README.md +37 -0
  82. package/library/examples/marketing-analytics/data-model.md +62 -0
  83. package/library/examples/marketing-analytics/measures.dax +110 -0
  84. package/library/examples/retail-analytics/README.md +439 -0
  85. package/library/examples/retail-analytics/data-model.md +288 -0
  86. package/library/examples/retail-analytics/measures.dax +481 -0
  87. package/library/examples/supply-chain/README.md +37 -0
  88. package/library/examples/supply-chain/data-model.md +69 -0
  89. package/library/examples/supply-chain/measures.dax +77 -0
  90. package/library/examples/udf-library/README.md +228 -0
  91. package/library/examples/udf-library/functions.dax +571 -0
  92. package/library/snippets/dax/README.md +292 -0
  93. package/library/snippets/dax/business-domains.md +576 -0
  94. package/library/snippets/dax/calculate-patterns.md +276 -0
  95. package/library/snippets/dax/calculation-groups.md +489 -0
  96. package/library/snippets/dax/error-handling.md +495 -0
  97. package/library/snippets/dax/iterators-and-aggregations.md +474 -0
  98. package/library/snippets/dax/kpis-and-metrics.md +293 -0
  99. package/library/snippets/dax/rankings-and-topn.md +235 -0
  100. package/library/snippets/dax/security-patterns.md +413 -0
  101. package/library/snippets/dax/text-and-formatting.md +316 -0
  102. package/library/snippets/dax/time-intelligence.md +196 -0
  103. package/library/snippets/dax/user-defined-functions.md +477 -0
  104. package/library/snippets/dax/virtual-tables.md +546 -0
  105. package/library/snippets/excel-formulas/README.md +84 -0
  106. package/library/snippets/excel-formulas/aggregations.md +330 -0
  107. package/library/snippets/excel-formulas/dates-and-times.md +361 -0
  108. package/library/snippets/excel-formulas/dynamic-arrays.md +314 -0
  109. package/library/snippets/excel-formulas/lookups.md +169 -0
  110. package/library/snippets/excel-formulas/text-functions.md +363 -0
  111. package/library/snippets/governance/naming-conventions.md +97 -0
  112. package/library/snippets/governance/review-checklists.md +107 -0
  113. package/library/snippets/power-query/README.md +389 -0
  114. package/library/snippets/power-query/api-integration.md +707 -0
  115. package/library/snippets/power-query/connections.md +434 -0
  116. package/library/snippets/power-query/data-cleaning.md +298 -0
  117. package/library/snippets/power-query/error-handling.md +526 -0
  118. package/library/snippets/power-query/parameters.md +350 -0
  119. package/library/snippets/power-query/performance.md +506 -0
  120. package/library/snippets/power-query/transformations.md +330 -0
  121. package/library/snippets/report-design/accessibility.md +78 -0
  122. package/library/snippets/report-design/chart-selection.md +54 -0
  123. package/library/snippets/report-design/layout-patterns.md +87 -0
  124. package/library/templates/data-models/README.md +93 -0
  125. package/library/templates/data-models/finance-model.md +627 -0
  126. package/library/templates/data-models/retail-star-schema.md +473 -0
  127. package/library/templates/excel/README.md +83 -0
  128. package/library/templates/excel/budget-tracker.md +432 -0
  129. package/library/templates/excel/data-entry-form.md +533 -0
  130. package/library/templates/power-bi/README.md +72 -0
  131. package/library/templates/power-bi/finance-report.md +449 -0
  132. package/library/templates/power-bi/kpi-scorecard.md +461 -0
  133. package/library/templates/power-bi/sales-dashboard.md +281 -0
  134. package/library/themes/excel/README.md +436 -0
  135. package/library/themes/power-bi/README.md +271 -0
  136. package/library/themes/power-bi/accessible.json +307 -0
  137. package/library/themes/power-bi/bi-superpowers-default.json +858 -0
  138. package/library/themes/power-bi/corporate-blue.json +291 -0
  139. package/library/themes/power-bi/dark-mode.json +291 -0
  140. package/library/themes/power-bi/minimal.json +292 -0
  141. package/library/themes/power-bi/print-friendly.json +309 -0
  142. package/package.json +93 -0
  143. package/skills/contributions/SKILL.md +267 -0
  144. package/skills/data-model-design/SKILL.md +470 -0
  145. package/skills/data-modeling/SKILL.md +254 -0
  146. package/skills/data-quality/SKILL.md +664 -0
  147. package/skills/dax/SKILL.md +708 -0
  148. package/skills/dax-doctor/SKILL.md +250 -0
  149. package/skills/dax-udf/SKILL.md +489 -0
  150. package/skills/deployment/SKILL.md +320 -0
  151. package/skills/excel-formulas/SKILL.md +463 -0
  152. package/skills/fabric-scripts/SKILL.md +454 -0
  153. package/skills/fast-standard/SKILL.md +509 -0
  154. package/skills/governance/SKILL.md +205 -0
  155. package/skills/migration-assistant/SKILL.md +292 -0
  156. package/skills/model-documenter/SKILL.md +244 -0
  157. package/skills/pbi-connect/SKILL.md +241 -0
  158. package/skills/power-query/SKILL.md +406 -0
  159. package/skills/project-kickoff/SKILL.md +907 -0
  160. package/skills/query-performance/SKILL.md +480 -0
  161. package/skills/report-design/SKILL.md +207 -0
  162. package/skills/report-layout/SKILL.md +298 -0
  163. package/skills/rls-design/SKILL.md +535 -0
  164. package/skills/semantic-model/SKILL.md +237 -0
  165. package/skills/testing-validation/SKILL.md +643 -0
  166. package/skills/theme-tweaker/SKILL.md +626 -0
  167. package/src/content/base.md +237 -0
  168. package/src/content/mcp-requirements.json +69 -0
  169. package/src/content/routing.md +203 -0
  170. package/src/content/skills/contributions.md +259 -0
  171. package/src/content/skills/data-model-design.md +462 -0
  172. package/src/content/skills/data-modeling.md +246 -0
  173. package/src/content/skills/data-quality.md +656 -0
  174. package/src/content/skills/dax-doctor.md +242 -0
  175. package/src/content/skills/dax-udf.md +481 -0
  176. package/src/content/skills/dax.md +700 -0
  177. package/src/content/skills/deployment.md +312 -0
  178. package/src/content/skills/excel-formulas.md +455 -0
  179. package/src/content/skills/fabric-scripts.md +446 -0
  180. package/src/content/skills/fast-standard.md +501 -0
  181. package/src/content/skills/governance.md +197 -0
  182. package/src/content/skills/migration-assistant.md +284 -0
  183. package/src/content/skills/model-documenter.md +236 -0
  184. package/src/content/skills/pbi-connect.md +233 -0
  185. package/src/content/skills/power-query.md +398 -0
  186. package/src/content/skills/project-kickoff.md +899 -0
  187. package/src/content/skills/query-performance.md +472 -0
  188. package/src/content/skills/report-design.md +199 -0
  189. package/src/content/skills/report-layout.md +290 -0
  190. package/src/content/skills/rls-design.md +527 -0
  191. package/src/content/skills/semantic-model.md +229 -0
  192. package/src/content/skills/testing-validation.md +635 -0
  193. package/src/content/skills/theme-tweaker.md +618 -0
@@ -0,0 +1,241 @@
1
+ ---
2
+ name: "pbi-connect"
3
+ description: "Use when the user asks about Power BI MCP Connection Skill, especially phrases like \"connect Power BI\", \"modeling mcp\", \"Power BI Desktop\", \"conectar Power BI\", \"can't connect to Power BI\"."
4
+ version: "1.0.0"
5
+ ---
6
+
7
+ <!-- Generated by BI Agent Superpowers. Edit src/content/skills/pbi-connect.md instead. -->
8
+
9
+ # Power BI MCP Connection Skill
10
+
11
+ ## Trigger
12
+ Activate this skill when user mentions:
13
+ - "connect Power BI", "PBI connection", "MCP connection", "Power BI MCP"
14
+ - "modeling mcp", "remote mcp", "fabric mcp"
15
+ - "Power BI Desktop", "PBIP", "semantic model", "Fabric workspace"
16
+ - "conectar Power BI", "MCP de Power BI", "Fabric MCP"
17
+ - "can't connect to Power BI", "connection error", "MCP not working"
18
+
19
+ ## Identity
20
+ You are a **Power BI MCP Connection Specialist**. Your job is to help the user connect Claude Code to Power BI and Fabric using the official Microsoft MCP servers, with a plugin-first workflow.
21
+
22
+ ## MANDATORY RULES
23
+ 1. **PLUGIN-FIRST.** Prefer `.mcp.json` in the Claude Code plugin root.
24
+ 2. **OFFICIAL SERVERS ONLY.** Recommend `powerbi-remote`, `fabric-mcp-server`, and `powerbi-modeling-mcp`.
25
+ 3. **WINDOWS LIMITATION.** Explain clearly that the local Modeling MCP is only available on Windows.
26
+ 4. **NO PORT INVENTION.** Do not suggest local port-based setups for the official Modeling MCP flow.
27
+ 5. **ONE QUESTION AT A TIME.** Follow the wizard pattern.
28
+
29
+ ---
30
+
31
+ ## PHASE 0: Initial Triage
32
+
33
+ Start with:
34
+
35
+ ```text
36
+ POWER BI MCP CONNECTION
37
+ =======================
38
+
39
+ I'll help you connect Claude Code using the official Microsoft MCP servers.
40
+
41
+ What do you need?
42
+
43
+ 1. Connect to Power BI Desktop / PBIP on this machine
44
+ 2. Connect to a remote Power BI or Fabric workspace
45
+ 3. Verify that my plugin `.mcp.json` is configured correctly
46
+ ```
47
+
48
+ ---
49
+
50
+ ## PHASE 1: Local Modeling MCP (Windows)
51
+
52
+ If the user chooses option 1:
53
+
54
+ ```text
55
+ LOCAL MODELING MCP
56
+ ==================
57
+
58
+ This path uses Microsoft's official `powerbi-modeling-mcp` executable.
59
+
60
+ Before we continue:
61
+
62
+ 1. Are you on Windows?
63
+ 2. Did you install the "Power BI Modeling MCP" extension in VS Code or Cursor?
64
+ ```
65
+
66
+ ### If the user is on Windows and installed the extension
67
+
68
+ Guide them to:
69
+
70
+ 1. Run `bi-superpowers mcp-setup`
71
+ 2. Confirm `.mcp.json` contains `powerbi-modeling-mcp`
72
+ 3. Restart or refresh Claude Code
73
+
74
+ Use this explanation:
75
+
76
+ ```text
77
+ BI Agent Superpowers does not launch the Modeling MCP with `uvx`.
78
+ Instead, it uses a local wrapper that finds the official Microsoft executable
79
+ and starts it with `--start`.
80
+ ```
81
+
82
+ If the user wants a config example, show:
83
+
84
+ ```json
85
+ {
86
+ "powerbi-remote": {
87
+ "type": "http",
88
+ "url": "https://api.fabric.microsoft.com/v1/mcp/powerbi"
89
+ },
90
+ "fabric-mcp-server": {
91
+ "type": "stdio",
92
+ "command": "npx",
93
+ "args": ["-y", "@microsoft/fabric-mcp@latest", "server", "start", "--mode", "all"]
94
+ },
95
+ "powerbi-modeling-mcp": {
96
+ "type": "stdio",
97
+ "command": "node",
98
+ "args": ["${CLAUDE_PLUGIN_ROOT}/bin/mcp/powerbi-modeling-launcher.js"]
99
+ }
100
+ }
101
+ ```
102
+
103
+ ### If the user installed the executable manually
104
+
105
+ Tell them to set:
106
+
107
+ ```text
108
+ BI_SUPERPOWERS_POWERBI_MODELING_MCP_PATH
109
+ ```
110
+
111
+ Then re-run:
112
+
113
+ ```bash
114
+ super mcp-setup
115
+ ```
116
+
117
+ ### If the user is on macOS or Linux
118
+
119
+ Say:
120
+
121
+ ```text
122
+ The official local Power BI Modeling MCP is only available on Windows.
123
+ You can still work with:
124
+
125
+ - powerbi-remote
126
+ - fabric-mcp-server
127
+
128
+ If you need local Desktop editing, you'll need a Windows environment.
129
+ ```
130
+
131
+ ---
132
+
133
+ ## PHASE 2: Remote Power BI / Fabric
134
+
135
+ If the user chooses option 2:
136
+
137
+ ```text
138
+ REMOTE / FABRIC MCP
139
+ ===================
140
+
141
+ This path uses the Microsoft-hosted and Microsoft-published MCP servers.
142
+
143
+ Default servers:
144
+ - powerbi-remote
145
+ - fabric-mcp-server
146
+ ```
147
+
148
+ Guide them to:
149
+
150
+ 1. Run `bi-superpowers mcp-setup`
151
+ 2. Verify `.mcp.json` contains the official endpoint and Fabric package
152
+ 3. Authenticate in the environment required by their MCP client
153
+ 4. Restart or refresh Claude Code
154
+
155
+ If they ask what gets configured, show:
156
+
157
+ ```text
158
+ powerbi-remote -> https://api.fabric.microsoft.com/v1/mcp/powerbi
159
+ fabric-mcp-server -> npx -y @microsoft/fabric-mcp@latest server start --mode all
160
+ ```
161
+
162
+ ---
163
+
164
+ ## PHASE 3: Verify Plugin Config
165
+
166
+ If the user chooses option 3:
167
+
168
+ Check these files in order:
169
+
170
+ 1. `.claude-plugin/plugin.json`
171
+ 2. `.mcp.json`
172
+ 3. `.bi-superpowers.json` if present
173
+
174
+ Confirm:
175
+
176
+ - plugin name is `bi-superpowers`
177
+ - `.mcp.json` includes `powerbi-remote`
178
+ - `.mcp.json` includes `fabric-mcp-server`
179
+ - `.mcp.json` includes `powerbi-modeling-mcp`
180
+
181
+ If anything is missing, recommend:
182
+
183
+ ```bash
184
+ super recharge
185
+ super mcp-setup
186
+ ```
187
+
188
+ Then:
189
+
190
+ ```bash
191
+ claude --plugin-dir .
192
+ ```
193
+
194
+ ---
195
+
196
+ ## TROUBLESHOOTING
197
+
198
+ | Problem | What to do |
199
+ | --- | --- |
200
+ | Modeling MCP missing on Windows | Install the Microsoft extension in VS Code or Cursor |
201
+ | Modeling MCP installed manually | Set `BI_SUPERPOWERS_POWERBI_MODELING_MCP_PATH` |
202
+ | Plugin not loading MCPs | Re-run `bi-superpowers mcp-setup` and restart Claude Code |
203
+ | macOS/Linux local modeling request | Redirect to `powerbi-remote` or `fabric-mcp-server` |
204
+ | User asks about Excel MCP | Explain Excel remains supported through skills and library content, not a default MCP |
205
+
206
+ ---
207
+
208
+ ## ANTI-PATTERNS
209
+
210
+ | Don't Do This | Why | Do This Instead |
211
+ | --- | --- | --- |
212
+ | Recommend `uvx` for Modeling MCP | Not the official Microsoft installation path | Use the official executable via the local launcher |
213
+ | Ask the user to find a localhost port | Not required in the new flow | Use the official Modeling MCP launcher |
214
+ | Put plugin MCP config in `.claude/settings.json` first | Plugin-first flow uses `.mcp.json` | Prefer `.mcp.json` at the plugin root |
215
+ | Block non-Windows users entirely | Remote/Fabric MCPs still work | Continue with `powerbi-remote` and `fabric-mcp-server` |
216
+
217
+ ---
218
+
219
+ ## Complexity Adaptation
220
+
221
+ Adjust depth based on `config.json → experienceLevel`:
222
+ - **beginner**: Step-by-step with explanations, reference library examples
223
+ - **intermediate**: Standard depth, explain non-obvious decisions
224
+ - **advanced**: Concise, skip basics, focus on edge cases and optimization
225
+
226
+ ---
227
+
228
+ ## Related Skills
229
+
230
+ - `/dax` — Write DAX measures via MCP connection
231
+ - `/model-documenter` — Document the connected model
232
+ - `/fabric-scripts` — Fabric automation via MCP
233
+
234
+ ---
235
+
236
+ ## RELATED RESOURCES
237
+
238
+ - [Power BI MCP overview](https://learn.microsoft.com/en-us/power-bi/developer/mcp/mcp-servers-overview)
239
+ - [Remote Power BI MCP quickstart](https://learn.microsoft.com/en-us/power-bi/developer/mcp/remote-mcp-server-get-started)
240
+ - [Power BI Modeling MCP](https://github.com/microsoft/powerbi-modeling-mcp)
241
+ - [Microsoft Fabric MCP Server](https://github.com/microsoft/mcp/tree/main/servers/Fabric.Mcp.Server)
@@ -0,0 +1,406 @@
1
+ ---
2
+ name: "power-query"
3
+ description: "Use when the user asks about Power Query Skill, especially phrases like \"Power Query\", \"query folding\", \"ETL\", \"source connection\", \"refresh\", \"parameters\"."
4
+ version: "1.0.0"
5
+ ---
6
+
7
+ <!-- Generated by BI Agent Superpowers. Edit src/content/skills/power-query.md instead. -->
8
+
9
+ # Power Query Skill
10
+
11
+ ## Trigger
12
+ Activate this skill when user mentions:
13
+ - "Power Query", "M language", "M code"
14
+ - "query folding", "data transformation"
15
+ - "ETL", "data cleaning", "data preparation"
16
+ - "source connection", "data source"
17
+ - "refresh", "incremental refresh"
18
+ - "parameters", "query parameters"
19
+ - "custom function", "M function"
20
+
21
+ ## Identity
22
+ You are a **Power Query Expert** specializing in efficient data transformations, query optimization, and M language best practices. You help users write clean, performant queries that maximize query folding and follow enterprise patterns.
23
+
24
+ ---
25
+
26
+ ## Naming Conventions
27
+
28
+ | Element | Convention | Example |
29
+ |---------|------------|---------|
30
+ | Queries (staging) | `stg_` prefix | `stg_Sales`, `stg_Customers` |
31
+ | Queries (final) | PascalCase, no prefix | `DimCustomer`, `FactSales` |
32
+ | Parameters | `param_` prefix | `param_StartDate`, `param_ServerName` |
33
+ | Functions | `fn_` prefix | `fn_CleanText`, `fn_ParseDate` |
34
+ | Steps | Descriptive, PascalCase | `RemovedDuplicates`, `FilteredByDate` |
35
+
36
+ ---
37
+
38
+ ## Query Folding
39
+
40
+ ### What is Query Folding?
41
+ Query folding pushes transformations back to the data source (SQL, OData, etc.) instead of processing in Power Query. This dramatically improves performance.
42
+
43
+ ### Check if Folding is Active
44
+ Right-click any step → "View Native Query"
45
+ - If grayed out: Folding is broken at that step
46
+ - If available: Shows the SQL being generated
47
+
48
+ ### Operations That Fold (SQL Sources)
49
+ ```
50
+ ✓ Remove columns (SELECT)
51
+ ✓ Filter rows (WHERE)
52
+ ✓ Sort (ORDER BY)
53
+ ✓ Group by (GROUP BY)
54
+ ✓ Join/Merge (JOIN)
55
+ ✓ Append (UNION ALL)
56
+ ✓ Rename columns (AS)
57
+ ✓ Change type (CAST)
58
+ ✓ Add conditional column (CASE WHEN)
59
+ ✓ Top N rows (TOP)
60
+ ```
61
+
62
+ ### Operations That Break Folding
63
+ ```
64
+ ✗ Add Index column
65
+ ✗ Pivot/Unpivot (usually)
66
+ ✗ Custom columns with M functions
67
+ ✗ Merge with non-folding query
68
+ ✗ Table.Buffer()
69
+ ✗ List.Generate()
70
+ ✗ Sorting after grouping
71
+ ```
72
+
73
+ ### Best Practice: Fold First
74
+ ```m
75
+ // GOOD: Filter and select before custom transforms
76
+ let
77
+ Source = Sql.Database("server", "database"),
78
+ Sales = Source{[Schema="dbo", Item="Sales"]}[Data],
79
+ // These fold:
80
+ FilteredRows = Table.SelectRows(Sales, each [Date] >= param_StartDate),
81
+ SelectedCols = Table.SelectColumns(FilteredRows, {"ID", "Date", "Amount"}),
82
+ // These don't fold (do them last):
83
+ AddedIndex = Table.AddIndexColumn(SelectedCols, "Index", 1, 1)
84
+ in
85
+ AddedIndex
86
+ ```
87
+
88
+ ---
89
+
90
+ ## Best Practices
91
+
92
+ ### 1. Staging Pattern
93
+ Separate data extraction from transformation:
94
+
95
+ ```m
96
+ // stg_Customers (staging - simple extraction)
97
+ let
98
+ Source = Sql.Database("server", "db"),
99
+ Customers = Source{[Schema="dbo", Item="Customers"]}[Data],
100
+ SelectedColumns = Table.SelectColumns(Customers, {"ID", "Name", "Email", "CreatedDate"})
101
+ in
102
+ SelectedColumns
103
+
104
+ // DimCustomer (transformation - references staging)
105
+ let
106
+ Source = stg_Customers,
107
+ CleanedNames = Table.TransformColumns(Source, {{"Name", Text.Proper}}),
108
+ AddedKey = Table.AddColumn(CleanedNames, "CustomerKey", each "C-" & Text.From([ID]))
109
+ in
110
+ AddedKey
111
+ ```
112
+
113
+ ### 2. Error Handling
114
+ Always handle potential errors in source data:
115
+
116
+ ```m
117
+ // Safe type conversion
118
+ Table.TransformColumns(Source, {
119
+ {"Amount", each try Number.From(_) otherwise 0, type number},
120
+ {"Date", each try Date.From(_) otherwise null, type date}
121
+ })
122
+
123
+ // Replace errors in column
124
+ Table.ReplaceErrorValues(Source, {{"Amount", 0}, {"Date", null}})
125
+
126
+ // Remove rows with errors
127
+ Table.RemoveRowsWithErrors(Source, {"Amount", "Date"})
128
+ ```
129
+
130
+ ### 3. Reusable Functions
131
+ Create functions for repeated logic:
132
+
133
+ ```m
134
+ // fn_CleanText - Remove special characters and trim
135
+ (inputText as text) as text =>
136
+ let
137
+ Trimmed = Text.Trim(inputText),
138
+ Cleaned = Text.Replace(Trimmed, " ", " "),
139
+ Result = Text.Clean(Cleaned)
140
+ in
141
+ Result
142
+
143
+ // Usage
144
+ Table.TransformColumns(Source, {{"Name", fn_CleanText}})
145
+ ```
146
+
147
+ ### 4. Performance Patterns
148
+
149
+ **Buffer for Multiple Uses:**
150
+ ```m
151
+ // Buffer when a table is referenced multiple times
152
+ let
153
+ Source = SomeExpensiveQuery,
154
+ Buffered = Table.Buffer(Source), // Cache in memory
155
+ Branch1 = Table.SelectRows(Buffered, each [Type] = "A"),
156
+ Branch2 = Table.SelectRows(Buffered, each [Type] = "B")
157
+ in
158
+ ...
159
+ ```
160
+
161
+ **Avoid Row-by-Row Operations:**
162
+ ```m
163
+ // BAD: Row-by-row lookup
164
+ Table.AddColumn(Source, "Category", each
165
+ Table.SelectRows(Categories, (c) => c[ID] = [CategoryID]){0}[Name]
166
+ )
167
+
168
+ // GOOD: Merge tables
169
+ Table.NestedJoin(Source, {"CategoryID"}, Categories, {"ID"}, "Cat", JoinKind.LeftOuter)
170
+ ```
171
+
172
+ ---
173
+
174
+ ## Common Patterns
175
+
176
+ ### Date Table Generation
177
+ ```m
178
+ let
179
+ StartDate = #date(2020, 1, 1),
180
+ EndDate = #date(2030, 12, 31),
181
+ NumberOfDays = Duration.Days(EndDate - StartDate) + 1,
182
+ DateList = List.Dates(StartDate, NumberOfDays, #duration(1, 0, 0, 0)),
183
+ ToTable = Table.FromList(DateList, Splitter.SplitByNothing(), {"Date"}, null, ExtraValues.Error),
184
+ ChangedType = Table.TransformColumnTypes(ToTable, {{"Date", type date}}),
185
+ AddedYear = Table.AddColumn(ChangedType, "Year", each Date.Year([Date]), Int64.Type),
186
+ AddedMonth = Table.AddColumn(AddedYear, "Month", each Date.Month([Date]), Int64.Type),
187
+ AddedMonthName = Table.AddColumn(AddedMonth, "MonthName", each Date.MonthName([Date]), type text),
188
+ AddedQuarter = Table.AddColumn(AddedMonthName, "Quarter", each Date.QuarterOfYear([Date]), Int64.Type),
189
+ AddedWeekday = Table.AddColumn(AddedQuarter, "Weekday", each Date.DayOfWeek([Date], Day.Monday) + 1, Int64.Type),
190
+ AddedWeekdayName = Table.AddColumn(AddedWeekday, "WeekdayName", each Date.DayOfWeekName([Date]), type text),
191
+ AddedDateKey = Table.AddColumn(AddedWeekdayName, "DateKey", each Date.Year([Date]) * 10000 + Date.Month([Date]) * 100 + Date.Day([Date]), Int64.Type)
192
+ in
193
+ AddedDateKey
194
+ ```
195
+
196
+ ### Dynamic Folder Import
197
+ ```m
198
+ let
199
+ FolderPath = param_FolderPath,
200
+ Source = Folder.Files(FolderPath),
201
+ FilteredFiles = Table.SelectRows(Source, each Text.EndsWith([Name], ".csv")),
202
+ AddedContent = Table.AddColumn(FilteredFiles, "Data", each
203
+ Csv.Document([Content], [Delimiter=",", Encoding=65001, QuoteStyle=QuoteStyle.Csv])
204
+ ),
205
+ ExpandedData = Table.ExpandTableColumn(AddedContent, "Data",
206
+ Table.ColumnNames(AddedContent{0}[Data])
207
+ ),
208
+ RemovedOtherColumns = Table.SelectColumns(ExpandedData,
209
+ List.Combine({{"Name"}, Table.ColumnNames(FilteredFiles{0}[Data])})
210
+ )
211
+ in
212
+ RemovedOtherColumns
213
+ ```
214
+
215
+ ### Incremental Load Pattern
216
+ ```m
217
+ let
218
+ // Get last refresh date from existing data
219
+ LastDate = try List.Max(ExistingData[ModifiedDate]) otherwise #date(1900, 1, 1),
220
+
221
+ // Only load new/modified records
222
+ Source = Sql.Database("server", "db"),
223
+ Sales = Source{[Schema="dbo", Item="Sales"]}[Data],
224
+ IncrementalRows = Table.SelectRows(Sales, each [ModifiedDate] > LastDate)
225
+ in
226
+ IncrementalRows
227
+ ```
228
+
229
+ ### Unpivot Pattern
230
+ ```m
231
+ // Transform columns to rows (wide to long)
232
+ let
233
+ Source = Excel.CurrentWorkbook(){[Name="SalesData"]}[Content],
234
+ // Columns: Product, Jan, Feb, Mar, Apr...
235
+ UnpivotedMonths = Table.UnpivotOtherColumns(Source, {"Product"}, "Month", "Amount"),
236
+ // Result: Product, Month, Amount (one row per product-month)
237
+ ChangedTypes = Table.TransformColumnTypes(UnpivotedMonths, {{"Amount", type number}})
238
+ in
239
+ ChangedTypes
240
+ ```
241
+
242
+ ### Conditional Merge (Left Join with Conditions)
243
+ ```m
244
+ let
245
+ Source = FactSales,
246
+ // Join with date-effective prices
247
+ Merged = Table.NestedJoin(
248
+ Source, {"ProductID", "Date"},
249
+ PriceHistory, {"ProductID", "EffectiveDate"},
250
+ "Price",
251
+ JoinKind.LeftOuter
252
+ ),
253
+ Expanded = Table.ExpandTableColumn(Merged, "Price", {"UnitPrice"})
254
+ in
255
+ Expanded
256
+ ```
257
+
258
+ ---
259
+
260
+ ## Anti-Patterns
261
+
262
+ ### 1. Breaking Query Folding Early
263
+ ```m
264
+ // BAD: Index column breaks folding
265
+ let
266
+ Source = Sql.Database("server", "db"),
267
+ AddedIndex = Table.AddIndexColumn(Source, "Index"), // Folding breaks here!
268
+ Filtered = Table.SelectRows(AddedIndex, each [Amount] > 1000) // Won't fold
269
+ in
270
+ Filtered
271
+
272
+ // GOOD: Filter first, then add index
273
+ let
274
+ Source = Sql.Database("server", "db"),
275
+ Filtered = Table.SelectRows(Source, each [Amount] > 1000), // Folds
276
+ AddedIndex = Table.AddIndexColumn(Filtered, "Index") // OK at the end
277
+ in
278
+ AddedIndex
279
+ ```
280
+
281
+ ### 2. Hardcoded Values
282
+ ```m
283
+ // BAD: Hardcoded server name
284
+ Source = Sql.Database("PROD-SQL-01", "SalesDB")
285
+
286
+ // GOOD: Use parameters
287
+ Source = Sql.Database(param_ServerName, param_DatabaseName)
288
+ ```
289
+
290
+ ### 3. Loading Unnecessary Data
291
+ ```m
292
+ // BAD: Load everything, filter in DAX
293
+ let
294
+ Source = Sql.Database("server", "db"),
295
+ AllData = Source{[Schema="dbo", Item="Sales"]}[Data]
296
+ in
297
+ AllData
298
+
299
+ // GOOD: Filter at source
300
+ let
301
+ Source = Sql.Database("server", "db"),
302
+ Sales = Source{[Schema="dbo", Item="Sales"]}[Data],
303
+ FilteredByYear = Table.SelectRows(Sales, each [Year] >= 2023),
304
+ SelectedColumns = Table.SelectColumns(FilteredByYear, RequiredColumns)
305
+ in
306
+ SelectedColumns
307
+ ```
308
+
309
+ ### 4. Multiple Source Connections
310
+ ```m
311
+ // BAD: Connect to same source multiple times
312
+ let
313
+ Query1 = Sql.Database("server", "db"){[Schema="dbo", Item="Sales"]}[Data],
314
+ Query2 = Sql.Database("server", "db"){[Schema="dbo", Item="Products"]}[Data]
315
+ in
316
+ ...
317
+
318
+ // GOOD: Single connection, multiple references
319
+ let
320
+ DB = Sql.Database("server", "db"),
321
+ Sales = DB{[Schema="dbo", Item="Sales"]}[Data],
322
+ Products = DB{[Schema="dbo", Item="Products"]}[Data]
323
+ in
324
+ ...
325
+ ```
326
+
327
+ ---
328
+
329
+ ## Data Source Patterns
330
+
331
+ ### SQL Server
332
+ ```m
333
+ Sql.Database("server-name", "database-name", [
334
+ Query = "SELECT * FROM dbo.Table WHERE Date > '2023-01-01'",
335
+ CommandTimeout = #duration(0, 0, 10, 0)
336
+ ])
337
+ ```
338
+
339
+ ### SharePoint List
340
+ ```m
341
+ SharePoint.Tables("https://company.sharepoint.com/sites/SiteName", [
342
+ Implementation = "2.0",
343
+ ViewMode = "All"
344
+ ]){[Title="ListName"]}[Items]
345
+ ```
346
+
347
+ ### REST API
348
+ ```m
349
+ let
350
+ Source = Json.Document(Web.Contents(
351
+ "https://api.example.com/data",
352
+ [
353
+ Headers = [
354
+ #"Authorization" = "Bearer " & param_APIToken,
355
+ #"Content-Type" = "application/json"
356
+ ],
357
+ Query = [
358
+ startDate = Date.ToText(param_StartDate, "yyyy-MM-dd"),
359
+ limit = "1000"
360
+ ]
361
+ ]
362
+ )),
363
+ ToTable = Table.FromRecords(Source[data])
364
+ in
365
+ ToTable
366
+ ```
367
+
368
+ ### Excel File
369
+ ```m
370
+ Excel.Workbook(File.Contents(param_FilePath), true, true){[Item="SheetName", Kind="Sheet"]}[Data]
371
+ ```
372
+
373
+ ### CSV with Encoding
374
+ ```m
375
+ Csv.Document(File.Contents(param_FilePath), [
376
+ Delimiter = ",",
377
+ Encoding = 65001, // UTF-8
378
+ QuoteStyle = QuoteStyle.Csv,
379
+ Columns = 10
380
+ ])
381
+ ```
382
+
383
+ ---
384
+
385
+ ## Complexity Adaptation
386
+
387
+ Adjust depth based on `config.json → experienceLevel`:
388
+ - **beginner**: Step-by-step with explanations, reference library examples
389
+ - **intermediate**: Standard depth, explain non-obvious decisions
390
+ - **advanced**: Concise, skip basics, focus on edge cases and optimization
391
+
392
+ ## Related Skills
393
+
394
+ - `/dax` — DAX measures over transformed data
395
+ - `/data-modeling` — Model design informs transformations
396
+ - `/data-quality` — Validate data during transformation
397
+ - `/query-performance` — Optimize query folding
398
+
399
+ ---
400
+
401
+ ## Related Resources
402
+
403
+ - [Snippets: Data Cleaning](../../snippets/power-query/data-cleaning.md)
404
+ - [Snippets: Transformations](../../snippets/power-query/transformations.md)
405
+ - [Snippets: Connections](../../snippets/power-query/connections.md)
406
+ - [Snippets: Parameters](../../snippets/power-query/parameters.md)