Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/Dataverse/CodeApp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,17 @@ Or use the SDK approach:

### Build-time targets

1. **CheckCodeAppPrereqs** -- validates that `package.json` exists and that `node` / `npm` are available in PATH. Runs only when `RunNodeBuild` is `true` (auto-detected from the presence of `package.json`).
2. **BuildCodeApp** (runs before `Build`, depends on `CheckCodeAppPrereqs`) -- executes `npm install` followed by `npm run build` in the project root directory.
3. **CopyCodeAppDist** (runs after `Build`) -- copies the `dist/` folder to `$(OutputPath)$(AppName)\`. Fails the build if `dist/` is missing or if `AppName` is not set.
1. **CheckNodePrereqs** / **NodeInstallPackagesWithLock** / **NodeInstallPackagesWithoutLock** -- shared Node.js targets from `TALXIS.DevKit.Build.Dataverse.Tasks` that validate `package.json`, check `node` / `npm`, and install packages in the project root when `RunNodeBuild` is enabled.
2. **BuildCodeApp** (runs before `Build`, depends on the shared Node.js targets) -- executes `npm run $(NodeBuildScript)` in the project root directory and passes `NODE_ENV` plus `BUILD_OUTPUT_DIR` to the npm script.
3. **CopyCodeAppDist** (runs after `Build`) -- copies the npm build output to `$(OutputPath)$(AppName)\`, preferring `$(NodeBuildOutputDir)` and falling back to `dist/`. Fails the build if no output folder is found or if `AppName` is not set.
4. **CopyCodeAppDistPublish** (runs after `Publish`) -- same as above, but copies to `$(PublishDir)` instead.

### Integration targets

These targets are called by `TALXIS.DevKit.Build.Dataverse.Solution` when it discovers this project via `ProjectReference`:

- **GetProjectType** -- returns `CodeApp` so the Solution build knows how to handle this reference.
- **GetCodeAppOutputs** (depends on `Build`) -- returns the path to the compiled `dist/` folder along with `AppName` and `ConfigPath` (location of `power.config.json`) metadata. The Solution project uses this to call `GenerateCodeAppMetaXml` and produce the `.meta.xml` file for PAC packaging.
- **GetCodeAppOutputs** (depends on `Build`) -- returns the path to the compiled npm output folder, preferring `$(NodeBuildOutputDir)` and falling back to `dist/`, along with `AppName` and `ConfigPath` (location of `power.config.json`) metadata. The Solution project uses this to call `GenerateCodeAppMetaXml` and produce the `.meta.xml` file for PAC packaging.

### What happens in the Solution project

Expand All @@ -49,7 +49,7 @@ When a Solution project has a `ProjectReference` to a CodeApp project, the follo
1. **ProbeCodeApps** discovers the CodeApp reference by calling `GetProjectType`.
2. **BuildCodeApps** calls `GetCodeAppOutputs`, which triggers the full CodeApp build (npm install + build).
3. **PrepareCodeAppsSources** generates `.meta.xml` via `GenerateCodeAppMetaXml`, adds a `RootComponent` entry (Type 300) to `Solution.xml`, and ensures the `CanvasApps` node exists in `Customizations.xml`.
4. **CopyCodeAppsToMetadata** copies the CodeApp dist output into the solution metadata `CanvasApps/` folder before PAC packages the solution.
4. **CopyCodeAppsToMetadata** copies the resolved CodeApp build output into the solution metadata `CanvasApps/` folder before PAC packages the solution.

The CodeApp reference is automatically filtered out of the standard `ResolveProjectReferences` pipeline to avoid unnecessary assembly resolution.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<PropertyGroup>
<RunNodeBuild Condition="'$(RunNodeBuild)'=='' and Exists('$(MSBuildProjectDirectory)/package.json')">true</RunNodeBuild>
<RunNodeBuild Condition="'$(RunNodeBuild)'==''">false</RunNodeBuild>
</PropertyGroup>

<Target Name="CheckCodeAppPrereqs"
Condition="'$(RunNodeBuild)'=='true'">
<Error Condition="!Exists('$(MSBuildProjectDirectory)/package.json')" Text="CodeApp package.json not found in $(MSBuildProjectDirectory)" />
<Exec Command="node --version" IgnoreExitCode="true" />
<Error Condition="'$(MSBuildLastTaskResult)'!='True'" Text="Node.js not found in PATH. Install Node.js to build CodeApp." />
<Exec Command="npm --version" IgnoreExitCode="true" />
<Error Condition="'$(MSBuildLastTaskResult)'!='True'" Text="npm not found in PATH. Install Node.js (includes npm) to build CodeApp." />
</Target>

<Target Name="BuildCodeApp"
DependsOnTargets="CheckCodeAppPrereqs"
DependsOnTargets="CheckNodePrereqs;NodeInstallPackagesWithLock;NodeInstallPackagesWithoutLock"
BeforeTargets="Build"
Condition="'$(RunNodeBuild)'=='true'">
<Message Text="Running npm install in $(MSBuildProjectDirectory)" Importance="High" />
<Exec WorkingDirectory="$(MSBuildProjectDirectory)" Command="npm install" />
<Message Text="Running npm run build in $(MSBuildProjectDirectory)" Importance="High" />
<Exec WorkingDirectory="$(MSBuildProjectDirectory)" Command="npm run build" />
<Message Text="Running npm run $(NodeBuildScript) in $(MSBuildProjectDirectory)" Importance="High" />
<RunNodeTool FileName="npm" Arguments="run $(NodeBuildScript)" WorkingDirectory="$(MSBuildProjectDirectory)"
EnvironmentVariables="NODE_ENV=$(NodeEnvironment);BUILD_OUTPUT_DIR=$(NodeBuildOutputDir)" />
</Target>

<Target Name="CopyCodeAppDist"
Expand All @@ -31,10 +17,13 @@
<Error Condition="'$(AppName)'==''" Text="AppName property is not set. Set it in the project file." />

<ItemGroup>
<CodeAppDistFiles Include="$(MSBuildProjectDirectory)/dist/**/*.*" />
<CodeAppDistFiles Include="$(NodeBuildOutputDir)**/*.*"
Condition="Exists('$(NodeBuildOutputDir)')" />
<CodeAppDistFiles Include="$(MSBuildProjectDirectory)/dist/**/*.*"
Condition="'@(CodeAppDistFiles)'=='' and Exists('$(MSBuildProjectDirectory)/dist')" />
</ItemGroup>

<Error Condition="'@(CodeAppDistFiles)'==''" Text="No files found in $(MSBuildProjectDirectory)/dist. Ensure npm run build produces output in the dist folder." />
<Error Condition="'@(CodeAppDistFiles)'==''" Text="No files found in $(NodeBuildOutputDir) or $(MSBuildProjectDirectory)/dist. Ensure npm run $(NodeBuildScript) produces output in BUILD_OUTPUT_DIR or the dist folder." />

<Message Text="Copying CodeApp dist to $(OutputPath)$(AppName)/" Importance="High" />
<Copy SourceFiles="@(CodeAppDistFiles)" DestinationFiles="@(CodeAppDistFiles->'$(OutputPath)$(AppName)/%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="true" />
Expand All @@ -52,7 +41,13 @@
DependsOnTargets="Build"
Returns="@(_CodeAppOutputs)">
<ItemGroup>
<_CodeAppOutputs Include="$(MSBuildProjectDirectory)/dist">
<_CodeAppOutputs Include="$(NodeBuildOutputDir)"
Condition="Exists('$(NodeBuildOutputDir)')">
<AppName>$(AppName)</AppName>
<ConfigPath>$(MSBuildProjectDirectory)/power.config.json</ConfigPath>
</_CodeAppOutputs>
<_CodeAppOutputs Include="$(MSBuildProjectDirectory)/dist"
Condition="'@(_CodeAppOutputs)'=='' and Exists('$(MSBuildProjectDirectory)/dist')">
<AppName>$(AppName)</AppName>
<ConfigPath>$(MSBuildProjectDirectory)/power.config.json</ConfigPath>
</_CodeAppOutputs>
Expand All @@ -65,10 +60,13 @@
<Error Condition="'$(AppName)'==''" Text="AppName property is not set. Set it in the project file." />

<ItemGroup>
<CodeAppDistPublishFiles Include="$(MSBuildProjectDirectory)/dist/**/*.*" />
<CodeAppDistPublishFiles Include="$(NodeBuildOutputDir)**/*.*"
Condition="Exists('$(NodeBuildOutputDir)')" />
<CodeAppDistPublishFiles Include="$(MSBuildProjectDirectory)/dist/**/*.*"
Condition="'@(CodeAppDistPublishFiles)'=='' and Exists('$(MSBuildProjectDirectory)/dist')" />
</ItemGroup>

<Error Condition="'@(CodeAppDistPublishFiles)'==''" Text="No files found in $(MSBuildProjectDirectory)/dist. Ensure npm run build produces output in the dist folder." />
<Error Condition="'@(CodeAppDistPublishFiles)'==''" Text="No files found in $(NodeBuildOutputDir) or $(MSBuildProjectDirectory)/dist. Ensure npm run $(NodeBuildScript) produces output in BUILD_OUTPUT_DIR or the dist folder." />

<Message Text="Copying CodeApp dist to $(PublishDir)$(AppName)/" Importance="High" />
<Copy SourceFiles="@(CodeAppDistPublishFiles)" DestinationFiles="@(CodeAppDistPublishFiles->'$(PublishDir)$(AppName)/%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="true" />
Expand Down
64 changes: 12 additions & 52 deletions src/Dataverse/GenPage/README.md
Original file line number Diff line number Diff line change
@@ -1,63 +1,23 @@
# TALXIS.DevKit.Build.Dataverse.GenPage
# TALXIS DevKit Dataverse GenPage build support

MSBuild integration for Dataverse generative page (GenPage) projects. Transpiles TSX source files via TypeScript, patches in RuntimeTypes, generates config metadata, and exposes output targets for Solution projects to discover and integrate GenPages as `uxagentprojects`.
MSBuild integration for Dataverse GenPage projects.

## Installation
A GenPage project is a project-type marker only. It carries no Dataverse IDs or page metadata. Every `*.tsx` file outside excluded build folders is treated as a page, and the page name is the file name without extension.

```xml
<PackageReference Include="TALXIS.DevKit.Build.Dataverse.GenPage" Version="0.0.0.1" PrivateAssets="All" />
```

Or use the SDK approach:
## Project contract

```xml
<Project Sdk="TALXIS.DevKit.Build.Sdk/0.0.0.1">
<PropertyGroup>
<ProjectType>GenPage</ProjectType>
<GenPageId>{your-genpage-guid}</GenPageId>
<GenPageDataSources>datasource1,datasource2</GenPageDataSources>
</PropertyGroup>
</Project>
<PropertyGroup>
<ProjectType>GenPage</ProjectType>
</PropertyGroup>
```

## Prerequisites

- **Node.js** must be available on `PATH`
- **npx** must be available on `PATH`

The build will fail with a descriptive error if either is missing.

## How It Works

The package sets `ProjectType` to `GenPage` and disables `GenerateAssemblyInfo` by default since this is not a traditional .NET assembly project.

### Build-time targets

1. **CheckGenPagePrereqs** — validates that the main TSX file exists and `node`/`npx` are on `PATH`.
2. **TranspileGenPage** (runs before `Build`) — executes `tsc` via `npx` to transpile TSX to JS, then patches the output by stripping `RuntimeTypes` imports and prepending `RuntimeTypes.js` content if present.
3. **GenerateGenPageConfig** — generates `config.json` from project properties (`GenPageDataSources`).
4. **CopyGenPageOutputs** (runs after `Build`) — copies `page.tsx`, `page.compiled`, and `config.json` to the output directory.

### Integration targets

Called by `TALXIS.DevKit.Build.Dataverse.Solution` via `ProjectReference`:

- **GetProjectType** — returns `GenPage`.
- **GetGenPageOutputs** — exposes the compiled output folder and metadata for the solution to copy into `uxagentprojects/`.
Optional source files:

## MSBuild Properties
- `<PageName>.config.json`, otherwise shared `genpage.config.json`

| Property | Default | Description |
|----------|---------|-------------|
| `ProjectType` | `GenPage` | Marks the project for reference discovery by Solution projects. |
| `GenPageMainFile` | `page.tsx` | Main TSX source file to transpile. |
| `GenPageName` | `$(MSBuildProjectName)` | Name used for the output folder and metadata. |
| `GenPageId` | _(required)_ | GUID identifying this GenPage in Dataverse. |
| `GenPageDataSources` | _(empty)_ | Comma-separated list of data source identifiers. |
| `LangVersion` | `latest` | C# language version for the project. |
| `GenerateAssemblyInfo` | `false` | Disables auto-generated assembly info. |
Build output is normalized to `$(TargetDir)<PageName>.js` for each page.

## Related Packages
## Solution integration

- **Depends on**: `TALXIS.DevKit.Build.Dataverse.Tasks`
- **Consumed by**: `TALXIS.DevKit.Build.Dataverse.Solution` projects via `ProjectReference`
Solution projects discover referenced GenPage projects, call `GetGenPageOutputs`, ensure XML-only `uxagentprojects/<page-guid>/...` declarations exist in solution source, then project native `filecontent/` only into the SolutionPackager metadata working directory under `obj`.
Loading