Skip to content

Commit

Permalink
Merge branch 'main' of github.com:SAP/open-ux-tools into fix/2589/sta…
Browse files Browse the repository at this point in the history
…tic-webapp-path

# Conflicts:
#	packages/adp-tooling/src/base/helper.ts
#	packages/adp-tooling/test/unit/preview/adp-preview.test.ts
  • Loading branch information
heimwege committed Feb 26, 2025
2 parents 9d877d7 + 1d4ba46 commit 8d9ca24
Show file tree
Hide file tree
Showing 60 changed files with 1,185 additions and 183 deletions.
6 changes: 6 additions & 0 deletions .changeset/red-jokes-flash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@sap-ux-private/preview-middleware-client': patch
'@sap-ux/preview-middleware': patch
---

feat: handling of legacy free ui5 version
7 changes: 7 additions & 0 deletions examples/simple-generator/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# @sap-ux/generator-simple-fe

## 1.0.140

### Patch Changes

- @sap-ux/fiori-elements-writer@2.1.19
- @sap-ux/fiori-freestyle-writer@2.1.1

## 1.0.139

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion examples/simple-generator/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@sap-ux/generator-simple-fe",
"version": "1.0.139",
"version": "1.0.140",
"description": "Simple example of a yeoman generator for Fiori elements.",
"license": "Apache-2.0",
"private": true,
Expand Down
8 changes: 8 additions & 0 deletions packages/adp-flp-config-sub-generator/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# @sap-ux/adp-flp-config-sub-generator

## 0.0.16

### Patch Changes

- Updated dependencies [127bd12]
- @sap-ux/adp-tooling@0.13.0
- @sap-ux/flp-config-inquirer@0.2.45

## 0.0.15

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/adp-flp-config-sub-generator/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@sap-ux/adp-flp-config-sub-generator",
"description": "Generator for adding FLP configuration to an Adaptation Project",
"version": "0.0.15",
"version": "0.0.16",
"repository": {
"type": "git",
"url": "https://github.com/SAP/open-ux-tools.git",
Expand Down
6 changes: 6 additions & 0 deletions packages/adp-tooling/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# @sap-ux/adp-tooling

## 0.13.0

### Minor Changes

- 127bd12: feat: Add Typescript support for Adaptation Project

## 0.12.138

### Patch Changes
Expand Down
10 changes: 6 additions & 4 deletions packages/adp-tooling/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"bugs": {
"url": "https://github.com/SAP/open-ux-tools/issues?q=is%3Aopen+is%3Aissue+label%3Abug+label%3Aadp-tooling"
},
"version": "0.12.138",
"version": "0.13.0",
"license": "Apache-2.0",
"author": "@SAP/ux-tools-team",
"main": "dist/index.js",
Expand All @@ -20,8 +20,8 @@
"format": "prettier --write '**/*.{js,json,ts,yaml,yml}' --ignore-path ../../.prettierignore",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"test": "jest FIORI_TOOLS_DISABLE_SECURE_STORE=true --ci --forceExit --detectOpenHandles --colors --testPathPattern=test/unit",
"test-u": "jest FIORI_TOOLS_DISABLE_SECURE_STORE=true --ci --forceExit --detectOpenHandles --colors -u",
"test": "cross-env FIORI_TOOLS_DISABLE_SECURE_STORE=true jest --ci --forceExit --detectOpenHandles --colors --testPathPattern=test/unit",
"test-u": "cross-env FIORI_TOOLS_DISABLE_SECURE_STORE=true jest --ci --forceExit --detectOpenHandles --colors -u",
"link": "pnpm link --global",
"unlink": "pnpm unlink --global"
},
Expand All @@ -44,6 +44,7 @@
"@sap-ux/system-access": "workspace:*",
"@sap-ux/ui5-config": "workspace:*",
"@sap-ux/odata-service-writer": "workspace:*",
"@sap-ux/nodejs-utils": "workspace:*",
"@sap-ux/i18n": "workspace:*",
"adm-zip": "0.5.10",
"ejs": "3.1.10",
Expand All @@ -70,7 +71,8 @@
"express": "4.21.2",
"nock": "13.4.0",
"rimraf": "5.0.5",
"supertest": "6.3.3"
"supertest": "6.3.3",
"cross-env": "^7.0.3"
},
"engines": {
"node": ">=18.x"
Expand Down
15 changes: 14 additions & 1 deletion packages/adp-tooling/src/base/helper.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type { Editor } from 'mem-fs-editor';
import { readdirSync, readFileSync } from 'fs';
import { existsSync, readdirSync, readFileSync } from 'fs';
import { join, isAbsolute, relative, basename, dirname } from 'path';
import { getWebappPath, FileName, readUi5Yaml } from '@sap-ux/project-access';
import type { UI5Config } from '@sap-ux/ui5-config';

import type { DescriptorVariant, AdpPreviewConfig } from '../types';

/**
Expand Down Expand Up @@ -53,6 +54,18 @@ export async function flpConfigurationExists(basePath: string): Promise<boolean>
}
}

/**
* Checks whether TypeScript is supported in the project by verifying the existence of `tsconfig.json`.
*
* @param basePath - The base path of the project.
* @param fs - An optional `mem-fs-editor` instance to check for the file's existence.
* @returns `true` if `tsconfig.json` exists, otherwise `false`.
*/
export function isTypescriptSupported(basePath: string, fs?: Editor): boolean {
const path = join(basePath, 'tsconfig.json');
return fs ? fs.exists(path) : existsSync(path);
}

/**
* Returns the adaptation project configuration, throws an error if not found.
*
Expand Down
21 changes: 21 additions & 0 deletions packages/adp-tooling/src/base/project-builder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { CommandRunner } from '@sap-ux/nodejs-utils';

/**
* Executes a build command in the specified project directory.
*
* This function uses the `CommandRunner` to run the build process via the command `npm run build`.
*
* @param {string} projectPath - The absolute path to the project directory where the build command will be executed.
* @returns {Promise<void>} Resolves when the build process has completed successfully.
* @throws {Error} If the build process fails or if an error occurs during cleanup.
*/
export async function runBuild(projectPath: string): Promise<void> {
const commandRunner = new CommandRunner();

try {
await commandRunner.run('npm', ['run', 'build'], { cwd: projectPath });
} catch (e) {
console.error(`Error during build and clean: ${e.message}`);
throw e;
}
}
8 changes: 8 additions & 0 deletions packages/adp-tooling/src/base/prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export type PromptDefaults = {
ft?: boolean;
package?: string;
transport?: string;
ts?: boolean;
};

/**
Expand Down Expand Up @@ -93,6 +94,13 @@ export async function promptGeneratorInput(
message: 'Enable Fiori tools?',
initial: defaults.ft !== false,
validate: (input) => input?.length > 0
},
{
type: 'confirm',
name: 'enableTypeScript',
message: 'Enable TypeScript?',
initial: defaults.ts !== false,
validate: (input) => input?.length > 0
}
]);

Expand Down
1 change: 1 addition & 0 deletions packages/adp-tooling/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * from './types';
export * from './prompts';
export * from './common';
export * from './base/cf';
export * from './base/project-builder';
export * from './base/abap/manifest-service';
export * from './base/helper';
export * from './preview/adp-preview';
Expand Down
70 changes: 47 additions & 23 deletions packages/adp-tooling/src/preview/routes-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { DirName, FileName } from '@sap-ux/project-access';
import { type CodeExtChange } from '../types';
import { ManifestService } from '../base/abap/manifest-service';
import type { DataSources } from '../base/abap/manifest-service';
import { getAdpConfig, getVariant } from '../base/helper';
import { getAdpConfig, getVariant, isTypescriptSupported } from '../base/helper';
import { createAbapServiceProvider } from '@sap-ux/system-access';

interface WriteControllerBody {
Expand Down Expand Up @@ -163,8 +163,11 @@ export default class RoutesHandler {

const project = this.util.getProject();
const sourcePath = project.getSourcePath();
const rootPath = this.util.getProject().getRootPath();
const projectName = project.getName();

const isTsSupported = isTypescriptSupported(rootPath);

const getPath = (projectPath: string, fileName: string, folder: string = DirName.Coding) =>
path.join(projectPath, DirName.Changes, folder, fileName).split(path.sep).join(path.posix.sep);

Expand All @@ -173,7 +176,8 @@ export default class RoutesHandler {
const change = JSON.parse(fileStr) as CodeExtChange;

if (change.selector.controllerName === controllerName) {
const fileName = change.content.codeRef.replace('coding/', '');
const baseFileName = change.content.codeRef.replace('coding/', '');
const fileName = isTsSupported ? baseFileName.replace('.js', '.ts') : baseFileName;
controllerPath = getPath(sourcePath, fileName);
controllerPathFromRoot = getPath(projectName, fileName);
changeFilePath = getPath(projectName, file.getName(), '');
Expand All @@ -195,7 +199,8 @@ export default class RoutesHandler {
controllerExists,
controllerPath: os.platform() === 'win32' ? `/${controllerPath}` : controllerPath,
controllerPathFromRoot,
isRunningInBAS
isRunningInBAS,
isTsSupported
});
this.logger.debug(
controllerExists
Expand All @@ -218,47 +223,37 @@ export default class RoutesHandler {
try {
const data = req.body as WriteControllerBody;

const controllerExtName = sanitize(data.controllerName);
const projectId = data.projectId;
const name = sanitize(data.controllerName);

const sourcePath = this.util.getProject().getSourcePath();
const rootPath = this.util.getProject().getRootPath();

if (!controllerExtName) {
if (!name) {
res.status(HttpStatusCodes.BAD_REQUEST).send('Controller extension name was not provided!');
this.logger.debug('Bad request. Controller extension name was not provided!');
return;
}

const isTsSupported = isTypescriptSupported(rootPath);

const fullPath = path.join(sourcePath, DirName.Changes, DirName.Coding);
const filePath = path.join(fullPath, `${controllerExtName}.js`);
const filePath = path.join(fullPath, `${name}.${isTsSupported ? 'ts' : 'js'}`);

if (!fs.existsSync(fullPath)) {
fs.mkdirSync(fullPath, { recursive: true });
}

if (fs.existsSync(filePath)) {
res.status(HttpStatusCodes.CONFLICT).send(
`Controller extension with name "${controllerExtName}" already exists`
);
this.logger.debug(`Controller extension with name "${controllerExtName}" already exists`);
res.status(HttpStatusCodes.CONFLICT).send(`Controller extension with name "${name}" already exists`);
this.logger.debug(`Controller extension with name "${name}" already exists`);
return;
}

const controllerExtPath = `${projectId}.${controllerExtName}`;

const controllerTemplateFilePath = path.join(__dirname, '../../templates/rta', TemplateFileName.Controller);

renderFile(controllerTemplateFilePath, { controllerExtPath }, {}, (err, str) => {
if (err) {
throw new Error('Error rendering template: ' + err.message);
}

fs.writeFileSync(filePath, str, { encoding: 'utf8' });
});
generateControllerFile(rootPath, filePath, name);

const message = 'Controller extension created!';
res.status(HttpStatusCodes.CREATED).send(message);
this.logger.debug(`Controller extension with name "${controllerExtName}" was created`);
this.logger.debug(`Controller extension with name "${name}" was created`);
} catch (e) {
const sanitizedMsg = sanitize(e.message);
this.logger.error(sanitizedMsg);
Expand Down Expand Up @@ -358,3 +353,32 @@ export default class RoutesHandler {
return await ManifestService.initMergedManifest(provider, basePath, variant, this.logger);
}
}

/**
* Generates a controller file for the Adaptation Project based on the project's TypeScript support.
*
* This function creates a controller file in the specified `filePath` by rendering a template.
* It determines whether to use a TypeScript or JavaScript template based on the TypeScript support of the project.
*
* @param {string} rootPath - The root directory of the project.
* @param {string} filePath - The destination path where the generated controller file should be saved.
* @param {string} name - The name of the controller extension (used in TypeScript templates).
* @throws {Error} Throws an error if rendering the template fails.
*/
function generateControllerFile(rootPath: string, filePath: string, name: string): void {
const id = getVariant(rootPath)?.id;
const isTsSupported = isTypescriptSupported(rootPath);
const tmplFileName = isTsSupported ? TemplateFileName.TSController : TemplateFileName.Controller;
const tmplPath = path.join(__dirname, '../../templates/rta', tmplFileName);
const extensionPath = `${id}.${name}`;

const templateData = isTsSupported ? { name, ns: id } : { extensionPath };

renderFile(tmplPath, templateData, {}, (err, str) => {
if (err) {
throw new Error(`Error rendering ${isTsSupported ? 'TypeScript' : 'JavaScript'} template: ${err.message}`);
}

fs.writeFileSync(filePath, str, { encoding: 'utf8' });
});
}
5 changes: 5 additions & 0 deletions packages/adp-tooling/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ export interface AdpWriterConfig {
* Optional: if set to true then the generated project will be recognized by the SAP Fiori tools
*/
fioriTools?: boolean;
/**
* Optional: if set to true then the generated project will support typescript
*/
enableTypeScript?: boolean;
};
}

Expand Down Expand Up @@ -278,6 +282,7 @@ export type ParameterRules = {
export const enum TemplateFileName {
Fragment = 'fragment.xml',
Controller = 'controller.ejs',
TSController = 'ts-controller.ejs',
Annotation = 'annotation.xml'
}

Expand Down
6 changes: 4 additions & 2 deletions packages/adp-tooling/src/writer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { AdpWriterConfig, InternalInboundNavigation } from '../types';
import { enhanceManifestChangeContentWithFlpConfig } from './options';
import { writeTemplateToFolder, writeUI5Yaml, writeUI5DeployYaml } from './project-utils';

const tmplPath = join(__dirname, '../../templates/project');
const baseTmplPath = join(__dirname, '../../templates');

/**
* Set default values for optional properties.
Expand Down Expand Up @@ -60,7 +60,7 @@ export async function generate(basePath: string, config: AdpWriterConfig, fs?: E
fullConfig.app.content
);
}
writeTemplateToFolder(join(tmplPath, '**/*.*'), join(basePath), fullConfig, fs);
writeTemplateToFolder(baseTmplPath, join(basePath), fullConfig, fs);
await writeUI5DeployYaml(basePath, fullConfig, fs);
await writeUI5Yaml(basePath, fullConfig, fs);

Expand All @@ -82,6 +82,8 @@ export async function migrate(basePath: string, config: AdpWriterConfig, fs?: Ed

const fullConfig = setDefaults(config);

const tmplPath = join(baseTmplPath, 'project');

// Copy the specified files to target project
fs.copyTpl(join(tmplPath, '**/ui5.yaml'), join(basePath), fullConfig, undefined, {
globOptions: { dot: true }
Expand Down
Loading

0 comments on commit 8d9ca24

Please sign in to comment.