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.
- package/.github/workflows/ci.yml +16 -11
- package/index.js +268 -67
- package/package.json +1 -1
package/.github/workflows/ci.yml
CHANGED
|
@@ -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
|
-
|
|
380
|
+
const safeName = projectName.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "");
|
|
381
381
|
|
|
382
|
-
|
|
383
|
-
|
|
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
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
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
|
-
|
|
397
|
-
write(path.join(dir, "
|
|
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
|
-
|
|
400
|
-
|
|
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
|
-
<
|
|
406
|
-
|
|
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
|
-
|
|
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
|
-
|
|
418
|
-
pac code init --outputDirectory .
|
|
613
|
+
Your app is already running. Open your AI assistant and copy one of these prompts.
|
|
419
614
|
|
|
420
|
-
|
|
421
|
-
npm install
|
|
615
|
+
---
|
|
422
616
|
|
|
423
|
-
##
|
|
424
|
-
"I'm building a Power Apps Code App called ${projectName} using React and TypeScript.
|
|
425
|
-
|
|
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
|
-
|
|
624
|
+
---
|
|
428
625
|
|
|
429
|
-
|
|
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
|
-
|
|
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
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
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
|
-
|
|
467
|
-
log.
|
|
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.
|
|
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": {
|