diff --git a/packages/apps-engine/src/definition/version.ts b/packages/apps-engine/src/definition/version.ts new file mode 100644 index 0000000000000..8feda95c5ad5d --- /dev/null +++ b/packages/apps-engine/src/definition/version.ts @@ -0,0 +1,16 @@ +/** + * The version of the Apps-Engine package. + * Consumed by host-side code (e.g. AppPackageParser) to validate app compatibility + * without relying on filesystem path traversal. + * + * Uses require() instead of a static import so TypeScript does not resolve the path + * at compile time. + * + * When running for tests, using ts-node, package.json is located two levels above the current file. + * When running in production, package.json is located one level above the compiled version of this file. + */ +const runningFromSource = __dirname.endsWith('src/definition'); +const requirePath = runningFromSource ? '../../package.json' : '../package.json'; + +// eslint-disable-next-line import/no-dynamic-require, @typescript-eslint/no-require-imports -- Paths are bounded, we just need to decide which package.json file to target +export const ENGINE_VERSION: string = require(requirePath).version; diff --git a/packages/apps-engine/src/server/compiler/AppPackageParser.ts b/packages/apps-engine/src/server/compiler/AppPackageParser.ts index 316f37079e75e..9d98cc0356310 100644 --- a/packages/apps-engine/src/server/compiler/AppPackageParser.ts +++ b/packages/apps-engine/src/server/compiler/AppPackageParser.ts @@ -1,4 +1,3 @@ -import * as fs from 'fs'; import * as path from 'path'; import * as AdmZip from 'adm-zip'; @@ -8,18 +7,15 @@ import { v4 as uuidv4 } from 'uuid'; import { AppImplements } from '.'; import type { IParseAppPackageResult } from './IParseAppPackageResult'; import type { IAppInfo } from '../../definition/metadata/IAppInfo'; +import { ENGINE_VERSION } from '../../definition/version'; import { RequiredApiVersionError } from '../errors'; export class AppPackageParser { - public static uuid4Regex = /^[0-9a-fA-f]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/; + public static uuid4Regex = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/; private allowedIconExts: Array = ['.png', '.jpg', '.jpeg', '.gif']; - private appsEngineVersion: string; - - constructor() { - this.appsEngineVersion = this.getEngineVersion(); - } + private appsEngineVersion: string = ENGINE_VERSION; public async unpackageApp(appPackage: Buffer): Promise { const zip = new AdmZip(appPackage); @@ -143,21 +139,4 @@ export class AppPackageParser { return `data:image/${ext.replace('.', '')};base64,${base64}`; } - - private getEngineVersion(): string { - const devLocation = path.join(__dirname, '../../../package.json'); - const prodLocation = path.join(__dirname, '../../package.json'); - - let info: { version: string }; - - if (fs.existsSync(devLocation)) { - info = JSON.parse(fs.readFileSync(devLocation, 'utf8')); - } else if (fs.existsSync(prodLocation)) { - info = JSON.parse(fs.readFileSync(prodLocation, 'utf8')); - } else { - throw new Error('Could not find the Apps TypeScript Definition Package Version!'); - } - - return info.version.replace(/^[^0-9]/, '').split('-')[0]; - } } diff --git a/packages/apps-engine/tsconfig.json b/packages/apps-engine/tsconfig.json index fe9e53b01cb85..2d70ec6e00a34 100644 --- a/packages/apps-engine/tsconfig.json +++ b/packages/apps-engine/tsconfig.json @@ -10,6 +10,7 @@ "emitDecoratorMetadata": true, "experimentalDecorators": true, "moduleResolution": "node", + "resolveJsonModule": true, "types": ["node"], "lib": ["es2017", "dom"], "rootDir": "./src",