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