create-powerapps-project 2.2.4 → 2.3.1

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.
@@ -58,7 +58,7 @@ export default (plop) => {
58
58
  plop.setActionType('runPcf', async (answers) => {
59
59
  const args = ['pcf', 'init', '-ns', answers.namespace, '-n', answers.name, '-t', answers.template, '-npm', 'false'];
60
60
  // Set framework to React if selected
61
- if (answers.react && answers.fluentVersion === 8) {
61
+ if (answers.react) {
62
62
  args.push('-fw', 'react');
63
63
  }
64
64
  console.log('running pac pcf command with args');
package/lib/plopfile.js CHANGED
@@ -284,16 +284,6 @@ export default async (plop) => {
284
284
  name: 'react',
285
285
  message: 'use react?'
286
286
  },
287
- {
288
- type: 'list',
289
- name: 'fluentVersion',
290
- message: 'select Fluent UI version',
291
- choices: [
292
- { name: 'v8', value: 8 },
293
- { name: 'v9', value: 9 }
294
- ],
295
- when: (answers) => answers.react
296
- },
297
287
  packageQuestion
298
288
  ],
299
289
  actions: (data) => {
@@ -302,30 +292,12 @@ export default async (plop) => {
302
292
  {
303
293
  type: 'runPcf'
304
294
  },
305
- {
306
- type: 'add',
307
- templateFile: '../plop-templates/pcf/tsconfig.json',
308
- path: path.resolve(process.cwd(), 'tsconfig.json'),
309
- force: true
310
- },
311
295
  {
312
296
  type: 'add',
313
297
  templateFile: '../plop-templates/pcf/plopfile.js',
314
298
  path: path.resolve(process.cwd(), 'plopfile.js'),
315
299
  force: true
316
300
  },
317
- {
318
- type: 'add',
319
- templateFile: '../plop-templates/pcf/.eslintrc.json',
320
- path: path.resolve(process.cwd(), '.eslintrc.json'),
321
- force: true
322
- },
323
- {
324
- type: 'add',
325
- templateFile: '../plop-templates/pcf/.gitattributes',
326
- path: path.resolve(process.cwd(), '.gitattributes'),
327
- force: true
328
- },
329
301
  {
330
302
  type: 'add',
331
303
  templateFile: '../plop-templates/pcf/App.tsx',
@@ -334,23 +306,6 @@ export default async (plop) => {
334
306
  if (!answers.react) {
335
307
  return 'react not included';
336
308
  }
337
- if (answers.fluentVersion === 9) {
338
- return 'using fluent v9';
339
- }
340
- return;
341
- }
342
- },
343
- {
344
- type: 'add',
345
- templateFile: '../plop-templates/pcf/AppFluent9.tsx.hbs',
346
- path: path.resolve(process.cwd(), '{{name}}', 'App.tsx'),
347
- skip: (answers) => {
348
- if (!answers.react) {
349
- return 'react not included';
350
- }
351
- if (answers.fluentVersion === 8) {
352
- return 'using fluent v8';
353
- }
354
309
  return;
355
310
  }
356
311
  },
@@ -365,24 +320,40 @@ export default async (plop) => {
365
320
  return;
366
321
  }
367
322
  },
368
- {
369
- type: 'add',
370
- templateFile: '../plop-templates/pcf/index.ts.hbs',
371
- path: path.resolve(process.cwd(), '{{name}}', 'index.ts'),
372
- force: true,
373
- skip: (answers) => {
374
- if (!answers.react || answers.fluentVersion === 8) {
375
- return 'not using Fluent UI v9';
376
- }
377
- return;
378
- }
379
- },
380
323
  {
381
324
  type: 'modify',
382
325
  path: `${process.cwd()}/{{name}}/index.ts`,
383
326
  pattern: 'import { HelloWorld, IHelloWorldProps } from "./HelloWorld";',
384
327
  template: `import { App } from './App';`
385
328
  },
329
+ {
330
+ type: 'append',
331
+ path: `${process.cwd()}/${path.basename(process.cwd())}.pcfproj`,
332
+ pattern: '</PowerAppsTargetsPath>',
333
+ template: `\t\t<PcfEnableAutoNpmInstall Condition=" '$(PcfEnableAutoNpmInstall)' == '' ">false</PcfEnableAutoNpmInstall>\r\n\t\t<PcfAlwaysNpmInstall Condition=" '$(PcfAlwaysNpmInstall)' == '' ">false</PcfAlwaysNpmInstall>`,
334
+ separator: '\n'
335
+ },
336
+ {
337
+ type: 'append',
338
+ path: `${process.cwd()}/eslint.config.mjs`,
339
+ pattern: 'reactPlugin.configs.flat.recommended,',
340
+ template: '\treactHooks.configs.flat.recommended,',
341
+ separator: '\n'
342
+ },
343
+ {
344
+ type: 'append',
345
+ path: `${process.cwd()}/eslint.config.mjs`,
346
+ pattern: `import reactPlugin from "eslint-plugin-react";`,
347
+ template: `import reactHooksPlugin from 'eslint-plugin-react-hooks';`,
348
+ separator: '\n'
349
+ },
350
+ {
351
+ type: 'append',
352
+ path: `${process.cwd()}/${path.basename(process.cwd())}.pcfproj`,
353
+ pattern: '</OutputPath>',
354
+ template: `\t\t<PcfBuildMode>development</PcfBuildMode>`,
355
+ separator: '\n'
356
+ },
386
357
  {
387
358
  type: 'modify',
388
359
  path: `${process.cwd()}/{{name}}/index.ts`,
@@ -392,9 +363,16 @@ export default async (plop) => {
392
363
  {
393
364
  type: 'modify',
394
365
  path: `${process.cwd()}/{{name}}/index.ts`,
395
- pattern: `const props: IHelloWorldProps = { name: 'Hello, World!' };`,
366
+ pattern: `const props: IHelloWorldProps = { name: 'Power Apps' };`,
396
367
  template: ''
397
368
  },
369
+ async (answers) => {
370
+ if (answers.react) {
371
+ await fs.promises.rm(path.resolve(process.cwd(), answers.name, 'HelloWorld.tsx'));
372
+ return 'removed default HelloWorld component';
373
+ }
374
+ return 'react not included';
375
+ },
398
376
  {
399
377
  type: 'addScript',
400
378
  data: {
@@ -413,14 +391,14 @@ export default async (plop) => {
413
391
  type: 'addScript',
414
392
  data: {
415
393
  scriptKey: 'push',
416
- scriptValue: `npm run select-auth && pac pcf version -s manifest && pac pcf push -pp ${data.prefix} -env ${data.server}`
394
+ scriptValue: `${data.package} run select-auth && pac pcf push -pp ${data.prefix} -env ${data.server}`
417
395
  }
418
396
  },
419
397
  {
420
398
  type: 'addScript',
421
399
  data: {
422
400
  scriptKey: 'push-inc',
423
- scriptValue: `npm run build && npm run select-auth && pac pcf version -s manifest && pac pcf push -pp ${data.prefix} -inc -env ${data.server}`
401
+ scriptValue: `${data.package} run build && ${data.package} run select-auth && pac pcf push -pp ${data.prefix} -inc -env ${data.server}`
424
402
  }
425
403
  },
426
404
  {
@@ -430,13 +408,6 @@ export default async (plop) => {
430
408
  scriptValue: `npx only-allow ${data.package}`
431
409
  }
432
410
  },
433
- async (answers) => {
434
- if (answers.react && answers.fluentVersion === 8) {
435
- await fs.promises.rm(path.resolve(process.cwd(), answers.name, 'HelloWorld.tsx'));
436
- return 'removed HelloWorld component';
437
- }
438
- return 'react not included';
439
- },
440
411
  {
441
412
  type: 'npmInstall'
442
413
  },
@@ -444,48 +415,14 @@ export default async (plop) => {
444
415
  type: 'npmInstall',
445
416
  data: {
446
417
  packages: {
447
- devDependencies: [
448
- 'powerapps-project-pcf',
449
- '@types/react@^16',
450
- '@types/react-dom@^16',
451
- 'eslint-plugin-react-hooks',
452
- '@types/xrm'
453
- ],
454
- dependencies: ['@fluentui/react-hooks']
418
+ devDependencies: ['powerapps-project-pcf', 'eslint-plugin-react-hooks', '@types/xrm'],
419
+ dependencies: ['@fluentui/react-icons']
455
420
  }
456
421
  },
457
422
  skip: (answers) => {
458
423
  if (!answers.react) {
459
424
  return 'react not included';
460
425
  }
461
- if (answers.fluentVersion === 9) {
462
- return 'using fluent v9';
463
- }
464
- return;
465
- }
466
- },
467
- {
468
- type: 'npmInstall',
469
- data: {
470
- packages: {
471
- devDependencies: [
472
- 'powerapps-project-pcf',
473
- '@types/react@^17',
474
- '@types/react-dom@^17',
475
- 'eslint-plugin-react-hooks',
476
- '@types/xrm',
477
- 'eslint-plugin-react'
478
- ],
479
- dependencies: ['@fluentui/react-hooks', '@fluentui/react-components', '@fluentui/react-icons', 'react@^17', 'react-dom@^17']
480
- }
481
- },
482
- skip: (answers) => {
483
- if (!answers.react) {
484
- return 'react not included';
485
- }
486
- if (answers.fluentVersion === 8) {
487
- return 'using fluent v8';
488
- }
489
426
  return;
490
427
  }
491
428
  }
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "create-powerapps-project",
3
3
  "description": "💧 plop generator for Dataverse development",
4
- "version": "2.2.4",
4
+ "version": "2.3.1",
5
5
  "license": "MIT",
6
6
  "exports": "./lib/index.js",
7
7
  "engines": {
8
- "node": ">=20.0.0"
8
+ "node": ">=22.0.0"
9
9
  },
10
10
  "bin": {
11
11
  "create-powerapps-project": "lib/index.js"
@@ -26,9 +26,6 @@
26
26
  },
27
27
  "type": "module",
28
28
  "dependencies": {
29
- "plop": "^3.1.2"
30
- },
31
- "volta": {
32
- "extends": "../../package.json"
29
+ "plop": "^4.0.4"
33
30
  }
34
31
  }
@@ -2,13 +2,9 @@ import React from 'react';
2
2
  import { IInputs } from './generated/ManifestTypes';
3
3
  import { AppContext } from './contexts/AppContext';
4
4
 
5
- export const App = (props: { context: ComponentFramework.Context<IInputs>; }) => {
6
- const {
7
- context
8
- } = props;
9
-
5
+ export const App = ({ context }: { context: ComponentFramework.Context<IInputs>; }) => {
10
6
  return (
11
- <AppContext.Provider value={{{ context }}}>
7
+ <AppContext.Provider value=\{{ context }}>
12
8
  </AppContext.Provider>
13
9
  );
14
10
  };
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { IInputs } from '../generated/ManifestTypes';
3
3
 
4
- interface IAppContext {
4
+ export interface IAppContext {
5
5
  context: ComponentFramework.Context<IInputs>;
6
6
  }
7
7
 
@@ -1,34 +0,0 @@
1
- {
2
- "env": {
3
- "browser": true,
4
- "es2021": true
5
- },
6
- "extends": [
7
- "eslint:recommended",
8
- "plugin:@typescript-eslint/recommended",
9
- "plugin:react/recommended",
10
- "plugin:react-hooks/recommended"
11
- ],
12
- "globals": {
13
- "ComponentFramework": true,
14
- "Xrm": true
15
- },
16
- "parser": "@typescript-eslint/parser",
17
- "parserOptions": {
18
- "ecmaVersion": 12,
19
- "sourceType": "module"
20
- },
21
- "plugins": [
22
- "@microsoft/power-apps",
23
- "@typescript-eslint"
24
- ],
25
- "rules": {
26
- "no-unused-vars": "off",
27
- "@typescript-eslint/no-empty-interface": "off"
28
- },
29
- "settings": {
30
- "react": {
31
- "version": "detect"
32
- }
33
- }
34
- }
@@ -1,3 +0,0 @@
1
- * text=auto eol=lf
2
- *.{cmd,[cC][mM][dD]} text eol=crlf
3
- *.{bat,[bB][aA][tT]} text eol=crlf
@@ -1,21 +0,0 @@
1
- import React from 'react';
2
- import { IInputs } from './generated/ManifestTypes';
3
- import { AppContext } from './contexts/AppContext';
4
- import { FluentProvider, IdPrefixProvider, webLightTheme } from '@fluentui/react-components';
5
-
6
- export const App = (props: { context: ComponentFramework.Context<IInputs>; }) => {
7
- const {
8
- context
9
- } = props;
10
-
11
- return (
12
- <IdPrefixProvider value="{{name}}">
13
- <FluentProvider theme={webLightTheme}>
14
- <AppContext.Provider value=\{{ context }}>
15
- </AppContext.Provider>
16
- </FluentProvider>
17
- </IdPrefixProvider>
18
- );
19
- };
20
-
21
- App.displayName = 'App';
@@ -1,58 +0,0 @@
1
- import { IInputs, IOutputs } from './generated/ManifestTypes';
2
- import { App } from './App';
3
- import ReactDOM from 'react-dom';
4
- import React from 'react';
5
-
6
- export class {{name}} implements ComponentFramework.StandardControl<IInputs, IOutputs> {
7
- container: HTMLDivElement;
8
- context: ComponentFramework.Context<IInputs>;
9
-
10
- /**
11
- * Used to initialize the control instance. Controls can kick off remote server calls and other initialization actions here.
12
- * Data-set values are not initialized here, use updateView.
13
- * @param context The entire property bag available to control via Context Object; It contains values as set up by the customizer mapped to property names defined in the manifest, as well as utility functions.
14
- * @param notifyOutputChanged A callback method to alert the framework that the control has new outputs ready to be retrieved asynchronously.
15
- * @param state A piece of data that persists in one session for a single user. Can be set at any point in a controls life cycle by calling 'setControlState' in the Mode interface.
16
- * @param container If a control is marked control-type='standard', it will receive an empty div element within which it can render its content.
17
- */
18
- public init(
19
- context: ComponentFramework.Context<IInputs>,
20
- notifyOutputChanged: () => void,
21
- state: ComponentFramework.Dictionary,
22
- container: HTMLDivElement
23
- ): void {
24
- this.context = context;
25
- this.container = container;
26
- this.context.mode.trackContainerResize(true);
27
- }
28
-
29
- /**
30
- * Called when any value in the property bag has changed. This includes field values, data-sets, global values such as container height and width, offline status, control metadata values such as label, visible, etc.
31
- * @param context The entire property bag available to control via Context Object; It contains values as set up by the customizer mapped to names defined in the manifest, as well as utility functions
32
- */
33
- public updateView(context: ComponentFramework.Context<IInputs>): void {
34
- ReactDOM.render(
35
- React.createElement(App, {
36
- context: context
37
- }),
38
- this.container
39
- );
40
- }
41
-
42
- /**
43
- * It is called by the framework prior to a control receiving new data.
44
- * @returns an object based on nomenclature defined in manifest, expecting object[s] for property marked as “bound” or “output”
45
- */
46
- public getOutputs(): IOutputs {
47
- return {
48
- };
49
- }
50
-
51
- /**
52
- * Called when the control is to be removed from the DOM tree. Controls should use this call for cleanup.
53
- * i.e. cancelling any pending remote calls, removing listeners, etc.
54
- */
55
- public destroy(): void {
56
- // Add code to cleanup control if necessary
57
- }
58
- }
@@ -1,10 +0,0 @@
1
- {
2
- "extends": "./node_modules/pcf-scripts/tsconfig_base.json",
3
- "compilerOptions": {
4
- "typeRoots": ["node_modules/@types"],
5
- "esModuleInterop": true,
6
- "target": "ES6",
7
- "module": "es2015",
8
- "moduleResolution": "node"
9
- }
10
- }