create-powerapp 1.0.0 → 1.1.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.
@@ -30,8 +30,7 @@ jobs:
30
30
  npm --version
31
31
 
32
32
  - name: Scaffold Canvas App (Copilot)
33
- run: |
34
- printf 'test-canvas\n1\n1\n\n' | node index.js
33
+ run: printf 'test-canvas\n1\n1\n\n' | node index.js
35
34
  shell: bash
36
35
 
37
36
  - name: Check Canvas App files exist
@@ -47,8 +46,7 @@ jobs:
47
46
  shell: bash
48
47
 
49
48
  - name: Scaffold Model-Driven App (Claude Code)
50
- run: |
51
- printf 'test-mda\n2\n2\n\n' | node index.js
49
+ run: printf 'test-mda\n2\n2\n\n' | node index.js
52
50
  shell: bash
53
51
 
54
52
  - name: Check MDA files exist
@@ -60,13 +58,11 @@ jobs:
60
58
  shell: bash
61
59
 
62
60
  - name: Scaffold PCF Component
63
- run: |
64
- printf 'test-pcf\n3\n1\n\n' | node index.js
61
+ run: printf 'test-pcf\n3\n1\n\n' | node index.js
65
62
  shell: bash
66
63
 
67
64
  - name: Scaffold Power Pages
68
- run: |
69
- printf 'test-pages\n4\n2\n\n' | node index.js
65
+ run: printf 'test-pages\n4\n2\n\n' | node index.js
70
66
  shell: bash
71
67
 
72
68
  - name: Check Power Pages folder structure
@@ -76,19 +72,28 @@ jobs:
76
72
  test -d test-pages/site/web-templates
77
73
  shell: bash
78
74
 
79
- - name: Scaffold Code App
80
- run: |
81
- printf 'test-codeapp\n5\n1\n\n' | node index.js
75
+ - name: Scaffold Code App (auto npm install runs inside scaffold)
76
+ run: printf 'test-codeapp\n5\n1\n\n' | node index.js
82
77
  shell: bash
83
78
 
84
79
  - name: Check Code App files exist
85
80
  run: |
86
81
  test -f test-codeapp/package.json
87
82
  test -f test-codeapp/tsconfig.json
83
+ test -f test-codeapp/vite.config.ts
84
+ test -f test-codeapp/index.html
85
+ test -f test-codeapp/src/main.tsx
88
86
  test -f test-codeapp/src/App.tsx
87
+ test -f test-codeapp/src/App.module.css
88
+ test -f test-codeapp/src/index.css
89
+ test -f test-codeapp/src/vite-env.d.ts
89
90
  node -e "JSON.parse(require('fs').readFileSync('test-codeapp/package.json','utf8'))"
90
91
  shell: bash
91
92
 
93
+ - name: Code App — npm run build succeeds with zero errors
94
+ run: cd test-codeapp && npm run build
95
+ shell: bash
96
+
92
97
  lint:
93
98
  name: Check syntax
94
99
  runs-on: ubuntu-latest
package/index.js CHANGED
@@ -377,94 +377,290 @@ Explain the folder structure and what each folder contains."
377
377
  function scaffoldCodeApp(dir, projectName, aiTool) {
378
378
  log.info("Setting up Code App structure...");
379
379
 
380
- write(path.join(dir, "instructions", "codeapp-instructions.md"), `# Code App Instructions
380
+ const safeName = projectName.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "");
381
381
 
382
- ## Type: Power Apps Code App (Code-first web app)
383
- ## Project: ${projectName}
382
+ // ── package.json ──────────────────────────────────────────────────────────
383
+ // Uses Vite (not react-scripts/CRA which is deprecated and broken).
384
+ // @microsoft/power-apps is intentionally NOT listed here — it bundles
385
+ // a native addon (keytar) that fails to build on most machines.
386
+ // It is installed globally via: npm install -g @microsoft/power-apps
387
+ // and imported in app code once the user is ready to connect to Power Platform.
388
+ write(path.join(dir, "package.json"), JSON.stringify({
389
+ name: safeName,
390
+ version: "0.1.0",
391
+ private: true,
392
+ type: "module",
393
+ scripts: {
394
+ start: "vite",
395
+ build: "tsc && vite build",
396
+ preview: "vite preview",
397
+ },
398
+ dependencies: {
399
+ react: "^18.3.1",
400
+ "react-dom": "^18.3.1",
401
+ },
402
+ devDependencies: {
403
+ "@types/react": "^18.3.3",
404
+ "@types/react-dom": "^18.3.0",
405
+ "@vitejs/plugin-react": "^6.0.0",
406
+ typescript: "^5.5.3",
407
+ vite: "^8.0.0",
408
+ },
409
+ }, null, 2));
384
410
 
385
- - Standard web app (React/TypeScript) hosted on Power Platform
386
- - Use @microsoft/power-apps npm package to access connectors and platform APIs
387
- - Authentication is handled by Microsoft Entra — do not build custom auth
388
- - Call Power Platform connectors directly from JavaScript via the client library
389
- - Publish with pac code push — no manual deployment pipeline needed
390
- - Follows canvas app sharing limits and DLP policies set by admins
391
- - Not supported in Power Apps mobile app or Power Apps for Windows
392
- - Use npm start for local dev; the platform manages hosting in production
393
- - Admin must enable Code Apps in Power Platform Admin Center before publishing
411
+ // ── vite.config.ts ────────────────────────────────────────────────────────
412
+ write(path.join(dir, "vite.config.ts"), `import { defineConfig } from 'vite'
413
+ import react from '@vitejs/plugin-react'
414
+
415
+ // https://vitejs.dev/config/
416
+ export default defineConfig({
417
+ plugins: [react()],
418
+ server: {
419
+ port: 3000,
420
+ open: true, // automatically opens the browser on npm start
421
+ },
422
+ })
394
423
  `);
395
424
 
396
- write(path.join(dir, "src", "components", ".gitkeep"), "");
397
- write(path.join(dir, "public", ".gitkeep"), "");
425
+ // ── tsconfig.json ─────────────────────────────────────────────────────────
426
+ write(path.join(dir, "tsconfig.json"), JSON.stringify({
427
+ compilerOptions: {
428
+ target: "ES2020",
429
+ useDefineForClassFields: true,
430
+ lib: ["ES2020", "DOM", "DOM.Iterable"],
431
+ module: "ESNext",
432
+ skipLibCheck: true,
433
+ moduleResolution: "bundler",
434
+ allowImportingTsExtensions: true,
435
+ isolatedModules: true,
436
+ moduleDetection: "force",
437
+ noEmit: true,
438
+ jsx: "react-jsx",
439
+ strict: true,
440
+ noUnusedLocals: true,
441
+ noUnusedParameters: true,
442
+ noFallthroughCasesInSwitch: true,
443
+ },
444
+ include: ["src"],
445
+ }, null, 2));
446
+
447
+ // ── index.html ────────────────────────────────────────────────────────────
448
+ // Vite requires index.html at the project root (not inside /public)
449
+ write(path.join(dir, "index.html"), `<!DOCTYPE html>
450
+ <html lang="en">
451
+ <head>
452
+ <meta charset="UTF-8" />
453
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
454
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
455
+ <title>${projectName}</title>
456
+ </head>
457
+ <body>
458
+ <div id="root"></div>
459
+ <script type="module" src="/src/main.tsx"></script>
460
+ </body>
461
+ </html>
462
+ `);
463
+
464
+ // ── public/favicon.svg ────────────────────────────────────────────────────
465
+ write(path.join(dir, "public", "favicon.svg"), `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
466
+ <rect width="32" height="32" rx="6" fill="#742774"/>
467
+ <text x="16" y="22" text-anchor="middle" font-size="18" fill="white" font-family="sans-serif">⚡</text>
468
+ </svg>
469
+ `);
470
+
471
+ // ── src/vite-env.d.ts ─────────────────────────────────────────────────────
472
+ // Required: tells TypeScript what *.module.css imports look like
473
+ write(path.join(dir, "src", "vite-env.d.ts"), `/// <reference types="vite/client" />
474
+
475
+ // CSS Modules
476
+ declare module '*.module.css' {
477
+ const classes: Record<string, string>
478
+ export default classes
479
+ }
480
+ `);
481
+
482
+ // ── src/main.tsx ──────────────────────────────────────────────────────────
483
+ write(path.join(dir, "src", "main.tsx"), `import { StrictMode } from 'react'
484
+ import { createRoot } from 'react-dom/client'
485
+ import App from './App'
486
+ import './index.css'
487
+
488
+ createRoot(document.getElementById('root')!).render(
489
+ <StrictMode>
490
+ <App />
491
+ </StrictMode>
492
+ )
493
+ `);
398
494
 
399
- write(path.join(dir, "src", "App.tsx"), `// ${projectName} — Code App entry point
400
- // Ask your AI assistant: "Set up the main App component for a Power Apps Code App called ${projectName}"
495
+ // ── src/App.tsx ───────────────────────────────────────────────────────────
496
+ write(path.join(dir, "src", "App.tsx"), `import styles from './App.module.css'
401
497
 
498
+ /**
499
+ * ${projectName}
500
+ *
501
+ * This is your app's root component. Start here.
502
+ *
503
+ * To connect to Power Platform data and connectors:
504
+ * 1. Install the CLI globally: npm install -g @microsoft/power-apps
505
+ * 2. Run: npx power-apps init (creates power.config.json)
506
+ * 3. Then import in your components:
507
+ * import { useData } from '@microsoft/power-apps'
508
+ *
509
+ * Ask your AI assistant: "Build the main layout for ${projectName}"
510
+ */
402
511
  export default function App() {
403
512
  return (
404
- <div>
405
- <h1>${projectName}</h1>
406
- <p>Ask your AI to build this app. Open the chat and describe what you want.</p>
513
+ <div className={styles.app}>
514
+ <header className={styles.header}>
515
+ <h1>${projectName}</h1>
516
+ <p>Your Power Apps Code App is running. Open your AI assistant and describe what to build.</p>
517
+ </header>
518
+ <main className={styles.main}>
519
+ <div className={styles.card}>
520
+ <h2>🚀 Ready to build</h2>
521
+ <p>Open Copilot Chat or Claude Code and paste a prompt from <code>prompts/starter.md</code></p>
522
+ </div>
523
+ </main>
407
524
  </div>
408
- );
525
+ )
409
526
  }
410
527
  `);
411
528
 
412
- write(path.join(dir, "src", "index.ts"), `// Entry point — ask your AI to fill this in
529
+ // ── src/App.module.css ────────────────────────────────────────────────────
530
+ write(path.join(dir, "src", "App.module.css"), `.app {
531
+ min-height: 100vh;
532
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
533
+ background: #f4f4f8;
534
+ color: #1a1a2e;
535
+ }
536
+
537
+ .header {
538
+ background: #742774;
539
+ color: white;
540
+ padding: 2rem;
541
+ text-align: center;
542
+ }
543
+
544
+ .header h1 {
545
+ margin: 0 0 0.5rem;
546
+ font-size: 2rem;
547
+ }
548
+
549
+ .header p {
550
+ margin: 0;
551
+ opacity: 0.85;
552
+ }
553
+
554
+ .main {
555
+ max-width: 800px;
556
+ margin: 2rem auto;
557
+ padding: 0 1rem;
558
+ }
559
+
560
+ .card {
561
+ background: white;
562
+ border-radius: 8px;
563
+ padding: 1.5rem 2rem;
564
+ box-shadow: 0 2px 8px rgba(0,0,0,0.08);
565
+ }
566
+
567
+ .card h2 { margin-top: 0; }
568
+ `);
569
+
570
+ // ── src/index.css ─────────────────────────────────────────────────────────
571
+ write(path.join(dir, "src", "index.css"), `*, *::before, *::after { box-sizing: border-box; }
572
+ body { margin: 0; }
573
+ `);
574
+
575
+ // ── src/components/ placeholder ───────────────────────────────────────────
576
+ write(path.join(dir, "src", "components", ".gitkeep"), "");
577
+
578
+ // ── instructions ─────────────────────────────────────────────────────────
579
+ write(path.join(dir, "instructions", "codeapp-instructions.md"), `# Code App Instructions
580
+
581
+ ## Type: Power Apps Code App (Code-first web app)
582
+ ## Project: ${projectName}
583
+
584
+ ### Tech stack (already installed — DO NOT change)
585
+ - Vite ^8 as the dev server and bundler (npm start = vite)
586
+ - React 18 + TypeScript 5
587
+ - CSS Modules for styling (*.module.css files)
588
+ - NO react-scripts, NO Create React App, NO webpack
589
+
590
+ ### Connecting to Power Platform data
591
+ The @microsoft/power-apps client library is installed globally (not in package.json)
592
+ because it includes a native addon that must be compiled separately.
593
+ To add Power Platform data to a component:
594
+ 1. Run once: npm install -g @microsoft/power-apps
595
+ 2. Run once: npx power-apps init (creates power.config.json)
596
+ 3. Import in components: import { useData } from '@microsoft/power-apps'
597
+
598
+ ### Coding rules
599
+ - All components are React functional components with TypeScript types
600
+ - CSS goes in *.module.css files — import as: import styles from './Component.module.css'
601
+ - New pages/screens = new .tsx files in src/components/
602
+ - No class components, no .then() chains (use async/await)
603
+ - Never touch vite.config.ts or tsconfig.json unless asked
604
+
605
+ ### To publish to Power Platform
606
+ 1. npm run build (creates dist/ folder)
607
+ 2. npx power-apps push (uploads to your environment)
413
608
  `);
414
609
 
610
+ // ── prompts/starter.md ────────────────────────────────────────────────────
415
611
  write(path.join(dir, "prompts", "starter.md"), `# Starter Prompts for ${projectName}
416
612
 
417
- ## First, initialise the Code App (run this command):
418
- pac code init --outputDirectory .
613
+ Your app is already running. Open your AI assistant and copy one of these prompts.
419
614
 
420
- ## Install dependencies:
421
- npm install
615
+ ---
422
616
 
423
- ## Then ask the AI:
424
- "I'm building a Power Apps Code App called ${projectName} using React and TypeScript.
425
- Set up the project with a clean layout, routing between pages, and connect it to Microsoft Entra authentication using the @microsoft/power-apps package."
617
+ ## Build the home screen
618
+ "I'm building a Power Apps Code App called ${projectName} using React and TypeScript with Vite.
619
+ Replace the placeholder home screen in src/App.tsx with a proper layout that has:
620
+ - A navigation bar at the top with the app name and a user avatar placeholder
621
+ - A main content area with cards showing [describe your main content]
622
+ - A clean, professional design using the existing CSS module pattern"
426
623
 
427
- "Add a page called [PageName] that [describe what the page does]."
624
+ ---
428
625
 
429
- "Connect this app to a Power Platform connector called [ConnectorName] and show the data in a table."
430
- `);
626
+ ## Add a new page
627
+ "Add a new page called [PageName] to this React app.
628
+ Create src/components/[PageName].tsx with [describe what the page does].
629
+ Add a navigation link to it in App.tsx."
431
630
 
432
- write(path.join(dir, "package.json"), JSON.stringify({
433
- name: projectName.toLowerCase().replace(/\s+/g, "-"),
434
- version: "0.1.0",
435
- private: true,
436
- scripts: {
437
- start: "react-scripts start",
438
- build: "react-scripts build",
439
- },
440
- dependencies: {
441
- "@microsoft/power-apps": "latest",
442
- react: "^18.0.0",
443
- "react-dom": "^18.0.0",
444
- },
445
- devDependencies: {
446
- typescript: "^5.0.0",
447
- "@types/react": "^18.0.0",
448
- "@types/react-dom": "^18.0.0",
449
- },
450
- }, null, 2));
631
+ ---
451
632
 
452
- write(path.join(dir, "tsconfig.json"), JSON.stringify({
453
- compilerOptions: {
454
- target: "ES2020",
455
- lib: ["ES2020", "DOM"],
456
- jsx: "react-jsx",
457
- module: "ESNext",
458
- moduleResolution: "bundler",
459
- strict: true,
460
- esModuleInterop: true,
461
- skipLibCheck: true,
462
- },
463
- include: ["src"],
464
- }, null, 2));
633
+ ## Add a data table
634
+ "Add a component called DataTable.tsx in src/components/ that displays a table of [describe your data].
635
+ Use mock data for now — I'll connect it to real data later.
636
+ Style it using a CSS module."
637
+
638
+ ---
639
+
640
+ ## Connect to Power Platform data
641
+ "I want to connect this app to Power Platform.
642
+ Walk me through:
643
+ 1. Installing @microsoft/power-apps globally
644
+ 2. Running npx power-apps init
645
+ 3. Adding a useData hook to fetch records from a Dataverse table called [TableName]"
646
+
647
+ ---
648
+
649
+ ## Fix a TypeScript error
650
+ "I got this TypeScript error in [filename]: [paste error]
651
+ Explain what it means and fix it."
652
+ `);
465
653
 
466
- log.ok("Code App structure created");
467
- log.dim("Next: pac code init --outputDirectory . then npm install");
654
+ // ── run npm install automatically ─────────────────────────────────────────
655
+ log.info("Running npm install (this takes about 30 seconds)...");
656
+ const installed = run("npm install", dir);
657
+ if (installed) {
658
+ log.ok("npm install completed — all dependencies ready");
659
+ } else {
660
+ log.warn("npm install had issues — try running npm install manually inside the project folder");
661
+ }
662
+
663
+ log.ok("Code App structure created — run npm start to launch the app");
468
664
  }
469
665
 
470
666
  // ─── AI context file writer ───────────────────────────────────────────────────
@@ -628,6 +824,7 @@ to open in VS Code and start prompting your AI assistant.
628
824
  }
629
825
 
630
826
  // ── Done ─────────────────────────────────────────────────────────────────
827
+ const isCodeApp = appTypeChoice.label === "Code App";
631
828
  console.log(`
632
829
  ${c.bold}${c.green}╔═══════════════════════════════════════════════════╗
633
830
  ║ ✅ Your project is ready! ║
@@ -638,9 +835,13 @@ ${c.bold}Project folder:${c.reset} ${dir}
638
835
  ${c.bold}What to do next:${c.reset}
639
836
 
640
837
  1. VS Code is now open (or open it manually and open the folder above)
641
-
838
+ ${isCodeApp ? `
839
+ 2. ${c.bold}${c.green}Start the app:${c.reset} In the VS Code terminal, run:
840
+ ${c.cyan}npm start${c.reset}
841
+ Your browser will open automatically at http://localhost:3000
842
+ ` : `
642
843
  2. Read the ${c.cyan}prompts/starter.md${c.reset} file for ready-made prompts to get started
643
-
844
+ `}
644
845
  3. Open your AI assistant:
645
846
  ${aiChoice.label === "Claude Code"
646
847
  ? ` • In the VS Code terminal, run: ${c.cyan}claude${c.reset}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-powerapp",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "One command to scaffold any Power Apps project — Canvas App, Model-Driven App, PCF Component, Power Pages, or Code App — with Git, AI context files, and everything ready so you can immediately start prompting your AI assistant.",
5
5
  "type": "module",
6
6
  "bin": {