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.
- package/.claude-plugin/marketplace.json +31 -0
- package/.claude-plugin/plugin.json +34 -0
- package/.claude-plugin/skill-manifest.json +79 -0
- package/.mcp.json +13 -0
- package/.plugin/plugin.json +14 -0
- package/LICENSE +21 -0
- package/README.md +849 -0
- package/bin/build-plugin.js +97 -0
- package/bin/cli.js +891 -0
- package/bin/commands/autoupdate.js +128 -0
- package/bin/commands/build-desktop.js +368 -0
- package/bin/commands/create-from-template.js +165 -0
- package/bin/commands/diff.js +435 -0
- package/bin/commands/install.js +542 -0
- package/bin/commands/lint.js +441 -0
- package/bin/commands/mcp-setup.js +255 -0
- package/bin/commands/session-update.js +204 -0
- package/bin/commands/smoke-test.js +20 -0
- package/bin/commands/uninstall.js +611 -0
- package/bin/commands/update-check.js +427 -0
- package/bin/commands/validate-cases.js +264 -0
- package/bin/commands/validate-projects.js +426 -0
- package/bin/commands/watch.js +251 -0
- package/bin/lib/agents.js +62 -0
- package/bin/lib/base-template-smoke.js +299 -0
- package/bin/lib/claude-hooks.js +160 -0
- package/bin/lib/generators/claude-plugin.js +529 -0
- package/bin/lib/generators/index.js +116 -0
- package/bin/lib/generators/shared.js +257 -0
- package/bin/lib/mcp-config.js +835 -0
- package/bin/lib/microsoft-mcp.js +206 -0
- package/bin/lib/powerbi-mcp-session.js +140 -0
- package/bin/lib/skills.js +164 -0
- package/bin/lib/template-scaffold.js +366 -0
- package/bin/mcp/powerbi-modeling-launcher.js +42 -0
- package/bin/postinstall.js +50 -0
- package/bin/utils/mcp-detect.js +346 -0
- package/bin/utils/tui.js +314 -0
- package/commands/bi-connect.md +520 -0
- package/commands/bi-dax.md +464 -0
- package/commands/bi-kickoff.md +550 -0
- package/commands/bi-modeling.md +485 -0
- package/commands/bi-performance.md +521 -0
- package/commands/bi-powerquery.md +229 -0
- package/commands/bi-refactor.md +249 -0
- package/commands/bi-scorecard.md +268 -0
- package/commands/bi-start.md +272 -0
- package/config.example.json +23 -0
- package/config.json +23 -0
- package/desktop-extension/manifest.json +30 -0
- package/desktop-extension/package.json +10 -0
- package/desktop-extension/server.js +137 -0
- package/package.json +94 -0
- package/skills/bi-connect/SKILL.md +522 -0
- package/skills/bi-connect/scripts/update-check.js +427 -0
- package/skills/bi-dax/SKILL.md +466 -0
- package/skills/bi-dax/scripts/update-check.js +427 -0
- package/skills/bi-kickoff/SKILL.md +552 -0
- package/skills/bi-kickoff/references/flow.html +78 -0
- package/skills/bi-kickoff/references/flow.md +62 -0
- package/skills/bi-kickoff/scripts/update-check.js +427 -0
- package/skills/bi-modeling/SKILL.md +487 -0
- package/skills/bi-modeling/scripts/update-check.js +427 -0
- package/skills/bi-performance/SKILL.md +523 -0
- package/skills/bi-performance/scripts/install-tabular-editor.ps1 +159 -0
- package/skills/bi-performance/scripts/run-bpa.ps1 +265 -0
- package/skills/bi-performance/scripts/update-check.js +427 -0
- package/skills/bi-powerquery/SKILL.md +231 -0
- package/skills/bi-powerquery/references/base-template-data-contract.md +323 -0
- package/skills/bi-powerquery/references/power-query-standards.md +74 -0
- package/skills/bi-powerquery/scripts/new-powerquery-staging.ps1 +371 -0
- package/skills/bi-powerquery/scripts/test-powerquery-contract.ps1 +225 -0
- package/skills/bi-powerquery/scripts/update-check.js +427 -0
- package/skills/bi-refactor/SKILL.md +251 -0
- package/skills/bi-refactor/references/flow.md +27 -0
- package/skills/bi-refactor/scripts/update-check.js +427 -0
- package/skills/bi-scorecard/SKILL.md +270 -0
- package/skills/bi-scorecard/examples/base-template-scorecard-overlay.json +82 -0
- package/skills/bi-scorecard/scripts/new-scorecard-blueprint-from-base-template.ps1 +124 -0
- package/skills/bi-scorecard/scripts/powerbi-goal-status-rules-api.ps1 +39 -0
- package/skills/bi-scorecard/scripts/powerbi-goal-values-api.ps1 +48 -0
- package/skills/bi-scorecard/scripts/powerbi-goals-api.ps1 +68 -0
- package/skills/bi-scorecard/scripts/powerbi-rest-common.ps1 +197 -0
- package/skills/bi-scorecard/scripts/powerbi-scorecards-api.ps1 +53 -0
- package/skills/bi-scorecard/scripts/update-check.js +427 -0
- package/skills/bi-start/SKILL.md +274 -0
- package/skills/bi-start/scripts/update-check.js +427 -0
- package/src/content/base.md +197 -0
- package/src/content/mcp-requirements.json +57 -0
- package/src/content/routing.md +201 -0
- package/src/content/skills/bi-connect.md +493 -0
- package/src/content/skills/bi-dax.md +437 -0
- package/src/content/skills/bi-kickoff/SKILL.md +523 -0
- package/src/content/skills/bi-kickoff/references/flow.html +78 -0
- package/src/content/skills/bi-kickoff/references/flow.md +62 -0
- package/src/content/skills/bi-modeling.md +458 -0
- package/src/content/skills/bi-performance/SKILL.md +494 -0
- package/src/content/skills/bi-performance/scripts/install-tabular-editor.ps1 +159 -0
- package/src/content/skills/bi-performance/scripts/run-bpa.ps1 +265 -0
- package/src/content/skills/bi-powerquery/SKILL.md +202 -0
- package/src/content/skills/bi-powerquery/references/base-template-data-contract.md +323 -0
- package/src/content/skills/bi-powerquery/references/power-query-standards.md +74 -0
- package/src/content/skills/bi-powerquery/scripts/new-powerquery-staging.ps1 +371 -0
- package/src/content/skills/bi-powerquery/scripts/test-powerquery-contract.ps1 +225 -0
- package/src/content/skills/bi-refactor/SKILL.md +222 -0
- package/src/content/skills/bi-refactor/references/flow.md +27 -0
- package/src/content/skills/bi-scorecard/SKILL.md +241 -0
- package/src/content/skills/bi-scorecard/examples/base-template-scorecard-blueprint.expected.json +105 -0
- package/src/content/skills/bi-scorecard/examples/base-template-scorecard-overlay.json +82 -0
- package/src/content/skills/bi-scorecard/scripts/new-scorecard-blueprint-from-base-template.ps1 +124 -0
- package/src/content/skills/bi-scorecard/scripts/powerbi-goal-status-rules-api.ps1 +39 -0
- package/src/content/skills/bi-scorecard/scripts/powerbi-goal-values-api.ps1 +48 -0
- package/src/content/skills/bi-scorecard/scripts/powerbi-goals-api.ps1 +68 -0
- package/src/content/skills/bi-scorecard/scripts/powerbi-rest-common.ps1 +197 -0
- package/src/content/skills/bi-scorecard/scripts/powerbi-scorecards-api.ps1 +53 -0
- package/src/content/skills/bi-start.md +266 -0
- package/templates/base-template/AGENTS.md +33 -0
- package/templates/base-template/base-template.Report/.platform +11 -0
- package/templates/base-template/base-template.Report/StaticResources/RegisteredResources/BISuperpowers.json +3888 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BaseThemes/CY18SU07.json +177 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BaseThemes/Fluent2-CY26SU03.json +4104 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/AccessibleCityPark.json +26 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/AccessibleDefault.json +26 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/AccessibleNeutral.json +26 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/AccessibleOrchid.json +26 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/AccessibleTidal.json +26 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Bloom.json +139 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/CityPark.json +40 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Classroom.json +40 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/ColorblindSafe.json +48 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/CopilotDefault.json +1861 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Divergent.json +127 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Electric.json +48 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Frontier.json +136 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/HighContrast.json +40 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Highrise.json +41 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Innovate.json +227 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/NewExecutive.json +41 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Solar.json +33 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Storm.json +25 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Sunset.json +48 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Temperature.json +33 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Tidal.json +100 -0
- package/templates/base-template/base-template.Report/StaticResources/SharedResources/BuiltInThemes/Twilight.json +40 -0
- package/templates/base-template/base-template.Report/definition/bookmarks/1d40d43c7ade66e8603c.bookmark.json +2297 -0
- package/templates/base-template/base-template.Report/definition/bookmarks/af068ff51c0ca3089ea7.bookmark.json +2300 -0
- package/templates/base-template/base-template.Report/definition/bookmarks/bookmarks.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/page.json +130 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/0352fd80d074693a65db/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/0352fd80d074693a65db/visual.json +669 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/1c5a14bf493697344b68/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/1c5a14bf493697344b68/visual.json +723 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/3486cf7624c5b109b4e5/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/3486cf7624c5b109b4e5/visual.json +333 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/4d8b989008edc0db28d1/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/4d8b989008edc0db28d1/visual.json +109 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/55e10ac7d76a1954f94f/mobile.json +31 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/55e10ac7d76a1954f94f/visual.json +378 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/57f52ecf4490f70e4da1/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/57f52ecf4490f70e4da1/visual.json +175 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/5f4d76bbc870118e9840/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/5f4d76bbc870118e9840/visual.json +468 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/73629e1abebb7a444b59/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/73629e1abebb7a444b59/visual.json +359 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/749cb1388c7e0a88161c/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/749cb1388c7e0a88161c/visual.json +690 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/90677f13cea5d1275990/visual.json +17 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/92cf92e3da10493adb78/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/92cf92e3da10493adb78/visual.json +468 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/9fe17b1971f68443fc15/mobile.json +10 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/9fe17b1971f68443fc15/visual.json +328 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/a30bd0950630ed94e8a3/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/a30bd0950630ed94e8a3/visual.json +578 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/a56e91d9400a835e4814/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/a56e91d9400a835e4814/visual.json +432 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/aded24cd205c0b528642/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/aded24cd205c0b528642/visual.json +801 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/af34b26f14a8a724c9a9/mobile.json +37 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/af34b26f14a8a724c9a9/visual.json +1318 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/b529688fe5a226643322/visual.json +209 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/c4c6f332d05e72e2eb06/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/c4c6f332d05e72e2eb06/visual.json +174 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/fa81f184e2cb0e8b087c/mobile.json +29 -0
- package/templates/base-template/base-template.Report/definition/pages/6a4808bb8bb9166f49ff/visuals/fa81f184e2cb0e8b087c/visual.json +241 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/page.json +130 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/07e9c4302e29029c5462/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/07e9c4302e29029c5462/visual.json +690 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/109ceede4bc015b0c006/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/109ceede4bc015b0c006/visual.json +468 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/118257e006d472277e10/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/118257e006d472277e10/visual.json +359 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/2caf02e0137c4a1280cc/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/2caf02e0137c4a1280cc/visual.json +669 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/311e76fe3c9edad68204/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/311e76fe3c9edad68204/visual.json +109 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/31c21f8cbeb3b208940a/visual.json +209 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/3ab72c25062437149b03/visual.json +17 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/5959867442abcb0ce2b3/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/5959867442abcb0ce2b3/visual.json +788 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/5b96e0f88d192b044a13/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/5b96e0f88d192b044a13/visual.json +592 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/64e749a63d0786000e22/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/64e749a63d0786000e22/visual.json +468 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/7ae1ca604edac6586ad0/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/7ae1ca604edac6586ad0/visual.json +1310 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/840300733885141a6603/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/840300733885141a6603/visual.json +175 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/a38448cdb203279273d2/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/a38448cdb203279273d2/visual.json +516 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/d1e86f213a3841d12e20/visual.json +328 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/d4a484c1bcc8ee3075e2/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/d4a484c1bcc8ee3075e2/visual.json +432 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/d87cb5cf06acca19bbb5/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/d87cb5cf06acca19bbb5/visual.json +241 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/e243da2677209ed69408/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/e243da2677209ed69408/visual.json +174 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/f3aaf24f5b22b67573b0/mobile.json +11 -0
- package/templates/base-template/base-template.Report/definition/pages/9a5b670b015cab882629/visuals/f3aaf24f5b22b67573b0/visual.json +333 -0
- package/templates/base-template/base-template.Report/definition/pages/pages.json +8 -0
- package/templates/base-template/base-template.Report/definition/report.json +89 -0
- package/templates/base-template/base-template.Report/definition/version.json +4 -0
- package/templates/base-template/base-template.Report/definition.pbir +9 -0
- package/templates/base-template/base-template.SemanticModel/.platform +11 -0
- package/templates/base-template/base-template.SemanticModel/definition/cultures/es-AR.tmdl +11185 -0
- package/templates/base-template/base-template.SemanticModel/definition/database.tmdl +3 -0
- package/templates/base-template/base-template.SemanticModel/definition/expressions.tmdl +234 -0
- package/templates/base-template/base-template.SemanticModel/definition/functions.tmdl +637 -0
- package/templates/base-template/base-template.SemanticModel/definition/model.tmdl +82 -0
- package/templates/base-template/base-template.SemanticModel/definition/relationships.tmdl +271 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Calendario.tmdl +200 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Campa/303/261as.tmdl +75 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Canales.tmdl +84 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Clientes.tmdl +143 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Devoluciones.tmdl +95 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Ejecuci/303/263n proyectos.tmdl" +130 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Entregas.tmdl +122 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Equipos m/303/251tricas.tmdl" +40 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Equipos.tmdl +73 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Horas.tmdl +122 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Interacciones clientes.tmdl +146 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Leads.tmdl +119 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Monedas.tmdl +44 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Movimientos financieros.tmdl +145 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/M/303/251tricas.tmdl +1294 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/N/303/263mina.tmdl +110 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Oportunidades.tmdl +135 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Presupuesto.tmdl +125 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Productos.tmdl +98 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Proyectos.tmdl +77 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Servicios.tmdl +75 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Tareas proyecto.tmdl +102 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Tipo de cambio.tmdl +67 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/Ventas.tmdl +180 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux An/303/241lisis dimensiones.tmdl" +38 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Comparaciones.tmdl +227 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Compatibilidad m/303/251trica-dimensi/303/263n.tmdl" +68 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Modelo configuraci/303/263n.tmdl" +44 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Modo fechas.tmdl +36 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux M/303/251trica-Equipo.tmdl" +102 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Overrides m/303/251trica-dimensi/303/263n.tmdl" +54 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Per/303/255odos.tmdl" +182 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Rango fechas modo.tmdl +36 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Rango fechas.tmdl +27 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_Aux Vista de calendario.tmdl +30 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_GC C/303/241lculo.tmdl" +70 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_GC Eje X.tmdl +63 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_GC M/303/251trica.tmdl" +374 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_GC Tipo c/303/241lculo.tmdl" +223 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_PC Dimensi/303/263n.tmdl" +98 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables/_PC Eje X.tmdl +68 -0
- package/templates/base-template/base-template.SemanticModel/definition/tables//303/223rdenes servicio.tmdl" +151 -0
- package/templates/base-template/base-template.SemanticModel/definition.pbism +5 -0
- package/templates/base-template/base-template.SemanticModel/diagramLayout.json +568 -0
- package/templates/base-template/base-template.pbip +14 -0
- package/templates/base-template/template.manifest.json +41 -0
- package/theme/BISuperpowers.json +3888 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# /bi-kickoff Flow
|
|
2
|
+
|
|
3
|
+
Este diagrama resume el flujo de producción de `/bi-kickoff`. Mantenelo sincronizado con `SKILL.md` y `flow.html` cada vez que cambien preguntas, ramas o contratos de modelado.
|
|
4
|
+
|
|
5
|
+
```mermaid
|
|
6
|
+
flowchart TD
|
|
7
|
+
A["Usuario invoca /bi-kickoff"] --> B{"Proyecto nuevo?"}
|
|
8
|
+
B -->|"No / PBIP existente"| Ref["Derivar a /bi-refactor"]
|
|
9
|
+
B -->|"Si / carpeta vacia"| C["Primer mensaje simple\npregunta nombre"]
|
|
10
|
+
C --> D["Scaffold desde base-template\nsin narrar checks"]
|
|
11
|
+
D --> E{"Existe Git?"}
|
|
12
|
+
E -->|"No"| F["git init"]
|
|
13
|
+
E -->|"Si"| G["Commit scaffold inicial"]
|
|
14
|
+
F --> G
|
|
15
|
+
G --> H["Agente abre PBIP en Desktop"]
|
|
16
|
+
H --> I["Aclarar: aún es plantilla\nsiguiente mensaje genera modelo"]
|
|
17
|
+
I --> J["Conectar MCP"]
|
|
18
|
+
J --> K["Pedir Inicio > Actualizar\ny esperar confirmación"]
|
|
19
|
+
K --> N["Onboarding negocio\nuna pregunta por vez"]
|
|
20
|
+
N --> O["Métricas, dimensiones y tiempo\ncon opciones numeradas"]
|
|
21
|
+
O --> P{"Mapeo de datos ahora?"}
|
|
22
|
+
P -->|"No"| Q["Pendiente para /bi-powerquery"]
|
|
23
|
+
P -->|"Si"| R["docs/mapeo-de-datos.md\nsin conectar fuentes reales"]
|
|
24
|
+
Q --> S["AGENTS.md + ROADMAP.md + LEARNINGS.md\nCodex-only"]
|
|
25
|
+
R --> S
|
|
26
|
+
S --> T["Proponer modelo demo\ncada fila representa algo medible"]
|
|
27
|
+
T --> U{"Agregamos o quitamos algo?"}
|
|
28
|
+
U -->|"Cambios"| T
|
|
29
|
+
U -->|"Aprobado"| Gen["Crear modelo con operaciones MCP exactas"]
|
|
30
|
+
Gen --> Model["Crear facts, dims, relaciones, métricas, dispatchers"]
|
|
31
|
+
Model --> Clean["Eliminar star schema demo de Ventas\nsi el dominio no es ventas"]
|
|
32
|
+
Clean --> V{"Verificación MCP pasa?"}
|
|
33
|
+
V -->|"No"| Gen
|
|
34
|
+
V -->|"Si"| W["Usuario guarda y cierra Desktop"]
|
|
35
|
+
W --> X{"TMDL persistido valida?"}
|
|
36
|
+
X -->|"No"| W
|
|
37
|
+
X -->|"Si"| Y{"Visual bindings validados?"}
|
|
38
|
+
Y -->|"Rebind tool"| RB["Rebind seguro\nbackup + dry-run + validación"]
|
|
39
|
+
Y -->|"Manual"| MH["Handoff manual explícito\nreporte pendiente"]
|
|
40
|
+
RB --> Cmt["Actualizar ROADMAP/docs\ncommit modelo generado"]
|
|
41
|
+
MH --> Cmt
|
|
42
|
+
Cmt --> Z["Handoff: report rebind, authoring o /bi-powerquery"]
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Contrato visual
|
|
46
|
+
|
|
47
|
+
- `/bi-kickoff` es solo para proyectos nuevos; existentes van a `/bi-refactor`.
|
|
48
|
+
- El primer mensaje no expone Windows, template, ni inventario técnico.
|
|
49
|
+
- Después del scaffold, el agente abre el PBIP; no le pide al usuario que lo abra.
|
|
50
|
+
- El mensaje post-apertura aclara que lo visible aún es la plantilla y que el modelo real comienza en el siguiente mensaje.
|
|
51
|
+
- Antes de generar el modelo, el primer refresh se hace en Power BI Desktop (`Inicio > Actualizar` o `Aplicar cambios`); el MCP lee y valida después, pero no procesa datos en un modelo abierto.
|
|
52
|
+
- El proyecto generado es Codex-first: `AGENTS.md`, `ROADMAP.md`, `LEARNINGS.md`, y opcional `docs/mapeo-de-datos.md`.
|
|
53
|
+
- No se crean `CLAUDE.md`, `GEMINI.md`, `.github`, `.kilo` ni adapters salvo pedido explícito.
|
|
54
|
+
- Git es obligatorio: commit inicial del scaffold y commit del modelo verificado.
|
|
55
|
+
- El modelo demo puede tener varias tablas de hechos; al usuario se le explica como "cada fila representa...".
|
|
56
|
+
- La estructura final reemplaza el ejemplo de ventas; `Ventas/Clientes/Productos/Canales` no quedan en proyectos no-sales.
|
|
57
|
+
- Kickoff crea estructura destino y demo data; `/bi-powerquery` carga datos reales después.
|
|
58
|
+
- No se conectan fuentes reales durante kickoff.
|
|
59
|
+
- Todo cambio semántico usa operaciones MCP exactas: leer, escribir una vez, leer de vuelta y guardar/exportar antes de validar archivos.
|
|
60
|
+
- Los nombres técnicos ya bindeados al reporte se preservan siempre que sea posible.
|
|
61
|
+
- REPORT TOPOLOGY LOCK: nunca borrar, renombrar, mover o recrear páginas, visuales, layouts mobile o bookmarks. Solo se pueden cambiar dimensiones/medidas dentro de visuales existentes, manualmente en Desktop o con una futura herramienta segura de rebind.
|
|
62
|
+
- Nada se marca como terminado hasta guardar, cerrar Desktop, validar PBIP persistido y pasar o explicitar el gate de rebind visual.
|
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* update-check — cross-agent version-check helper for bi-superpowers.
|
|
4
|
+
*
|
|
5
|
+
* The SKILL.md preamble (see lib/generators/claude-plugin.js) invokes this
|
|
6
|
+
* script at the start of every skill so the agent can surface an update
|
|
7
|
+
* notice to the user when a newer version is on npm — without hitting the
|
|
8
|
+
* network on every invocation. Cache TTL is 24h; repeated calls inside
|
|
9
|
+
* that window are served from `~/.bi-superpowers/update-state.json`.
|
|
10
|
+
*
|
|
11
|
+
* Output (stdout, one line):
|
|
12
|
+
* UPTODATE when installed >= latest
|
|
13
|
+
* UPDATE_AVAILABLE <installed> <latest> when installed < latest
|
|
14
|
+
* SNOOZED <iso> when user deferred the notice
|
|
15
|
+
*
|
|
16
|
+
* Flags:
|
|
17
|
+
* --force bypass cache (re-fetch npm, ignore snooze TTL)
|
|
18
|
+
* --silent-if-uptodate suppress UPTODATE line (used by the preamble)
|
|
19
|
+
* --silent-if-snoozed suppress SNOOZED line (used by the preamble)
|
|
20
|
+
* --json emit JSON instead of text
|
|
21
|
+
* --snooze 24h|48h|7d|clear set (or clear) the snooze state and exit
|
|
22
|
+
* --reset delete the state file and exit (used post-upgrade)
|
|
23
|
+
* --state-dir <path> override ~/.bi-superpowers/ (for tests)
|
|
24
|
+
* --package-name <name> override the package name (for tests)
|
|
25
|
+
* -h, --help show this help
|
|
26
|
+
*
|
|
27
|
+
* Exit code is always 0 when the script itself ran — errors during the
|
|
28
|
+
* network fetch degrade to "no output" so the caller never blocks. A
|
|
29
|
+
* non-zero exit means a user error (bad flags).
|
|
30
|
+
*
|
|
31
|
+
* Pure helpers (compareVersions, isCacheFresh, isSnoozed,
|
|
32
|
+
* computeNextSnoozeUntil, readState, writeState, fetchLatestVersion) are
|
|
33
|
+
* exported so unit tests can exercise them without spawning child
|
|
34
|
+
* processes or hitting the network.
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
'use strict';
|
|
38
|
+
|
|
39
|
+
const fs = require('fs');
|
|
40
|
+
const os = require('os');
|
|
41
|
+
const path = require('path');
|
|
42
|
+
const https = require('https');
|
|
43
|
+
|
|
44
|
+
const PACKAGE_NAME = 'bi-superpowers';
|
|
45
|
+
const CACHE_TTL_MS = 1000 * 60 * 60 * 24; // 24 hours
|
|
46
|
+
const HTTPS_TIMEOUT_MS = 5000;
|
|
47
|
+
// Rewritten at generation time when this helper is copied into
|
|
48
|
+
// `skills/<name>/scripts/update-check.js`. In the canonical source under
|
|
49
|
+
// `bin/commands/`, it stays null and we fall back to package.json.
|
|
50
|
+
const BUNDLED_INSTALLED_VERSION = "1.0.0";
|
|
51
|
+
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
// Argument parsing
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
|
|
56
|
+
function parseArgs(argv) {
|
|
57
|
+
const out = {
|
|
58
|
+
force: false,
|
|
59
|
+
silentIfUptodate: false,
|
|
60
|
+
silentIfSnoozed: false,
|
|
61
|
+
json: false,
|
|
62
|
+
snooze: null,
|
|
63
|
+
reset: false,
|
|
64
|
+
help: false,
|
|
65
|
+
stateDir: null,
|
|
66
|
+
packageName: null,
|
|
67
|
+
installedVersion: null,
|
|
68
|
+
};
|
|
69
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
70
|
+
const a = argv[i];
|
|
71
|
+
if (a === '--force') out.force = true;
|
|
72
|
+
else if (a === '--silent-if-uptodate') out.silentIfUptodate = true;
|
|
73
|
+
else if (a === '--silent-if-snoozed') out.silentIfSnoozed = true;
|
|
74
|
+
else if (a === '--json') out.json = true;
|
|
75
|
+
else if (a === '--snooze') {
|
|
76
|
+
out.snooze = argv[++i];
|
|
77
|
+
if (out.snooze === undefined) {
|
|
78
|
+
process.stderr.write(
|
|
79
|
+
'update-check: --snooze requires a value (e.g. 24h, 48h, 7d, auto, clear)\n'
|
|
80
|
+
);
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
} else if (a === '--reset') out.reset = true;
|
|
84
|
+
else if (a === '--state-dir') out.stateDir = argv[++i];
|
|
85
|
+
else if (a === '--package-name') out.packageName = argv[++i];
|
|
86
|
+
else if (a === '--installed-version') out.installedVersion = argv[++i];
|
|
87
|
+
else if (a === '-h' || a === '--help') out.help = true;
|
|
88
|
+
else {
|
|
89
|
+
process.stderr.write(`update-check: unknown flag: ${a}\n`);
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return out;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function help() {
|
|
97
|
+
process.stdout.write(
|
|
98
|
+
[
|
|
99
|
+
'Usage: update-check [options]',
|
|
100
|
+
'',
|
|
101
|
+
'Prints one of: UPTODATE, UPDATE_AVAILABLE <installed> <latest>, SNOOZED <iso>.',
|
|
102
|
+
'',
|
|
103
|
+
'Options:',
|
|
104
|
+
' --force Bypass cache and snooze TTL',
|
|
105
|
+
' --silent-if-uptodate Skip the UPTODATE line',
|
|
106
|
+
' --silent-if-snoozed Skip the SNOOZED line',
|
|
107
|
+
' --json Emit JSON',
|
|
108
|
+
' --snooze <dur> Set snooze state (24h|48h|7d) or "clear" to reset snooze',
|
|
109
|
+
' --reset Delete the state file (used after a successful upgrade)',
|
|
110
|
+
' --state-dir <path> Override ~/.bi-superpowers/ (tests)',
|
|
111
|
+
' --package-name <name> Override the package name (tests)',
|
|
112
|
+
' --installed-version <v> Override the installed version (generated skill bundles)',
|
|
113
|
+
' -h, --help Show this help',
|
|
114
|
+
'',
|
|
115
|
+
].join('\n')
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ---------------------------------------------------------------------------
|
|
120
|
+
// Version comparison (semver-ish: MAJOR.MINOR.PATCH with optional -prerelease)
|
|
121
|
+
// No deps; handles the shapes bi-superpowers uses today.
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Compare two semver strings.
|
|
126
|
+
* Returns -1 if a < b, 0 if equal, 1 if a > b.
|
|
127
|
+
* Pre-release tags (`-alpha.1`) sort before the release per semver.
|
|
128
|
+
*/
|
|
129
|
+
function compareVersions(a, b) {
|
|
130
|
+
const parse = (v) => {
|
|
131
|
+
const [main, pre] = String(v).split('-');
|
|
132
|
+
const parts = main.split('.').map((n) => parseInt(n, 10) || 0);
|
|
133
|
+
while (parts.length < 3) parts.push(0);
|
|
134
|
+
return { parts, pre: pre || null };
|
|
135
|
+
};
|
|
136
|
+
const va = parse(a);
|
|
137
|
+
const vb = parse(b);
|
|
138
|
+
for (let i = 0; i < 3; i += 1) {
|
|
139
|
+
if (va.parts[i] !== vb.parts[i]) return va.parts[i] < vb.parts[i] ? -1 : 1;
|
|
140
|
+
}
|
|
141
|
+
// Main equal — pre-release < release.
|
|
142
|
+
if (va.pre && !vb.pre) return -1;
|
|
143
|
+
if (!va.pre && vb.pre) return 1;
|
|
144
|
+
if (va.pre && vb.pre) {
|
|
145
|
+
// Semver prerelease precedence: dot-separated identifiers compared
|
|
146
|
+
// left-to-right; numeric identifiers compared numerically, numeric ranks
|
|
147
|
+
// below alphanumeric, and a shorter identifier set has lower precedence.
|
|
148
|
+
const pa = va.pre.split('.');
|
|
149
|
+
const pb = vb.pre.split('.');
|
|
150
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i += 1) {
|
|
151
|
+
if (pa[i] === undefined) return -1;
|
|
152
|
+
if (pb[i] === undefined) return 1;
|
|
153
|
+
const an = /^\d+$/.test(pa[i]);
|
|
154
|
+
const bn = /^\d+$/.test(pb[i]);
|
|
155
|
+
if (an && bn) {
|
|
156
|
+
const d = parseInt(pa[i], 10) - parseInt(pb[i], 10);
|
|
157
|
+
if (d !== 0) return d < 0 ? -1 : 1;
|
|
158
|
+
} else if (an !== bn) {
|
|
159
|
+
return an ? -1 : 1;
|
|
160
|
+
} else if (pa[i] !== pb[i]) {
|
|
161
|
+
return pa[i] < pb[i] ? -1 : 1;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return 0;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
// Cache + snooze state
|
|
170
|
+
// ---------------------------------------------------------------------------
|
|
171
|
+
|
|
172
|
+
function defaultStateDir() {
|
|
173
|
+
return path.join(os.homedir(), '.bi-superpowers');
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function stateFilePath(stateDir) {
|
|
177
|
+
return path.join(stateDir, 'update-state.json');
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function readState(stateDir) {
|
|
181
|
+
const filePath = stateFilePath(stateDir);
|
|
182
|
+
if (!fs.existsSync(filePath)) return null;
|
|
183
|
+
try {
|
|
184
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
185
|
+
} catch (_) {
|
|
186
|
+
// Malformed → treat as no cache.
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function writeState(stateDir, state) {
|
|
192
|
+
fs.mkdirSync(stateDir, { recursive: true });
|
|
193
|
+
fs.writeFileSync(stateFilePath(stateDir), JSON.stringify(state, null, 2) + '\n');
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function resetState(stateDir) {
|
|
197
|
+
const filePath = stateFilePath(stateDir);
|
|
198
|
+
if (fs.existsSync(filePath)) fs.unlinkSync(filePath);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function isCacheFresh(state, now, ttlMs) {
|
|
202
|
+
if (!state || !state.checkedAt) return false;
|
|
203
|
+
const checkedAt = Date.parse(state.checkedAt);
|
|
204
|
+
if (!Number.isFinite(checkedAt)) return false;
|
|
205
|
+
return now - checkedAt < ttlMs;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function isSnoozed(state, now) {
|
|
209
|
+
if (!state || !state.snoozeUntil) return false;
|
|
210
|
+
const until = Date.parse(state.snoozeUntil);
|
|
211
|
+
if (!Number.isFinite(until)) return false;
|
|
212
|
+
return until > now;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Snooze escalation: 24h → 48h → 7d (capped).
|
|
216
|
+
function computeNextSnoozeUntil(currentLevel, now) {
|
|
217
|
+
const levels = [
|
|
218
|
+
1000 * 60 * 60 * 24, // 24h
|
|
219
|
+
1000 * 60 * 60 * 48, // 48h
|
|
220
|
+
1000 * 60 * 60 * 24 * 7, // 7d
|
|
221
|
+
];
|
|
222
|
+
const idx = Math.min(Math.max(currentLevel, 0), levels.length - 1);
|
|
223
|
+
return new Date(now + levels[idx]).toISOString();
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function parseSnoozeArg(arg, now, currentLevel) {
|
|
227
|
+
if (arg === 'clear') return { clear: true };
|
|
228
|
+
if (arg === '24h') return { until: new Date(now + 1000 * 60 * 60 * 24).toISOString(), level: 0 };
|
|
229
|
+
if (arg === '48h') return { until: new Date(now + 1000 * 60 * 60 * 48).toISOString(), level: 1 };
|
|
230
|
+
if (arg === '7d')
|
|
231
|
+
return { until: new Date(now + 1000 * 60 * 60 * 24 * 7).toISOString(), level: 2 };
|
|
232
|
+
if (arg === 'auto')
|
|
233
|
+
return {
|
|
234
|
+
until: computeNextSnoozeUntil(currentLevel, now),
|
|
235
|
+
level: Math.min(currentLevel + 1, 2),
|
|
236
|
+
};
|
|
237
|
+
throw new Error(`invalid --snooze value: ${arg}. Expected 24h|48h|7d|auto|clear.`);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// ---------------------------------------------------------------------------
|
|
241
|
+
// npm registry fetch
|
|
242
|
+
// ---------------------------------------------------------------------------
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Fetch the latest published version of a package from the npm registry.
|
|
246
|
+
* Never rejects with a network error — resolves null on timeout / failure
|
|
247
|
+
* so callers always degrade gracefully.
|
|
248
|
+
*
|
|
249
|
+
* @param {string} packageName - e.g. "bi-superpowers"
|
|
250
|
+
* @returns {Promise<string|null>}
|
|
251
|
+
*/
|
|
252
|
+
function fetchLatestVersion(packageName) {
|
|
253
|
+
return new Promise((resolve) => {
|
|
254
|
+
const encoded = packageName.replace('/', '%2F');
|
|
255
|
+
const url = `https://registry.npmjs.org/${encoded}/latest`;
|
|
256
|
+
|
|
257
|
+
const req = https.get(
|
|
258
|
+
url,
|
|
259
|
+
{ headers: { Accept: 'application/vnd.npm.install-v1+json' } },
|
|
260
|
+
(res) => {
|
|
261
|
+
if (res.statusCode !== 200) {
|
|
262
|
+
res.resume();
|
|
263
|
+
resolve(null);
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
let body = '';
|
|
267
|
+
res.setEncoding('utf8');
|
|
268
|
+
res.on('data', (chunk) => (body += chunk));
|
|
269
|
+
res.on('end', () => {
|
|
270
|
+
try {
|
|
271
|
+
const json = JSON.parse(body);
|
|
272
|
+
resolve(typeof json.version === 'string' ? json.version : null);
|
|
273
|
+
} catch (_) {
|
|
274
|
+
resolve(null);
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
);
|
|
279
|
+
req.on('error', () => resolve(null));
|
|
280
|
+
req.setTimeout(HTTPS_TIMEOUT_MS, () => {
|
|
281
|
+
req.destroy();
|
|
282
|
+
resolve(null);
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// ---------------------------------------------------------------------------
|
|
288
|
+
// Installed version — read from our own package.json
|
|
289
|
+
// ---------------------------------------------------------------------------
|
|
290
|
+
|
|
291
|
+
function readInstalledVersion(explicitVersion = null) {
|
|
292
|
+
if (explicitVersion) {
|
|
293
|
+
return String(explicitVersion);
|
|
294
|
+
}
|
|
295
|
+
if (BUNDLED_INSTALLED_VERSION) {
|
|
296
|
+
return String(BUNDLED_INSTALLED_VERSION);
|
|
297
|
+
}
|
|
298
|
+
try {
|
|
299
|
+
return require(path.join(__dirname, '..', '..', 'package.json')).version;
|
|
300
|
+
} catch (_) {
|
|
301
|
+
return null;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// ---------------------------------------------------------------------------
|
|
306
|
+
// Emit helpers
|
|
307
|
+
// ---------------------------------------------------------------------------
|
|
308
|
+
|
|
309
|
+
function emit(args, kind, payload) {
|
|
310
|
+
if (args.json) {
|
|
311
|
+
process.stdout.write(JSON.stringify({ status: kind, ...payload }) + '\n');
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
if (kind === 'UPTODATE' && args.silentIfUptodate) return;
|
|
315
|
+
if (kind === 'SNOOZED' && args.silentIfSnoozed) return;
|
|
316
|
+
|
|
317
|
+
if (kind === 'UPTODATE') process.stdout.write('UPTODATE\n');
|
|
318
|
+
else if (kind === 'UPDATE_AVAILABLE')
|
|
319
|
+
process.stdout.write(`UPDATE_AVAILABLE ${payload.installed} ${payload.latest}\n`);
|
|
320
|
+
else if (kind === 'SNOOZED') process.stdout.write(`SNOOZED ${payload.until}\n`);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// ---------------------------------------------------------------------------
|
|
324
|
+
// main
|
|
325
|
+
// ---------------------------------------------------------------------------
|
|
326
|
+
|
|
327
|
+
async function main() {
|
|
328
|
+
const args = parseArgs(process.argv.slice(2));
|
|
329
|
+
if (args.help) {
|
|
330
|
+
help();
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
const stateDir = args.stateDir || defaultStateDir();
|
|
335
|
+
const packageName = args.packageName || PACKAGE_NAME;
|
|
336
|
+
|
|
337
|
+
if (args.reset) {
|
|
338
|
+
resetState(stateDir);
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (args.snooze) {
|
|
343
|
+
const now = Date.now();
|
|
344
|
+
const prior = readState(stateDir) || {};
|
|
345
|
+
const parsed = parseSnoozeArg(args.snooze, now, prior.snoozeLevel || 0);
|
|
346
|
+
if (parsed.clear) {
|
|
347
|
+
writeState(stateDir, { ...prior, snoozeUntil: null, snoozeLevel: 0 });
|
|
348
|
+
} else {
|
|
349
|
+
writeState(stateDir, {
|
|
350
|
+
...prior,
|
|
351
|
+
snoozeUntil: parsed.until,
|
|
352
|
+
snoozeLevel: parsed.level,
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const installed = readInstalledVersion(args.installedVersion);
|
|
359
|
+
if (!installed) {
|
|
360
|
+
// Installed version undetermined — nothing useful to report.
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
const now = Date.now();
|
|
365
|
+
let state = readState(stateDir);
|
|
366
|
+
|
|
367
|
+
// Snooze short-circuits everything except --force.
|
|
368
|
+
if (!args.force && isSnoozed(state, now)) {
|
|
369
|
+
emit(args, 'SNOOZED', { until: state.snoozeUntil });
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// Use cached `latest` when the cache is fresh (unless --force).
|
|
374
|
+
let latest = state && state.latest;
|
|
375
|
+
if (args.force || !isCacheFresh(state, now, CACHE_TTL_MS)) {
|
|
376
|
+
const fetched = await fetchLatestVersion(packageName);
|
|
377
|
+
if (fetched) {
|
|
378
|
+
latest = fetched;
|
|
379
|
+
const nextState = {
|
|
380
|
+
installed,
|
|
381
|
+
latest,
|
|
382
|
+
checkedAt: new Date(now).toISOString(),
|
|
383
|
+
snoozeUntil: (state && state.snoozeUntil) || null,
|
|
384
|
+
snoozeLevel: (state && state.snoozeLevel) || 0,
|
|
385
|
+
};
|
|
386
|
+
writeState(stateDir, nextState);
|
|
387
|
+
state = nextState;
|
|
388
|
+
}
|
|
389
|
+
// If fetched is null (network fail), we keep using the previous cache
|
|
390
|
+
// — or emit nothing if there's no cache at all.
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
if (!latest) {
|
|
394
|
+
// No cached value and no fetch — nothing to say.
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
if (compareVersions(installed, latest) < 0) {
|
|
399
|
+
emit(args, 'UPDATE_AVAILABLE', { installed, latest });
|
|
400
|
+
} else {
|
|
401
|
+
emit(args, 'UPTODATE', { installed, latest });
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
module.exports = {
|
|
406
|
+
parseArgs,
|
|
407
|
+
compareVersions,
|
|
408
|
+
isCacheFresh,
|
|
409
|
+
isSnoozed,
|
|
410
|
+
computeNextSnoozeUntil,
|
|
411
|
+
parseSnoozeArg,
|
|
412
|
+
readState,
|
|
413
|
+
writeState,
|
|
414
|
+
resetState,
|
|
415
|
+
fetchLatestVersion,
|
|
416
|
+
readInstalledVersion,
|
|
417
|
+
CACHE_TTL_MS,
|
|
418
|
+
PACKAGE_NAME,
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
if (require.main === module) {
|
|
422
|
+
main().catch((err) => {
|
|
423
|
+
// Never throw out of the CLI — the preamble must not break skill invocation.
|
|
424
|
+
process.stderr.write(`update-check: ${err.message}\n`);
|
|
425
|
+
process.exit(0);
|
|
426
|
+
});
|
|
427
|
+
}
|