Skip to content

Commit

Permalink
Merge branch 'release/7.0.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
nsteenbeek committed Feb 10, 2023
2 parents 996ff96 + 9831af1 commit 70fb56f
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 74 deletions.
2 changes: 1 addition & 1 deletion bin/main.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@hso/d365-cli",
"version": "6.2.0",
"version": "7.0.0",
"author": "HSO Innovation <[email protected]> (https://www.hso.com)",
"description": "Dynamics 365 Command Line Interface for TypeScript projects for Dataverse",
"repository": {
Expand Down
44 changes: 8 additions & 36 deletions src/commands/Update.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as colors from 'colors';
import shell from 'shelljs';
import fs from 'fs';
import {WebresourcesCrmJson} from '../root/Webresources/CrmJson';
import {CrmJson} from '../root/CrmJson';
import cp from 'child_process';

Expand Down Expand Up @@ -87,10 +86,10 @@ export class Update {
const fileData = String(fs.readFileSync(filepath));
const match = fileData.match(new RegExp(`specify Form onLoad function: ${crm.publisher_prefix}.${crm.namespace}.([^\\W]*).Form.onLoad`));
if (match) {
const entityName_formName = match[1];
const split = entityName_formName.split('_');
const newFileData = fileData.replace(new RegExp(entityName_formName, 'ig'), `${split[0]}.${split[1]}`);
shell.ShellString(newFileData).to(filepath);
// const entityName_formName = match[1];
// const split = entityName_formName.split('_');
// const newFileData = fileData.replace(new RegExp(entityName_formName, 'ig'), `${split[0]}.${split[1]}`);
// shell.ShellString(newFileData).to(filepath);
}
});

Expand Down Expand Up @@ -119,10 +118,10 @@ export class Update {
const fileData = String(fs.readFileSync(filepath));
const match = fileData.match(new RegExp('export class ([a-zA-Z]*)Form {'));
if (match) {
const entityName = match[1];
const importString = `import {${entityName}FormContext} from './${entityName}.formContext';`;
const newExportString = `export class ${entityName}Form extends ${entityName}FormContext {`;
shell.sed('-i', new RegExp(`export class ${entityName}Form {`, 'i'), `${importString}\n${newExportString}`, filepath);
// const entityName = match[1];
// const importString = `import {${entityName}FormContext} from './${entityName}.formContext';`;
// const newExportString = `export class ${entityName}Form extends ${entityName}FormContext {`;
// shell.sed('-i', new RegExp(`export class ${entityName}Form {`, 'i'), `${importString}\n${newExportString}`, filepath);
}
}
});
Expand Down Expand Up @@ -183,33 +182,6 @@ export class Update {

// eslint-disable-next-line max-lines-per-function
private static updateCrmJson(): void {
if (fs.existsSync('./tools/crm.json')) {
//crm.json
const crmSettings: CrmJson = JSON.parse(fs.readFileSync('./tools/crm.json', 'utf8'));
shell.cp('-R', `${__dirname}/root/crm.json`, '../');
shell.sed('-i', new RegExp('<%= publisher_prefix %>', 'ig'), crmSettings.crm.publisher_prefix, '../crm.json');
shell.sed('-i', new RegExp('<%= environment %>', 'ig'), crmSettings.crm.url, '../crm.json');
shell.sed('-i', new RegExp('<%= namespace %>', 'ig'), (crmSettings as unknown as {webresource: {namespace:string} }).webresource.namespace, '../crm.json');
if (shell.test('-e', '../.git')) {
cp.execFileSync('git', ['add', '../crm.json']);
}

// Webresources/crm.json
const webresourcesSettings: WebresourcesCrmJson = JSON.parse(fs.readFileSync('./tools/crm.json', 'utf8'));
shell.cp('-R', `${__dirname}/root/Webresources/crm.json`, '.');
shell.sed('-i', new RegExp('<%= solution_name_deploy %>', 'ig'), webresourcesSettings.crm.solution_name_deploy, './crm.json');
shell.sed('-i', new RegExp('<%= solution_name_generate %>', 'ig'), webresourcesSettings.crm.solution_name_generate, './crm.json');
if (shell.test('-e', '../.git')) {
cp.execFileSync('git', ['add', './crm.json']);
}
// shell.exec('git add ./crm.json');

shell.rm('-rf', `./tools`);
if (shell.test('-e', '../.git')) {
cp.execFileSync('git', ['rm', './tools']);
}
// shell.exec('git rm ./tools');
}
const crmSettings: CrmJson = JSON.parse(fs.readFileSync('../crm.json', 'utf8'));
shell.cp('-R', `${__dirname}/root/crm.json`, '../');
shell.sed('-i', new RegExp('<%= publisher_prefix %>', 'ig'), crmSettings.crm.publisher_prefix, '../crm.json');
Expand Down
17 changes: 10 additions & 7 deletions src/commands/generators/Entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ export class Entity {
private readonly options: EntityOptions;
private entityLogicalName: string;

constructor(bearer: string, entityName: string, options: EntityOptions) {
constructor(bearer: string, entityName: string, entityLogicalName: string, options: EntityOptions) {
this.bearer = bearer;
this.entityName = entityName;
this.entityLogicalName = entityLogicalName;
this.options = options;
}

Expand All @@ -46,12 +47,14 @@ export class Entity {
private async generateEntityFiles(): Promise<void> {
const serviceFilepath = `src/${this.entityName}/${this.entityName}.service.ts`;
if (!shell.test('-f', serviceFilepath)) {
const answers = await inquirer.prompt([{
type: 'input',
name: 'entityLogicalName',
message: 'Entity LogicalName:'
}]);
this.entityLogicalName = answers.entityLogicalName;
if (!this.entityLogicalName) {
const answers = await inquirer.prompt([{
type: 'input',
name: 'entityLogicalName',
message: 'Entity LogicalName:'
}]);
this.entityLogicalName = answers.entityLogicalName;
}
try {
await NodeApi.getEntityDefinition(this.entityLogicalName, this.bearer, ['PrimaryIdAttribute']);
} catch (e) {
Expand Down
77 changes: 49 additions & 28 deletions src/commands/generators/Regenerator.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,12 @@
import * as shell from 'shelljs';
import fs from 'fs';
import {Entity} from './Entity';
import {GlobalOptionSet} from './GlobalOptionSet';
import {EnvironmentVariable} from './EnvironmentVariable';

// TODO duplicate with webpack.config.ts
interface BuildJson {
forms: FormJson[];
webresources: WebresourceJson[];
}
// TODO duplicate with webpack.config.ts
interface FormJson {
name: string;
build: boolean;
}
// TODO duplicate with webpack.config.ts
interface WebresourceJson extends FormJson {
template: 'React' | 'HTML';
}
import {WebresourcesCrmJson} from '../../root/Webresources/CrmJson';
import {SolutionService} from '../../node/Solution/Solution.service';
import {SolutionComponentService} from '../../node/SolutionComponent/SolutionComponent.service';
import {EntityService} from '../../node/Entity/Entity.service';
import { EntityModel } from '../../node/Entity/Entity.model';

export class Regenerator {
private readonly bearer: string;
Expand All @@ -35,19 +24,51 @@ export class Regenerator {
}

private async regenerateEntities(): Promise<void> {
const buildFiles = shell.ls('./src/**/build.json');
for (const filepath of buildFiles) {
const pathSplit = filepath.split('/');
const entityName = pathSplit[pathSplit.length - 2];
const buildJsonString = String(fs.readFileSync(filepath));
const buildJson = JSON.parse(buildJsonString) as BuildJson;
const {forms} = buildJson;
if (forms.length > 0) {
console.log(`hso-d365 generate Entity ${entityName}`);
const entity = new Entity(this.bearer, entityName,{});
await entity.generate();
}
const entityModels = await this.getEntities();
for (const entityModel of entityModels) {
const physicalName = entityModel.originallocalizedname || entityModel.physicalname;
const folderName = physicalName.replaceAll(' ', '');
const entity = new Entity(this.bearer, folderName, entityModel.logicalname, {});
await entity.generate();
}
}

// eslint-disable-next-line max-lines-per-function
private async getEntities(): Promise<EntityModel[]> {
const settings: WebresourcesCrmJson = JSON.parse(fs.readFileSync('./crm.json', 'utf8'));
const {solution_name_generate} = settings.crm;
const solution = await SolutionService.getSolution(solution_name_generate, ['solutionid'], this.bearer);
const filters: Filter[] = [{
type: 'or',
conditions: [{
attribute: 'componenttype',
value: 1 // Entity
}]
}, {
conditions: [{
attribute: '_solutionid_value',
value: solution.solutionid
}]
}];
const solutionComponents = await SolutionComponentService.retrieveMultipleRecords({
select: ['objectid'],
filters: filters,
}, this.bearer);
const conditions: Condition[] = [];
for (const solutionComponent of solutionComponents) {
const objectid = solutionComponent.objectid;
conditions.push({
attribute: 'entityid',
value: objectid,
});
}
return EntityService.retrieveMultipleRecords({
select: ['entityid', 'collectionname', 'entitysetname', 'logicalname', 'name', 'objecttypecode', 'physicalname', 'originallocalizedname'],
filters: [{
type: 'or',
conditions: conditions
}]
}, this.bearer);
}

private async regenerateGlobalOptionSets(): Promise<void> {
Expand Down
12 changes: 12 additions & 0 deletions src/node/Entity/Entity.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

export interface EntityModel extends Model {
entityid?: string;
collectionname?: string;
entitysetname?: string;
logicalname?: string;
name?: string;
objecttypecode?: number;
originallocalizedname?: string;
physicalname?: string;
solutionid?: string;
}
10 changes: 10 additions & 0 deletions src/node/Entity/Entity.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {NodeApi} from '../NodeApi/NodeApi';
import {EntityModel} from './Entity.model';

export class EntityService {
private static entitySetName = 'entities';

public static async retrieveMultipleRecords(multipleSystemQueryOptions: MultipleSystemQueryOptions, bearer: string): Promise<EntityModel[]> {
return NodeApi.retrieveMultipleRecords(EntityService.entitySetName, multipleSystemQueryOptions, bearer);
}
}
2 changes: 1 addition & 1 deletion src/routers/EntityRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class EntityRouter extends MsalRouter {
}

protected async onAuthenticated(): Promise<void> {
const entity = new Entity(this.bearer, this.entityName, this.options);
const entity = new Entity(this.bearer, this.entityName, null, this.options);
await entity.generate();
}
}

0 comments on commit 70fb56f

Please sign in to comment.