@powerbuilder/skill 1.0.5 → 1.0.7

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/README.md CHANGED
@@ -42,6 +42,7 @@ The installer searches upward from your current directory to your home folder an
42
42
  ## Requirements
43
43
 
44
44
  - Node.js ≥ 18
45
+ - [Power Platform CLI (PAC)](https://learn.microsoft.com/en-us/power-platform/developer/cli/introduction) — authenticated via `pac auth create`
45
46
 
46
47
  ---
47
48
 
package/codeapp.md ADDED
@@ -0,0 +1,123 @@
1
+ # Power Apps Code App Skill
2
+
3
+ > Part of the **PowerBuilder** toolkit by TuongDoan — AI agent skills for the Microsoft Power Platform.
4
+
5
+ ---
6
+
7
+ ## What is a Code App?
8
+
9
+ Power Apps **Code Apps** let developers build custom web apps (React, Vue, or any framework) in their own IDE and run them natively on the Power Platform — with full access to Dataverse, 1,500+ connectors, Microsoft Entra authentication, and managed deployment.
10
+
11
+ You write real code. The platform handles hosting, security, licensing, and ALM.
12
+
13
+ **Key capabilities:**
14
+ - Build with modern web frameworks (React, TypeScript, Vite)
15
+ - Access Dataverse and 1,500+ Power Platform connectors directly from JavaScript
16
+ - Microsoft Entra authentication out of the box
17
+ - Publish and host line-of-business apps inside Power Platform
18
+ - Full DLP, Conditional Access, and governance policy support
19
+ - Simplified ALM and deployment via `pac code push`
20
+
21
+ 📖 [Official overview](https://learn.microsoft.com/en-us/power-apps/developer/code-apps/overview) · [Quickstart](https://learn.microsoft.com/en-us/power-apps/developer/code-apps/how-to/create-an-app-from-scratch)
22
+
23
+ ---
24
+
25
+ ## What Does This Skill Do?
26
+
27
+ This skill gives your AI agent (Claude, Cursor, or Google Antigravity) a complete, opinionated playbook for delivering Code Apps end-to-end:
28
+
29
+ | Phase | What happens |
30
+ |-------|-------------|
31
+ | **1. Scaffold** | `npx power-apps init` — creates the Vite + TypeScript project wired to Power Apps |
32
+ | **2. Database** | Plan a Dataverse star schema, generate `planning-payload.json` |
33
+ | **3. Provision** | Run `dataverse-flow.js` to create tables + relationships via Dataverse Web API |
34
+ | **4. Connect** | `pac code add-data-source` — binds generated TypeScript services to your tables |
35
+ | **5. Build UI** | 3-layer architecture: Components → Hooks → Generated Services. TailwindCSS default |
36
+ | **6. Test** | `playwright-cli` with `--headed --persistent` against the `apps.powerapps.com` Local Play URL |
37
+ | **7. Deploy** | `npm run build` then `pac code push` |
38
+
39
+ ---
40
+
41
+ ## Prerequisites
42
+
43
+ Before using this skill, ensure the following are set up on your machine:
44
+
45
+ ### 1. Node.js (LTS)
46
+ Download from [nodejs.org](https://nodejs.org). Verify with:
47
+ ```bash
48
+ node --version # should be v18 or higher
49
+ ```
50
+
51
+ ### 2. Power Platform CLI (PAC CLI)
52
+ Required for authenticating to Power Platform, adding data sources, and deploying apps.
53
+
54
+ **Install:**
55
+ ```bash
56
+ # macOS / Linux
57
+ npm install -g @microsoft/powerplatform-cli-osx
58
+ # Windows
59
+ npm install -g @microsoft/powerplatform-cli-windows
60
+ ```
61
+ Or download the [standalone installer](https://learn.microsoft.com/en-us/power-platform/developer/cli/introduction).
62
+
63
+ **Verify:**
64
+ ```bash
65
+ pac --version
66
+ ```
67
+
68
+ **Authenticate:**
69
+ ```bash
70
+ pac auth create
71
+ # A browser window will open — sign in with your Microsoft 365 account
72
+ ```
73
+
74
+ ### 3. A Power Platform Environment with Code Apps Enabled
75
+
76
+ Code Apps must be enabled by an admin in your environment:
77
+
78
+ 1. Go to [Power Platform admin center](https://admin.powerplatform.microsoft.com)
79
+ 2. Navigate to **Manage → Environments** → select your environment
80
+ 3. Go to **Settings → Product → Features**
81
+ 4. Find **Power Apps code apps** and toggle **Enable code apps** ON
82
+ 5. Click **Save**
83
+
84
+ ### 4. Power Apps Premium License
85
+
86
+ End-users running code apps require a **Power Apps Premium** license.
87
+ [See pricing](https://www.microsoft.com/power-platform/products/power-apps/pricing)
88
+
89
+ ### 5. Playwright CLI (auto-installed by this skill)
90
+ Used for automated E2E testing. Installed automatically when you run `npx @powerbuilder/skill codeapp`.
91
+
92
+ ---
93
+
94
+ ## Install This Skill
95
+
96
+ ```bash
97
+ npx @powerbuilder/skill codeapp
98
+ ```
99
+
100
+ The installer will:
101
+ 1. Detect your AI agent folders (`.claude`, `.cursor`, `.gemini`)
102
+ 2. Copy the skill files into each one
103
+ 3. Install `@playwright/cli` globally
104
+ 4. Open Power Apps in a persistent browser for first-time login
105
+
106
+ ---
107
+
108
+ ## Quick Start (after skill is installed)
109
+
110
+ Open your AI agent (Claude, Cursor, etc.) in an empty folder and ask:
111
+
112
+ > *"Create a Power Apps Code App for managing [your use case]"*
113
+
114
+ The agent will follow the skill's end-to-end phase sequence automatically.
115
+
116
+ ---
117
+
118
+ ## References
119
+
120
+ - [Power Apps code apps overview](https://learn.microsoft.com/en-us/power-apps/developer/code-apps/overview)
121
+ - [Quickstart: Create a code app from scratch](https://learn.microsoft.com/en-us/power-apps/developer/code-apps/how-to/create-an-app-from-scratch)
122
+ - [Power Platform CLI reference](https://learn.microsoft.com/en-us/power-platform/developer/cli/introduction)
123
+ - [Dataverse Web API](https://learn.microsoft.com/en-us/power-apps/developer/data-platform/webapi/overview)
package/lib/banner.js CHANGED
@@ -4,15 +4,14 @@ export function printBanner() {
4
4
  const cyan = chalk.cyanBright.bold;
5
5
  const yellow = chalk.yellowBright.bold;
6
6
  const dim = chalk.dim;
7
- const green = chalk.greenBright;
8
7
 
9
8
  console.log();
10
- console.log(cyan(' ██████╗ ██████╗ ██╗ ██╗███████╗██████╗ ██████╗ ██╗ ██╗██╗██╗ ██████╗ ███████╗██████╗ '));
11
- console.log(cyan(' ██╔══██╗██╔═══██╗██║ ██║██╔════╝██╔══██╗██╔══██╗██║ ██║██║██║ ██╔══██╗██╔════╝██╔══██╗'));
12
- console.log(cyan(' ██████╔╝██║ ██║██║ █╗ ██║█████╗ ██████╔╝██████╔╝██║ ██║██║██║ ██║ ██║█████╗ ██████╔╝'));
13
- console.log(cyan(' ██╔═══╝ ██║ ██║██║███╗██║██╔══╝ ██╔══██╗██╔══██╗██║ ██║██║██║ ██║ ██║██╔══╝ ██╔══██╗'));
14
- console.log(cyan(' ██║ ╚██████╔╝╚███╔███╔╝███████╗██║ ██║██████╔╝╚██████╔╝██║███████╗██████╔╝███████╗██║ ██║'));
15
- console.log(cyan(' ╚═╝ ╚═════╝ ╚══╝╚══╝ ╚══════╝╚═╝ ╚═╝╚═════╝ ╚═════╝ ╚═╝╚══════╝╚═════╝ ╚══════╝╚═╝ ╚═╝'));
9
+ console.log(cyan(' ██████╗ ██████╗ ██╗ ██╗███████╗██████╗ ██████╗ ██╗ ██╗██╗██╗ ██████╗ ███████╗██████╗ '));
10
+ console.log(cyan(' ██╔══██╗██╔═══██╗██║ ██║██╔════╝██╔══██╗ ██╔══██╗██║ ██║██║██║ ██╔══██╗██╔════╝██╔══██╗'));
11
+ console.log(cyan(' ██████╔╝██║ ██║██║ █╗ ██║█████╗ ██████╔╝ ██████╔╝██║ ██║██║██║ ██║ ██║█████╗ ██████╔╝'));
12
+ console.log(cyan(' ██╔═══╝ ██║ ██║██║███╗██║██╔══╝ ██╔══██╗ ██╔══██╗██║ ██║██║██║ ██║ ██║██╔══╝ ██╔══██╗'));
13
+ console.log(cyan(' ██║ ╚██████╔╝╚███╔███╔╝███████╗██║ ██║ ██████╔╝╚██████╔╝██║███████╗██████╔╝███████╗██║ ██║'));
14
+ console.log(cyan(' ╚═╝ ╚═════╝ ╚══╝╚══╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝╚══════╝╚═════╝ ╚══════╝╚═╝ ╚═╝'));
16
15
  console.log();
17
16
  console.log(' ' + yellow('⚡ Power Apps Code App Skill') + dim(' · by TuongDoan · © 2026'));
18
17
  console.log();
@@ -3,13 +3,10 @@ import { existsSync } from 'fs';
3
3
  import os from 'os';
4
4
 
5
5
  /**
6
- * Search for supported AI agent root folders starting from cwd up to home dir.
7
- * Returns an array of { target, agentFolder, dir } objects for each found target.
8
- *
9
- * Supported targets:
10
- * - .cursor → skills go into <target>/.cursor/rules/ (or just .cursor/skills/)
11
- * - .claude → skills go into <target>/.claude/skills/
12
- * - .gemini → skills go into <target>/.gemini/antigravity/skills/
6
+ * Detect where to install skills:
7
+ * - .cursor → optional: skip if folder doesn't exist
8
+ * - .gemini → optional: skip if folder doesn't exist
9
+ * - .claude → always: create ~/.claude if it doesn't exist
13
10
  */
14
11
  export function detectTargets(startDir = process.cwd()) {
15
12
  const home = os.homedir();
@@ -22,15 +19,15 @@ export function detectTargets(startDir = process.cwd()) {
22
19
  dirs.push(current);
23
20
  if (current === home) break;
24
21
  const parent = path.dirname(current);
25
- if (parent === current) break; // filesystem root
22
+ if (parent === current) break;
26
23
  current = parent;
27
24
  }
28
25
 
29
26
  for (const dir of dirs) {
30
27
  const cursorDir = path.join(dir, '.cursor');
31
- const claudeDir = path.join(dir, '.claude');
32
28
  const geminiDir = path.join(dir, '.gemini');
33
29
 
30
+ // .cursor — optional: only add if the folder already exists
34
31
  if (existsSync(cursorDir)) {
35
32
  targets.push({
36
33
  target: '.cursor',
@@ -40,15 +37,8 @@ export function detectTargets(startDir = process.cwd()) {
40
37
  dir,
41
38
  });
42
39
  }
43
- if (existsSync(claudeDir)) {
44
- targets.push({
45
- target: '.claude',
46
- label: 'Claude',
47
- agentFolder: claudeDir,
48
- skillsDir: path.join(claudeDir, 'skills'),
49
- dir,
50
- });
51
- }
40
+
41
+ // .gemini — optional: only add if the folder already exists
52
42
  if (existsSync(geminiDir)) {
53
43
  targets.push({
54
44
  target: '.gemini',
@@ -60,6 +50,16 @@ export function detectTargets(startDir = process.cwd()) {
60
50
  }
61
51
  }
62
52
 
53
+ // .claude — always install to home dir; folder will be created if missing
54
+ const claudeDir = path.join(home, '.claude');
55
+ targets.push({
56
+ target: '.claude',
57
+ label: 'Claude',
58
+ agentFolder: claudeDir,
59
+ skillsDir: path.join(claudeDir, 'skills'),
60
+ dir: home,
61
+ });
62
+
63
63
  // Deduplicate by agentFolder
64
64
  const seen = new Set();
65
65
  return targets.filter(t => {
@@ -47,11 +47,45 @@ function runSilent(cmd) {
47
47
  }
48
48
  }
49
49
 
50
+ function runOutput(cmd) {
51
+ try {
52
+ return execSync(cmd, { stdio: 'pipe', encoding: 'utf8' });
53
+ } catch {
54
+ return null;
55
+ }
56
+ }
57
+
50
58
  // ─── skill asset path ────────────────────────────────────────────────────────
51
59
 
52
60
  // When installed via npm the skill files are at ../../skills/codeapp relative to this file
53
61
  const SKILL_SRC = path.resolve(__dirname, '..', 'skills', 'codeapp');
54
62
 
63
+ // ─── PRE-FLIGHT — Check PAC CLI auth ─────────────────────────────────────────
64
+
65
+ async function stepCheckPacCli() {
66
+ const output = runOutput('pac auth list');
67
+
68
+ // null = command failed to run = pac not installed
69
+ if (output === null) {
70
+ console.log();
71
+ err('Power Platform CLI (pac) was not found on this machine.');
72
+ log(chalk.dim(' Install it from: https://learn.microsoft.com/en-us/power-platform/developer/cli/introduction'));
73
+ log(chalk.dim(' Or via npm: npm install -g @microsoft/powerplatform-cli-osx'));
74
+ console.log();
75
+ process.exit(1);
76
+ }
77
+
78
+ // pac is installed but no auth profile exists
79
+ if (output.includes('No profiles were found on this computer')) {
80
+ console.log();
81
+ warn('PAC CLI is installed but no authenticated profile was found.');
82
+ log(` Run ${chalk.cyanBright('pac auth create')} to sign in, then re-run this installer.`);
83
+ console.log();
84
+ process.exit(1);
85
+ }
86
+ }
87
+
88
+
55
89
  // ─── STEP 1 — Detect & confirm targets ───────────────────────────────────────
56
90
 
57
91
  async function stepDetectTargets() {
@@ -205,6 +239,8 @@ async function stepOpenPowerApps() {
205
239
  // ─── MAIN ─────────────────────────────────────────────────────────────────────
206
240
 
207
241
  export async function runCodeAppWizard() {
242
+ // Pre-flight: verify PAC CLI is installed and authenticated
243
+ await stepCheckPacCli();
208
244
  // Detect first, show summary, confirm — then execute
209
245
  const targets = await stepDetectTargets();
210
246
  await stepShowSummary(targets);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@powerbuilder/skill",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "PowerBuilder skill installer — drop production-ready AI agent skills into .cursor, .claude, or .gemini folders with one command.",
5
5
  "author": "TuongDoan",
6
6
  "license": "MIT",
@@ -11,7 +11,8 @@
11
11
  "files": [
12
12
  "bin/",
13
13
  "lib/",
14
- "skills/"
14
+ "skills/",
15
+ "codeapp.md"
15
16
  ],
16
17
  "dependencies": {
17
18
  "chalk": "^5.3.0",