diff --git a/packages/flutter_tools/lib/src/android/android_device.dart b/packages/flutter_tools/lib/src/android/android_device.dart index a388672b39bcc6812a329c6fe0b6a64465062536..d2596cb2dbecd2287e0bfe2a0d5e61311c1dc34d 100644 --- a/packages/flutter_tools/lib/src/android/android_device.dart +++ b/packages/flutter_tools/lib/src/android/android_device.dart @@ -226,6 +226,10 @@ class AndroidDevice extends Device { case TargetPlatform.tester: case TargetPlatform.web_javascript: case TargetPlatform.windows_x64: + case TargetPlatform.ohos: + case TargetPlatform.ohos_arm: + case TargetPlatform.ohos_arm64: + case TargetPlatform.ohos_x64: throw UnsupportedError('Invalid target platform for Android'); } } @@ -564,6 +568,10 @@ class AndroidDevice extends Device { case TargetPlatform.tester: case TargetPlatform.web_javascript: case TargetPlatform.windows_x64: + case TargetPlatform.ohos: + case TargetPlatform.ohos_arm: + case TargetPlatform.ohos_arm64: + case TargetPlatform.ohos_x64: _logger.printError('Android platforms are only supported.'); return LaunchResult.failed(); } diff --git a/packages/flutter_tools/lib/src/artifacts.dart b/packages/flutter_tools/lib/src/artifacts.dart index 5ac870497bfe17bf5eb6244b6cfde9ebba5c0a17..004be979fbb24bcbe36e0365412db7e1c1d1e13c 100644 --- a/packages/flutter_tools/lib/src/artifacts.dart +++ b/packages/flutter_tools/lib/src/artifacts.dart @@ -49,6 +49,9 @@ enum Artifact { /// Tools related to subsetting or icon font files. fontSubset, constFinder, + + /// the flutter engine runtime + flutterEngineSo, } /// A subset of [Artifact]s that are platform and build mode independent @@ -113,6 +116,8 @@ TargetPlatform? _mapTargetPlatform(TargetPlatform? targetPlatform) { switch (targetPlatform) { case TargetPlatform.android: return TargetPlatform.android_arm64; + case TargetPlatform.ohos: + return TargetPlatform.ohos_arm64; case TargetPlatform.ios: case TargetPlatform.darwin: case TargetPlatform.linux_x64: @@ -126,6 +131,9 @@ TargetPlatform? _mapTargetPlatform(TargetPlatform? targetPlatform) { case TargetPlatform.android_arm64: case TargetPlatform.android_x64: case TargetPlatform.android_x86: + case TargetPlatform.ohos_arm: + case TargetPlatform.ohos_arm64: + case TargetPlatform.ohos_x64: case null: return targetPlatform; } @@ -148,6 +156,10 @@ bool _isWindows(TargetPlatform? platform) { case TargetPlatform.linux_x64: case TargetPlatform.tester: case TargetPlatform.web_javascript: + case TargetPlatform.ohos: + case TargetPlatform.ohos_arm: + case TargetPlatform.ohos_arm64: + case TargetPlatform.ohos_x64: case null: return false; } @@ -201,6 +213,8 @@ String? _artifactToFileName(Artifact artifact, [ TargetPlatform? platform, Build return 'font-subset$exe'; case Artifact.constFinder: return 'const_finder.dart.snapshot'; + case Artifact.flutterEngineSo: + return 'libflutter.so'; } } @@ -442,6 +456,10 @@ class CachedArtifacts implements Artifacts { return _getFuchsiaArtifactPath(artifact, platform!, mode!); case TargetPlatform.tester: case TargetPlatform.web_javascript: + case TargetPlatform.ohos: + case TargetPlatform.ohos_arm: + case TargetPlatform.ohos_arm64: + case TargetPlatform.ohos_x64: case null: return _getHostArtifactPath(artifact, platform ?? _currentHostPlatform(_platform, _operatingSystemUtils), mode); } @@ -489,6 +507,7 @@ class CachedArtifacts implements Artifacts { case Artifact.vmSnapshotData: case Artifact.windowsCppClientWrapper: case Artifact.windowsDesktopPath: + case Artifact.flutterEngineSo: return _getHostArtifactPath(artifact, platform, mode); } } @@ -521,6 +540,7 @@ class CachedArtifacts implements Artifacts { case Artifact.vmSnapshotData: case Artifact.windowsCppClientWrapper: case Artifact.windowsDesktopPath: + case Artifact.flutterEngineSo: return _getHostArtifactPath(artifact, platform, mode); } } @@ -565,6 +585,7 @@ class CachedArtifacts implements Artifacts { case Artifact.vmSnapshotData: case Artifact.windowsCppClientWrapper: case Artifact.windowsDesktopPath: + case Artifact.flutterEngineSo: return _getHostArtifactPath(artifact, platform, mode); } } @@ -634,6 +655,10 @@ class CachedArtifacts implements Artifacts { case Artifact.fuchsiaFlutterRunner: case Artifact.fuchsiaKernelCompiler: throw StateError('Artifact $artifact not available for platform $platform.'); + case Artifact.flutterEngineSo: + return _cache.getArtifactDirectory('engine') + .childFile(_artifactToFileName(artifact)!) + .path; } } @@ -768,8 +793,21 @@ class CachedLocalEngineArtifacts implements LocalEngineArtifacts { final OperatingSystemUtils _operatingSystemUtils; final CachedArtifacts _backupCache; + /// this list hostArtifact will execute by the backup engine ,because local engine arch not match . + final List hostArtifactList = [ + HostArtifact.engineDartBinary, + HostArtifact.impellerc, + ]; + + bool isOhosLocalEngine(){ + return localEngineName.contains('ohos'); + } + @override FileSystemEntity getHostArtifact(HostArtifact artifact) { + if(isOhosLocalEngine() && hostArtifactList.contains(artifact)){ + return _backupCache.getHostArtifact(artifact); + } switch (artifact) { case HostArtifact.engineDartSdkPath: final String path = _getDartSdkPath(); @@ -860,7 +898,7 @@ class CachedLocalEngineArtifacts implements LocalEngineArtifacts { final String? artifactFileName = isDirectoryArtifact ? null : _artifactToFileName(artifact, platform, mode); switch (artifact) { case Artifact.genSnapshot: - return _genSnapshotPath(); + return _genSnapshotPath(platform); case Artifact.flutterTester: return _flutterTesterPath(platform!); case Artifact.isolateSnapshotData: @@ -908,6 +946,7 @@ class CachedLocalEngineArtifacts implements LocalEngineArtifacts { case Artifact.linuxHeaders: case Artifact.windowsDesktopPath: case Artifact.windowsCppClientWrapper: + case Artifact.flutterEngineSo: return _fileSystem.path.join(_hostEngineOutPath, artifactFileName); case Artifact.frontendServerSnapshotForEngineDartSdk: return _fileSystem.path.join( @@ -967,6 +1006,10 @@ class CachedLocalEngineArtifacts implements LocalEngineArtifacts { case TargetPlatform.fuchsia_x64: case TargetPlatform.web_javascript: case TargetPlatform.tester: + case TargetPlatform.ohos: + case TargetPlatform.ohos_arm: + case TargetPlatform.ohos_arm64: + case TargetPlatform.ohos_x64: throwToolExit('Unsupported host platform: $hostPlatform'); } } @@ -975,8 +1018,14 @@ class CachedLocalEngineArtifacts implements LocalEngineArtifacts { return _fileSystem.path.join(engineOutPath, 'flutter_web_sdk'); } - String _genSnapshotPath() { - const List clangDirs = ['.', 'clang_x64', 'clang_x86', 'clang_i386', 'clang_arm64']; + String _genSnapshotPath(TargetPlatform? platform) { + late List clangDirs; + if (isOhosPlatform(platform)) { + // on ohos platform, clang_x64 has compatibility first + clangDirs = ['clang_x64', '.', 'clang_x86', 'clang_i386', 'clang_arm64']; + } else { + clangDirs = ['.', 'clang_x64', 'clang_x86', 'clang_i386', 'clang_arm64']; + } final String genSnapshotName = _artifactToFileName(Artifact.genSnapshot)!; for (final String clangDir in clangDirs) { final String genSnapshotPath = _fileSystem.path.join(engineOutPath, clangDir, genSnapshotName); diff --git a/packages/flutter_tools/lib/src/base/build.dart b/packages/flutter_tools/lib/src/base/build.dart index 105e435c043bae5949f2ccc222fcf2343f4cfc92..9b0facfb2b7a43aea62b673d323340527b4c7002 100644 --- a/packages/flutter_tools/lib/src/base/build.dart +++ b/packages/flutter_tools/lib/src/base/build.dart @@ -347,6 +347,9 @@ class AOTSnapshotter { TargetPlatform.linux_x64, TargetPlatform.linux_arm64, TargetPlatform.windows_x64, + TargetPlatform.ohos_arm64, + TargetPlatform.ohos_arm, + TargetPlatform.ohos_x64, ].contains(platform); } } diff --git a/packages/flutter_tools/lib/src/base/user_messages.dart b/packages/flutter_tools/lib/src/base/user_messages.dart index 63cb28f7c29873d1df000f66e4ef16b1118addf4..b2a9dfb1147077cdbdc271c6969f59140a4bf6f1 100644 --- a/packages/flutter_tools/lib/src/base/user_messages.dart +++ b/packages/flutter_tools/lib/src/base/user_messages.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import '../ohos/ohos_sdk.dart'; import 'context.dart'; import 'platform.dart'; @@ -159,6 +160,42 @@ class UserMessages { 'Android Studio not found; download from https://developer.android.com/studio/index.html\n' '(or visit ${_androidSdkInstallUrl(platform)} for detailed instructions).'; + // Messages used in NoOhosSdkValidator + String ohosSdkMissing(String location) => + 'OHOS_SDK_HOME = $location\n' + 'but OpenHarmony Sdk not found at this location'; + String ohosSdkInstallation() => + 'OpenHarmony Sdk not found; \n' + 'please do that, first: download from https://developer.harmonyos.com/cn/develop/deveco-studio#download_cli ;\n' + 'second: follow this document: https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/ide-command-line-ohsdkmgr-0000001545647965-V3 to install OpenHarmony sdk with ohsdkmgr; \n' + 'If the Ohos SDK has been installed to a custom location, please use\n' + '`flutter config --ohos-sdk` to update to that location.\n'; + String ohosSdkVersion(OhosSdk ohosSdk) => + 'OpenHarmony Sdk location: ${ohosSdk.sdkPath}, available api versions has ${ohosSdk.apiAvailable}'; + + String hdcMissing() => + 'hdc is missing ,please download from https://developer.harmonyos.com/cn/develop/deveco-studio#download_cli;\n' + 'and set environment HDC_HOME also set to PATH'; + String hdcVersion(String ohpmVersion) => + 'hdc version $ohpmVersion'; + + String ohpmMissing() => + 'ohpm is missing ,please download from https://developer.harmonyos.com/cn/develop/deveco-studio#download_cli;\n' + 'and set environment OHPM_HOME also set to PATH\n' + 'If the ohpm has been installed to a custom location, please use\n' + '`flutter config --ohpm-home` to update to that location.\n'; + String ohpmVersion(String ohpmVersion) => + 'ohpm version $ohpmVersion'; + + String signToolMissing() => + 'signTool is missing ,please download from https://gitee.com/openharmony/developtools_hapsigner;\n' + 'and follow ReadMe to generate hap-sign-tool.jar, set environment SIGN_TOOL_HOME = /developtools_hapsigner/autosign such as /home/xxx/sdk/developtools_hapsigner/autosign\n' + 'If the signTool has been installed to a custom location, please use\n' + '`flutter config --signTool-home` to update to that location.\n'; + String signToolVersion(String signToolHome) => + 'signTool location:$signToolHome'; + + // Messages used in XcodeValidator String xcodeLocation(String location) => 'Xcode at $location'; diff --git a/packages/flutter_tools/lib/src/build_info.dart b/packages/flutter_tools/lib/src/build_info.dart index ce9b4993edcc3a8760fa6a9ff447c1031ae08101..3cda7b9b7063abbad229260c6d0ee5e093436d0f 100644 --- a/packages/flutter_tools/lib/src/build_info.dart +++ b/packages/flutter_tools/lib/src/build_info.dart @@ -581,6 +581,11 @@ enum TargetPlatform { android_arm64, android_x64, android_x86, + //ohos platform + ohos, + ohos_arm, + ohos_arm64, + ohos_x64, } /// iOS and macOS target device architecture. @@ -600,6 +605,24 @@ enum AndroidArch { x86_64, } +enum OhosArch { + armeabi_v7a, + arm64_v8a, + x86_64, +} + + +bool isOhosPlatform(TargetPlatform? targetPlatform){ + switch(targetPlatform){ + case TargetPlatform.ohos: + case TargetPlatform.ohos_arm: + case TargetPlatform.ohos_arm64: + case TargetPlatform.ohos_x64: + return true; + } + return false; +} + /// The default set of iOS device architectures to build for. List defaultIOSArchsForEnvironment( EnvironmentType environmentType, @@ -737,6 +760,14 @@ String getNameForTargetPlatform(TargetPlatform platform, {DarwinArch? darwinArch return 'web-javascript'; case TargetPlatform.android: return 'android'; + case TargetPlatform.ohos: + return 'ohos'; + case TargetPlatform.ohos_arm: + return 'ohos-arm'; + case TargetPlatform.ohos_arm64: + return 'ohos-arm64'; + case TargetPlatform.ohos_x64: + return 'ohos-x86'; } } @@ -766,12 +797,20 @@ TargetPlatform getTargetPlatformForName(String platform) { return TargetPlatform.darwin; case 'linux-x64': return TargetPlatform.linux_x64; - case 'linux-arm64': + case 'linux-arm64': return TargetPlatform.linux_arm64; case 'windows-x64': return TargetPlatform.windows_x64; case 'web-javascript': return TargetPlatform.web_javascript; + case 'ohos': + return TargetPlatform.ohos; + case 'ohos-arm': + return TargetPlatform.ohos_arm; + case 'ohos-arm64': + return TargetPlatform.ohos_arm64; + case 'ohos-x64': + return TargetPlatform.ohos_x64; } throw Exception('Unsupported platform name "$platform"'); } @@ -816,6 +855,40 @@ String getPlatformNameForAndroidArch(AndroidArch arch) { } } +OhosArch getOhosArchForName(String platform) { + switch (platform) { + case 'ohos-arm': + return OhosArch.armeabi_v7a; + case 'ohos-arm64': + return OhosArch.arm64_v8a; + case 'ohos-x86': + return OhosArch.x86_64; + } + throw Exception('Unsupported Ohos arch name "$platform"'); +} + +String getNameForOhosArch(OhosArch arch) { + switch (arch) { + case OhosArch.armeabi_v7a: + return 'armeabi-v7a'; + case OhosArch.arm64_v8a: + return 'arm64-v8a'; + case OhosArch.x86_64: + return 'x86_64'; + } +} + +String getPlatformNameForOhosArch(OhosArch arch) { + switch (arch) { + case OhosArch.armeabi_v7a: + return 'ohos-arm'; + case OhosArch.arm64_v8a: + return 'ohos-arm64'; + case OhosArch.x86_64: + return 'ohos-x86'; + } +} + String fuchsiaArchForTargetPlatform(TargetPlatform targetPlatform) { switch (targetPlatform) { case TargetPlatform.fuchsia_arm64: @@ -834,6 +907,10 @@ String fuchsiaArchForTargetPlatform(TargetPlatform targetPlatform) { case TargetPlatform.tester: case TargetPlatform.web_javascript: case TargetPlatform.windows_x64: + case TargetPlatform.ohos: + case TargetPlatform.ohos_arm: + case TargetPlatform.ohos_arm64: + case TargetPlatform.ohos_x64: throw UnsupportedError('Unexpected Fuchsia platform $targetPlatform'); } } @@ -907,6 +984,11 @@ String getWebBuildDirectory() { return globals.fs.path.join(getBuildDirectory(), 'web'); } +/// Returns the ohos build output directory. +String getOhosBuildDirectory(){ + return globals.fs.path.join(getBuildDirectory(), 'ohos'); +} + /// Returns the Linux build output directory. String getLinuxBuildDirectory([TargetPlatform? targetPlatform]) { final String arch = (targetPlatform == null) ? @@ -1089,6 +1171,10 @@ String getNameForTargetPlatformArch(TargetPlatform platform) { case TargetPlatform.ios: case TargetPlatform.tester: case TargetPlatform.web_javascript: + case TargetPlatform.ohos: + case TargetPlatform.ohos_arm: + case TargetPlatform.ohos_arm64: + case TargetPlatform.ohos_x64: throw UnsupportedError('Unexpected target platform $platform'); } } diff --git a/packages/flutter_tools/lib/src/build_system/targets/common.dart b/packages/flutter_tools/lib/src/build_system/targets/common.dart index 91a39e6c20c906b86c6aa4fc5edcbfa7473d46ca..e484b8505e75c820498debd4df6677fc823a048f 100644 --- a/packages/flutter_tools/lib/src/build_system/targets/common.dart +++ b/packages/flutter_tools/lib/src/build_system/targets/common.dart @@ -208,6 +208,10 @@ class KernelSnapshot extends Target { case TargetPlatform.linux_arm64: case TargetPlatform.tester: case TargetPlatform.web_javascript: + case TargetPlatform.ohos: + case TargetPlatform.ohos_arm: + case TargetPlatform.ohos_arm64: + case TargetPlatform.ohos_x64: forceLinkPlatform = false; break; } diff --git a/packages/flutter_tools/lib/src/build_system/targets/ohos.dart b/packages/flutter_tools/lib/src/build_system/targets/ohos.dart new file mode 100644 index 0000000000000000000000000000000000000000..3bdcf26d04e8887b7df44fc279b9297a436517fd --- /dev/null +++ b/packages/flutter_tools/lib/src/build_system/targets/ohos.dart @@ -0,0 +1,362 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import 'package:file/file.dart'; + +import '../../artifacts.dart'; +import '../../base/build.dart'; +import '../../base/deferred_component.dart'; +import '../../build_info.dart'; +import '../../globals.dart' as globals show xcode; +import '../build_system.dart'; +import '../depfile.dart'; +import '../exceptions.dart'; +import 'assets.dart'; +import 'common.dart'; +import 'shader_compiler.dart'; + +class DebugOhosApplication extends OhosAssetBundle { + const DebugOhosApplication(); + + @override + String get name => 'debug_ohos_application'; + + @override + List get inputs => [ + ...super.inputs, + const Source.artifact(Artifact.vmSnapshotData, mode: BuildMode.debug), + const Source.artifact(Artifact.isolateSnapshotData, + mode: BuildMode.debug), + ]; + + @override + List get outputs => [ + ...super.outputs, + const Source.pattern('{OUTPUT_DIR}/flutter_assets/vm_snapshot_data'), + const Source.pattern( + '{OUTPUT_DIR}/flutter_assets/isolate_snapshot_data'), + const Source.pattern('{OUTPUT_DIR}/flutter_assets/kernel_blob.bin'), + ]; +} + +/// ohos release targets +const OhosAotBundle ohosArmReleaseBundle = OhosAotBundle(ohosArmRelease); +const OhosAotBundle ohosArm64ReleaseBundle = OhosAotBundle(ohosArm64Release); +const OhosAotBundle ohosX64ReleaseBundle = OhosAotBundle(ohosX64Release); + +List ohosTargets = [ + ohosArmReleaseBundle, + ohosArm64ReleaseBundle, + ohosX64ReleaseBundle, + const DebugOhosApplication(), +]; + +/// A rule paired with [OhosAot] that copies the produced so file and manifest.json (if present) into the output directory. +class OhosAotBundle extends Target { + /// Create an [OhosAotBundle] implementation for a given [targetPlatform] and [buildMode]. + const OhosAotBundle(this.dependency); + + /// The [OhosAot] instance this bundle rule depends on. + final OhosAot dependency; + + /// The name of the produced Ohos ABI. + String get _ohosAbiName { + return getNameForOhosArch(getOhosArchForName( + getNameForTargetPlatform(dependency.targetPlatform))); + } + + @override + String get name => + 'ohos_aot_bundle_${getNameForBuildMode(dependency.buildMode)}_' + '${getNameForTargetPlatform(dependency.targetPlatform)}'; + + TargetPlatform get targetPlatform => dependency.targetPlatform; + + /// The selected build mode. + /// + /// This is restricted to [BuildMode.profile] or [BuildMode.release]. + BuildMode get buildMode => dependency.buildMode; + + @override + List get inputs => [ + Source.pattern('{BUILD_DIR}/$_ohosAbiName/app.so'), + ]; + + // flutter.gradle has been updated to correctly consume it. + @override + List get outputs => [ + Source.pattern('{OUTPUT_DIR}/$_ohosAbiName/app.so'), + ]; + + @override + List get depfiles => [ + 'flutter_$name.d', + ]; + + @override + List get dependencies => [ + dependency, + const AotOhosAssetBundle(), + ]; + + @override + Future build(Environment environment) async { + final Directory buildDir = + environment.buildDir.childDirectory(_ohosAbiName); + final Directory outputDirectory = + environment.outputDir.childDirectory(_ohosAbiName); + if (!outputDirectory.existsSync()) { + outputDirectory.createSync(recursive: true); + } + final File outputLibFile = buildDir.childFile('app.so'); + outputLibFile.copySync(outputDirectory.childFile('app.so').path); + + final List inputs = []; + final List outputs = []; + final File manifestFile = buildDir.childFile('manifest.json'); + if (manifestFile.existsSync()) { + final File destinationFile = outputDirectory.childFile('manifest.json'); + manifestFile.copySync(destinationFile.path); + inputs.add(manifestFile); + outputs.add(destinationFile); + } + final DepfileService depfileService = DepfileService( + fileSystem: environment.fileSystem, + logger: environment.logger, + ); + depfileService.writeToFile( + Depfile(inputs, outputs), + environment.buildDir.childFile('flutter_$name.d'), + writeEmpty: true, + ); + } +} + +const OhosAot ohosArmRelease = + OhosAot(TargetPlatform.ohos_arm, BuildMode.release); +const OhosAot ohosArm64Release = + OhosAot(TargetPlatform.ohos_arm64, BuildMode.release); +const OhosAot ohosX64Release = + OhosAot(TargetPlatform.ohos_x64, BuildMode.release); + +class OhosAot extends AotElfBase { + /// Create an [OhosAot] implementation for a given [targetPlatform] and [buildMode]. + const OhosAot(this.targetPlatform, this.buildMode); + + /// The name of the produced Ohos ABI. + String get _ohosAbiName { + return getNameForOhosArch( + getOhosArchForName(getNameForTargetPlatform(targetPlatform))); + } + + @override + String get name => 'ohos_aot_${getNameForBuildMode(buildMode)}_' + '${getNameForTargetPlatform(targetPlatform)}'; + + /// The specific Ohos ABI we are building for. + final TargetPlatform targetPlatform; + + /// The selected build mode. + /// + /// Build mode is restricted to [BuildMode.profile] or [BuildMode.release] for AOT builds. + final BuildMode buildMode; + + @override + List get inputs => [ + const Source.pattern( + '{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/ohos.dart'), + const Source.pattern('{BUILD_DIR}/app.dill'), + const Source.hostArtifact(HostArtifact.engineDartBinary), + const Source.artifact(Artifact.skyEnginePath), + Source.artifact( + Artifact.genSnapshot, + mode: buildMode, + platform: targetPlatform, + ), + ]; + + @override + List get outputs => [ + Source.pattern('{BUILD_DIR}/$_ohosAbiName/app.so'), + ]; + + @override + List get depfiles => [ + 'flutter_$name.d', + ]; + + @override + List get dependencies => const [ + KernelSnapshot(), + ]; + + @override + Future build(Environment environment) async { + final AOTSnapshotter snapshotter = AOTSnapshotter( + fileSystem: environment.fileSystem, + logger: environment.logger, + xcode: globals.xcode!, + processManager: environment.processManager, + artifacts: environment.artifacts, + ); + final Directory output = environment.buildDir.childDirectory(_ohosAbiName); + final String? buildModeEnvironment = environment.defines[kBuildMode]; + if (buildModeEnvironment == null) { + throw MissingDefineException(kBuildMode, 'aot_elf'); + } + if (!output.existsSync()) { + output.createSync(recursive: true); + } + final List extraGenSnapshotOptions = + decodeCommaSeparated(environment.defines, kExtraGenSnapshotOptions); + final List outputs = []; // outputs for the depfile + final String manifestPath = + '${output.path}${environment.platform.pathSeparator}manifest.json'; + if (environment.defines[kDeferredComponents] == 'true') { + extraGenSnapshotOptions.add('--loading_unit_manifest=$manifestPath'); + outputs.add(environment.fileSystem.file(manifestPath)); + } + final BuildMode buildMode = getBuildModeForName(buildModeEnvironment); + final bool dartObfuscation = + environment.defines[kDartObfuscation] == 'true'; + final String? codeSizeDirectory = environment.defines[kCodeSizeDirectory]; + + if (codeSizeDirectory != null) { + final File codeSizeFile = environment.fileSystem + .directory(codeSizeDirectory) + .childFile('snapshot.$_ohosAbiName.json'); + final File precompilerTraceFile = environment.fileSystem + .directory(codeSizeDirectory) + .childFile('trace.$_ohosAbiName.json'); + extraGenSnapshotOptions + .add('--write-v8-snapshot-profile-to=${codeSizeFile.path}'); + extraGenSnapshotOptions + .add('--trace-precompiler-to=${precompilerTraceFile.path}'); + } + + final String? splitDebugInfo = environment.defines[kSplitDebugInfo]; + final int snapshotExitCode = await snapshotter.build( + platform: targetPlatform, + buildMode: buildMode, + mainPath: environment.buildDir.childFile('app.dill').path, + outputPath: output.path, + extraGenSnapshotOptions: extraGenSnapshotOptions, + splitDebugInfo: splitDebugInfo, + dartObfuscation: dartObfuscation, + ); + if (snapshotExitCode != 0) { + throw Exception('AOT snapshotter exited with code $snapshotExitCode'); + } + if (environment.defines[kDeferredComponents] == 'true') { + // Parse the manifest for .so paths + final List loadingUnits = + LoadingUnit.parseLoadingUnitManifest( + environment.fileSystem.file(manifestPath), environment.logger); + for (final LoadingUnit unit in loadingUnits) { + outputs.add(environment.fileSystem.file(unit.path)); + } + } + final DepfileService depfileService = DepfileService( + fileSystem: environment.fileSystem, + logger: environment.logger, + ); + depfileService.writeToFile( + Depfile([], outputs), + environment.buildDir.childFile('flutter_$name.d'), + writeEmpty: true, + ); + } +} + +/// An implementation of [OhosAssetBundle] that only includes assets. +class AotOhosAssetBundle extends OhosAssetBundle { + const AotOhosAssetBundle(); + + @override + String get name => 'aot_ohos_asset_bundle'; +} + +/// Prepares the asset bundle in the format expected by flutter.gradle. +/// +/// The vm_snapshot_data, isolate_snapshot_data, and kernel_blob.bin are +/// expected to be in the root output directory. +/// +/// All assets and manifests are included from flutter_assets/**. +abstract class OhosAssetBundle extends Target { + const OhosAssetBundle(); + + @override + List get inputs => const [ + Source.pattern('{BUILD_DIR}/app.dill'), + // ...IconTreeShaker.inputs, + ]; + + @override + List get outputs => const []; + + @override + List get depfiles => [ + 'flutter_assets.d', + ]; + + @override + Future build(Environment environment) async { + final String? buildModeEnvironment = environment.defines[kBuildMode]; + if (buildModeEnvironment == null) { + throw MissingDefineException(kBuildMode, name); + } + final BuildMode buildMode = getBuildModeForName(buildModeEnvironment); + final Directory outputDirectory = environment.outputDir + .childDirectory('flutter_assets') + ..createSync(recursive: true); + + // Only copy the prebuilt runtimes and kernel blob in debug mode. + if (buildMode == BuildMode.debug) { + final String vmSnapshotData = environment.artifacts + .getArtifactPath(Artifact.vmSnapshotData, mode: BuildMode.debug); + final String isolateSnapshotData = environment.artifacts + .getArtifactPath(Artifact.isolateSnapshotData, mode: BuildMode.debug); + environment.buildDir + .childFile('app.dill') + .copySync(outputDirectory.childFile('kernel_blob.bin').path); + environment.fileSystem + .file(vmSnapshotData) + .copySync(outputDirectory.childFile('vm_snapshot_data').path); + environment.fileSystem + .file(isolateSnapshotData) + .copySync(outputDirectory.childFile('isolate_snapshot_data').path); + } + final Depfile assetDepfile = await copyAssets( + environment, + outputDirectory, + targetPlatform: TargetPlatform.ohos, + buildMode: buildMode, + shaderTarget: ShaderTarget.sksl, + ); + final DepfileService depfileService = DepfileService( + fileSystem: environment.fileSystem, + logger: environment.logger, + ); + depfileService.writeToFile( + assetDepfile, + environment.buildDir.childFile('flutter_assets.d'), + ); + } + + @override + List get dependencies => const [ + KernelSnapshot(), + ]; +} diff --git a/packages/flutter_tools/lib/src/commands/assemble.dart b/packages/flutter_tools/lib/src/commands/assemble.dart index c32f89a3f9e5046d14130a497b92193edbfbe927..992acb016e2e3fbf1b01c61be8d1dfd96953a241 100644 --- a/packages/flutter_tools/lib/src/commands/assemble.dart +++ b/packages/flutter_tools/lib/src/commands/assemble.dart @@ -18,6 +18,7 @@ import '../build_system/targets/deferred_components.dart'; import '../build_system/targets/ios.dart'; import '../build_system/targets/linux.dart'; import '../build_system/targets/macos.dart'; +import '../build_system/targets/ohos.dart'; import '../build_system/targets/web.dart'; import '../build_system/targets/windows.dart'; import '../cache.dart'; @@ -79,45 +80,49 @@ List _kDefaultTargets = [ const DebugBundleWindowsAssets(), const ProfileBundleWindowsAssets(), const ReleaseBundleWindowsAssets(), + // Ohos targets + ...ohosTargets, ]; /// Assemble provides a low level API to interact with the flutter tool build /// system. class AssembleCommand extends FlutterCommand { - AssembleCommand({ bool verboseHelp = false, required BuildSystem buildSystem }) - : _buildSystem = buildSystem { + AssembleCommand({bool verboseHelp = false, required BuildSystem buildSystem}) + : _buildSystem = buildSystem { argParser.addMultiOption( 'define', abbr: 'd', valueHelp: 'target=key=value', - help: 'Allows passing configuration to a target, as in "--define=target=key=value".', - ); - argParser.addOption( - 'performance-measurement-file', - help: 'Output individual target performance to a JSON file.' - ); - argParser.addMultiOption( - 'input', - abbr: 'i', - help: 'Allows passing additional inputs with "--input=key=value". Unlike ' - 'defines, additional inputs do not generate a new configuration; instead ' - 'they are treated as dependencies of the targets that use them.' + help: + 'Allows passing configuration to a target, as in "--define=target=key=value".', ); + argParser.addOption('performance-measurement-file', + help: 'Output individual target performance to a JSON file.'); + argParser.addMultiOption('input', + abbr: 'i', + help: + 'Allows passing additional inputs with "--input=key=value". Unlike ' + 'defines, additional inputs do not generate a new configuration; instead ' + 'they are treated as dependencies of the targets that use them.'); argParser.addOption('depfile', - help: 'A file path where a depfile will be written. ' - 'This contains all build inputs and outputs in a Make-style syntax.' - ); - argParser.addOption('build-inputs', help: 'A file path where a newline-separated ' - 'file containing all inputs used will be written after a build. ' - 'This file is not included as a build input or output. This file is not ' - 'written if the build fails for any reason.'); - argParser.addOption('build-outputs', help: 'A file path where a newline-separated ' - 'file containing all outputs created will be written after a build. ' - 'This file is not included as a build input or output. This file is not ' - 'written if the build fails for any reason.'); - argParser.addOption('output', abbr: 'o', help: 'A directory where output ' - 'files will be written. Must be either absolute or relative from the ' - 'root of the current Flutter project.', + help: 'A file path where a depfile will be written. ' + 'This contains all build inputs and outputs in a Make-style syntax.'); + argParser.addOption('build-inputs', + help: 'A file path where a newline-separated ' + 'file containing all inputs used will be written after a build. ' + 'This file is not included as a build input or output. This file is not ' + 'written if the build fails for any reason.'); + argParser.addOption('build-outputs', + help: 'A file path where a newline-separated ' + 'file containing all outputs created will be written after a build. ' + 'This file is not included as a build input or output. This file is not ' + 'written if the build fails for any reason.'); + argParser.addOption( + 'output', + abbr: 'o', + help: 'A directory where output ' + 'files will be written. Must be either absolute or relative from the ' + 'root of the current Flutter project.', ); usesExtraDartFlagOptions(verboseHelp: verboseHelp); usesDartDefineOption(); @@ -163,7 +168,8 @@ class AssembleCommand extends FlutterCommand { } final TargetPlatform targetPlatform = getTargetPlatformForName(platform); - final DevelopmentArtifact? artifact = artifactFromTargetPlatform(targetPlatform); + final DevelopmentArtifact? artifact = + artifactFromTargetPlatform(targetPlatform); if (artifact != null) { return {artifact}; } @@ -178,13 +184,11 @@ class AssembleCommand extends FlutterCommand { } final String name = argumentResults.rest.first; final Map targetMap = { - for (final Target target in _kDefaultTargets) - target.name: target, + for (final Target target in _kDefaultTargets) target.name: target, }; final List results = [ for (final String targetName in argumentResults.rest) - if (targetMap.containsKey(targetName)) - targetMap[targetName]!, + if (targetMap.containsKey(targetName)) targetMap[targetName]!, ]; if (results.isEmpty) { throwToolExit('No target named "$name" defined.'); @@ -241,8 +245,8 @@ class AssembleCommand extends FlutterCommand { usage: globals.flutterUsage, platform: globals.platform, engineVersion: artifacts.isLocalEngine - ? null - : globals.flutterVersion.engineRevision, + ? null + : globals.flutterVersion.engineRevision, generateDartPluginRegistry: true, ); return result; @@ -261,37 +265,50 @@ class AssembleCommand extends FlutterCommand { } final ArgResults argumentResults = argResults!; if (argumentResults.wasParsed(FlutterOptions.kExtraGenSnapshotOptions)) { - results[kExtraGenSnapshotOptions] = (argumentResults[FlutterOptions.kExtraGenSnapshotOptions] as List).join(','); + results[kExtraGenSnapshotOptions] = + (argumentResults[FlutterOptions.kExtraGenSnapshotOptions] + as List) + .join(','); } List dartDefines = []; if (argumentResults.wasParsed(FlutterOptions.kDartDefinesOption)) { - dartDefines = argumentResults[FlutterOptions.kDartDefinesOption] as List; + dartDefines = + argumentResults[FlutterOptions.kDartDefinesOption] as List; } if (argumentResults.wasParsed(FlutterOptions.kDartDefineFromFileOption)) { - final String? configJsonPath = stringArg(FlutterOptions.kDartDefineFromFileOption); + final String? configJsonPath = + stringArg(FlutterOptions.kDartDefineFromFileOption); if (configJsonPath != null && globals.fs.isFileSync(configJsonPath)) { - final String configJsonRaw = globals.fs.file(configJsonPath).readAsStringSync(); + final String configJsonRaw = + globals.fs.file(configJsonPath).readAsStringSync(); try { - (json.decode(configJsonRaw) as Map).forEach((String key, dynamic value) { + (json.decode(configJsonRaw) as Map) + .forEach((String key, dynamic value) { dartDefines.add('$key=$value'); }); } on FormatException catch (err) { - throwToolExit('Json config define file "--${FlutterOptions.kDartDefineFromFileOption}=$configJsonPath" format err, ' + throwToolExit( + 'Json config define file "--${FlutterOptions.kDartDefineFromFileOption}=$configJsonPath" format err, ' 'please fix first! format err:\n$err'); } } } - if(dartDefines.isNotEmpty){ + if (dartDefines.isNotEmpty) { results[kDartDefines] = dartDefines.join(','); } results[kDeferredComponents] = 'false'; - if (FlutterProject.current().manifest.deferredComponents != null && isDeferredComponentsTargets() && !isDebug()) { + if (FlutterProject.current().manifest.deferredComponents != null && + isDeferredComponentsTargets() && + !isDebug()) { results[kDeferredComponents] = 'true'; } if (argumentResults.wasParsed(FlutterOptions.kExtraFrontEndOptions)) { - results[kExtraFrontEndOptions] = (argumentResults[FlutterOptions.kExtraFrontEndOptions] as List).join(','); + results[kExtraFrontEndOptions] = + (argumentResults[FlutterOptions.kExtraFrontEndOptions] + as List) + .join(','); } return results; } @@ -314,17 +331,17 @@ class AssembleCommand extends FlutterCommand { decodedDefines = decodeDartDefines(environment.defines, kDartDefines); } on FormatException { throwToolExit( - 'Error parsing assemble command: your generated configuration may be out of date. ' - "Try re-running 'flutter build ios' or the appropriate build command." - ); + 'Error parsing assemble command: your generated configuration may be out of date. ' + "Try re-running 'flutter build ios' or the appropriate build command."); } - if (FlutterProject.current().manifest.deferredComponents != null - && decodedDefines.contains('validate-deferred-components=true') - && deferredTargets.isNotEmpty - && !isDebug()) { + if (FlutterProject.current().manifest.deferredComponents != null && + decodedDefines.contains('validate-deferred-components=true') && + deferredTargets.isNotEmpty && + !isDebug()) { // Add deferred components validation target that require loading units. target = DeferredComponentsGenSnapshotValidatorTarget( - deferredComponentsDependencies: deferredTargets.cast(), + deferredComponentsDependencies: + deferredTargets.cast(), nonDeferredComponentsDependencies: nonDeferredTargets, title: 'Deferred components gen_snapshot validation', ); @@ -339,15 +356,17 @@ class AssembleCommand extends FlutterCommand { environment, buildSystemConfig: BuildSystemConfig( resourcePoolSize: argumentResults.wasParsed('resource-pool-size') - ? int.tryParse(stringArgDeprecated('resource-pool-size')!) - : null, - ), - ); + ? int.tryParse(stringArgDeprecated('resource-pool-size')!) + : null, + ), + ); if (!result.success) { for (final ExceptionMeasurement measurement in result.exceptions.values) { if (measurement.fatal || globals.logger.isVerbose) { - globals.printError('Target ${measurement.target} failed: ${measurement.exception}', - stackTrace: globals.logger.isVerbose ? measurement.stackTrace : null, + globals.printError( + 'Target ${measurement.target} failed: ${measurement.exception}', + stackTrace: + globals.logger.isVerbose ? measurement.stackTrace : null, ); } } @@ -356,13 +375,16 @@ class AssembleCommand extends FlutterCommand { globals.printTrace('build succeeded.'); if (argumentResults.wasParsed('build-inputs')) { - writeListIfChanged(result.inputFiles, stringArgDeprecated('build-inputs')!); + writeListIfChanged( + result.inputFiles, stringArgDeprecated('build-inputs')!); } if (argumentResults.wasParsed('build-outputs')) { - writeListIfChanged(result.outputFiles, stringArgDeprecated('build-outputs')!); + writeListIfChanged( + result.outputFiles, stringArgDeprecated('build-outputs')!); } if (argumentResults.wasParsed('performance-measurement-file')) { - final File outFile = globals.fs.file(argumentResults['performance-measurement-file']); + final File outFile = + globals.fs.file(argumentResults['performance-measurement-file']); writePerformanceData(result.performance.values, outFile); } if (argumentResults.wasParsed('depfile')) { @@ -398,7 +420,8 @@ void writeListIfChanged(List files, String path) { /// Output performance measurement data in [outFile]. @visibleForTesting -void writePerformanceData(Iterable measurements, File outFile) { +void writePerformanceData( + Iterable measurements, File outFile) { final Map jsonData = { 'targets': [ for (final PerformanceMeasurement measurement in measurements) diff --git a/packages/flutter_tools/lib/src/commands/build.dart b/packages/flutter_tools/lib/src/commands/build.dart index 8ecd83bb21d74fb5f9d772ea06a847e7d1084641..1dbf99a4c1d29188467431018b202d086d808f1e 100644 --- a/packages/flutter_tools/lib/src/commands/build.dart +++ b/packages/flutter_tools/lib/src/commands/build.dart @@ -18,6 +18,7 @@ import 'build_aar.dart'; import 'build_apk.dart'; import 'build_appbundle.dart'; import 'build_bundle.dart'; +import 'build_hap.dart'; import 'build_ios.dart'; import 'build_ios_framework.dart'; import 'build_macos_framework.dart'; @@ -67,6 +68,7 @@ class BuildCommand extends FlutterCommand { verboseHelp: verboseHelp )); _addSubcommand(BuildWindowsCommand(logger: logger, verboseHelp: verboseHelp)); + _addSubcommand(BuildHapCommand(logger: logger, verboseHelp: verboseHelp)); } void _addSubcommand(BuildSubCommand command) { diff --git a/packages/flutter_tools/lib/src/commands/build_hap.dart b/packages/flutter_tools/lib/src/commands/build_hap.dart new file mode 100644 index 0000000000000000000000000000000000000000..61112158d559ee0d69e9a98dc94fd1ebb2b885a7 --- /dev/null +++ b/packages/flutter_tools/lib/src/commands/build_hap.dart @@ -0,0 +1,56 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import '../build_info.dart'; +import '../globals.dart' as globals; +import '../ohos/build_hap.dart'; +import '../project.dart'; +import '../runner/flutter_command.dart'; +import 'build.dart'; + +class BuildHapCommand extends BuildSubCommand { + BuildHapCommand({required super.logger, bool verboseHelp = false}) + : super(verboseHelp: verboseHelp) { + const String defaultTargetPlatform = 'ohos-arm64'; + argParser.addOption( + 'target-platform', + defaultsTo: defaultTargetPlatform, + allowed: ['ohos-arm64', 'ohos-arm', 'ohos-x86'], + help: 'The target platform for which the app is compiled.', + ); + addBuildModeFlags(verboseHelp: verboseHelp); + } + + @override + final String description = 'Build an Ohos Hap file from your app.\n\n'; + + @override + String get name => 'hap'; + + @override + Future runCommand() async { + final BuildInfo buildInfo = await getBuildInfo(); + final TargetPlatform targetPlatform = + getTargetPlatformForName(stringArgDeprecated('target-platform')!); + await buildHap( + FlutterProject.current(), + buildInfo, + targetPlatform: targetPlatform, + logger: globals.logger, + target: getNameForTargetPlatform(targetPlatform), + ); + return FlutterCommandResult.success(); + } +} diff --git a/packages/flutter_tools/lib/src/commands/config.dart b/packages/flutter_tools/lib/src/commands/config.dart index f67b9c995bc6330d8dbcaedd902d6cac55274aab..066ebd4ed04d33af971fcd53d38a580d214536a4 100644 --- a/packages/flutter_tools/lib/src/commands/config.dart +++ b/packages/flutter_tools/lib/src/commands/config.dart @@ -20,6 +20,9 @@ class ConfigCommand extends FlutterCommand { help: 'Clear the saved development certificate choice used to sign apps for iOS device deployment.'); argParser.addOption('android-sdk', help: 'The Android SDK directory.'); argParser.addOption('android-studio-dir', help: 'The Android Studio install directory.'); + argParser.addOption('ohos-sdk', help: 'The OpenHarmony SDK directory.'); + argParser.addOption('ohpm-home', help: 'The ohpm tool directory.'); + argParser.addOption('signTool-home', help: 'The sign tool directory.'); argParser.addOption('build-dir', help: 'The relative path to override a projects build directory.', valueHelp: 'out/'); argParser.addFlag('machine', @@ -139,6 +142,18 @@ class ConfigCommand extends FlutterCommand { _updateConfig('android-studio-dir', stringArgDeprecated('android-studio-dir')!); } + if (argResults?.wasParsed('ohos-sdk') ?? false) { + _updateConfig('ohos-sdk', stringArgDeprecated('ohos-sdk')!); + } + + if (argResults?.wasParsed('ohpm-home') ?? false) { + _updateConfig('ohpm-home', stringArgDeprecated('ohpm-home')!); + } + + if (argResults?.wasParsed('signTool-home') ?? false) { + _updateConfig('signTool-home', stringArgDeprecated('signTool-home')!); + } + if (argResults?.wasParsed('clear-ios-signing-cert') ?? false) { _updateConfig('ios-signing-cert', ''); } diff --git a/packages/flutter_tools/lib/src/commands/create.dart b/packages/flutter_tools/lib/src/commands/create.dart index fc72baea884ae616c083924e5e6ba705a76febb3..861af4ff0a6f643c1c0a78e99946214bca68bd63 100644 --- a/packages/flutter_tools/lib/src/commands/create.dart +++ b/packages/flutter_tools/lib/src/commands/create.dart @@ -274,6 +274,7 @@ class CreateCommand extends CreateBase { final bool includeLinux; final bool includeMacos; final bool includeWindows; + final bool includeOhos; if (template == FlutterProjectType.module) { // The module template only supports iOS and Android. includeIos = true; @@ -282,6 +283,7 @@ class CreateCommand extends CreateBase { includeLinux = false; includeMacos = false; includeWindows = false; + includeOhos = false; } else { includeIos = featureFlags.isIOSEnabled && platforms.contains('ios'); includeAndroid = featureFlags.isAndroidEnabled && platforms.contains('android'); @@ -289,6 +291,7 @@ class CreateCommand extends CreateBase { includeLinux = featureFlags.isLinuxEnabled && platforms.contains('linux'); includeMacos = featureFlags.isMacOSEnabled && platforms.contains('macos'); includeWindows = featureFlags.isWindowsEnabled && platforms.contains('windows'); + includeOhos = featureFlags.isOhosEnabled && platforms.contains('ohos'); } String? developmentTeam; @@ -323,6 +326,7 @@ class CreateCommand extends CreateBase { linux: includeLinux, macos: includeMacos, windows: includeWindows, + ohos: includeOhos, // Enable null safety everywhere. dartSdkVersionBounds: "'>=$dartSdk <3.0.0'", implementationTests: boolArgDeprecated('implementation-tests'), diff --git a/packages/flutter_tools/lib/src/commands/create_base.dart b/packages/flutter_tools/lib/src/commands/create_base.dart index 0fc09004af2827e174cfa0f24e19271f87edf1b0..166b410504fd4d633b00b629496bcf67284cd2eb 100644 --- a/packages/flutter_tools/lib/src/commands/create_base.dart +++ b/packages/flutter_tools/lib/src/commands/create_base.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:io'; + import 'package:meta/meta.dart'; import 'package:pub_semver/pub_semver.dart'; import 'package:uuid/uuid.dart'; @@ -30,6 +32,7 @@ const List _kAvailablePlatforms = [ 'linux', 'macos', 'web', + 'ohos', ]; /// A list of all possible create platforms, even those that may not be enabled @@ -41,6 +44,7 @@ const List kAllCreatePlatforms = [ 'linux', 'macos', 'web', + 'ohos', ]; const String _kDefaultPlatformArgumentHelp = @@ -361,6 +365,7 @@ abstract class CreateBase extends FlutterCommand { bool linux = false, bool macos = false, bool windows = false, + bool ohos = false, bool implementationTests = false, }) { final String pluginDartClass = _createPluginClassName(projectName); @@ -382,12 +387,20 @@ abstract class CreateBase extends FlutterCommand { // https://developer.gnome.org/gio/stable/GApplication.html#g-application-id-is-valid final String linuxIdentifier = androidIdentifier; + // TODO(dacoharkes): Replace with hardcoded version in template when Flutter 2.11 is released. final Version ffiPluginStableRelease = Version(2, 11, 0); final String minFrameworkVersionFfiPlugin = Version.parse(globals.flutterVersion.frameworkVersion) < ffiPluginStableRelease ? globals.flutterVersion.frameworkVersion : ffiPluginStableRelease.toString(); + // Ohos uses the same scheme as the Android identifier. + final String ohosIdentifier = androidIdentifier; + // locating ohos sdk from environment + final String? ohosSdkHome = globals.ohosSdk?.sdkPath; + final String? hosSdkHome = Platform.environment['HOS_SDK_HOME']; + final String? nodeHome = Platform.environment['NODE_HOME']; + return { 'organization': organization, 'projectName': projectName, @@ -397,6 +410,10 @@ abstract class CreateBase extends FlutterCommand { 'macosIdentifier': appleIdentifier, 'linuxIdentifier': linuxIdentifier, 'windowsIdentifier': windowsIdentifier, + 'ohosIdentifier':ohosIdentifier, + 'ohosSdkHome':ohosSdkHome, + 'hosSdkHome':hosSdkHome, + 'nodeHome':nodeHome, 'description': projectDescription, 'dartSdk': '$flutterRoot/bin/cache/dart-sdk', 'androidMinApiLevel': android_common.minApiLevel, @@ -424,6 +441,7 @@ abstract class CreateBase extends FlutterCommand { 'linux': linux, 'macos': macos, 'windows': windows, + 'ohos': ohos, 'year': DateTime.now().year, 'dartSdkVersionBounds': dartSdkVersionBounds, 'implementationTests': implementationTests, @@ -527,6 +545,7 @@ abstract class CreateBase extends FlutterCommand { final bool macOSPlatform = templateContext['macos'] as bool? ?? false; final bool windowsPlatform = templateContext['windows'] as bool? ?? false; final bool webPlatform = templateContext['web'] as bool? ?? false; + final bool ohosPlatform = templateContext['ohos'] as bool ? ?? false; if (boolArgDeprecated('pub')) { final Environment environment = Environment( @@ -571,6 +590,9 @@ abstract class CreateBase extends FlutterCommand { if (windowsPlatform) { platformsForMigrateConfig.add(SupportedPlatform.windows); } + if (ohosPlatform) { + platformsForMigrateConfig.add(SupportedPlatform.ohos); + } if (templateContext['fuchsia'] == true) { platformsForMigrateConfig.add(SupportedPlatform.fuchsia); } diff --git a/packages/flutter_tools/lib/src/commands/daemon.dart b/packages/flutter_tools/lib/src/commands/daemon.dart index 11fb279f459cb91386189ea25782c6ab15a1b020..39cd12e10673bdd67402eea74e7e5a79e0b409f2 100644 --- a/packages/flutter_tools/lib/src/commands/daemon.dart +++ b/packages/flutter_tools/lib/src/commands/daemon.dart @@ -425,6 +425,9 @@ class DaemonDomain extends Domain { if (featureFlags.isWindowsEnabled && supportedPlatforms.contains(SupportedPlatform.windows)) { result.add('windows'); } + if (featureFlags.isOhosEnabled && supportedPlatforms.contains(SupportedPlatform.ohos)) { + result.add('ohos'); + } if (featureFlags.isIOSEnabled && supportedPlatforms.contains(SupportedPlatform.ios)) { result.add('ios'); } diff --git a/packages/flutter_tools/lib/src/context_runner.dart b/packages/flutter_tools/lib/src/context_runner.dart index 606fadd9e46fe956da8c290d527173f313fa3658..1687e091416845fc26205c5cee424632b21df070 100644 --- a/packages/flutter_tools/lib/src/context_runner.dart +++ b/packages/flutter_tools/lib/src/context_runner.dart @@ -55,6 +55,9 @@ import 'macos/macos_workflow.dart'; import 'macos/xcdevice.dart'; import 'macos/xcode.dart'; import 'mdns_discovery.dart'; +import 'ohos/ohos_doctor.dart'; +import 'ohos/ohos_sdk.dart'; +import 'ohos/ohos_workflow.dart'; import 'persistent_tool_state.dart'; import 'reporting/crash_reporting.dart'; import 'reporting/first_run.dart'; @@ -107,6 +110,7 @@ Future runInContext( stdio: globals.stdio, ), AndroidSdk: AndroidSdk.locateAndroidSdk, + OhosSdk: OhosSdk.localOhosSdk, AndroidStudio: AndroidStudio.latestValid, AndroidValidator: () => AndroidValidator( androidStudio: globals.androidStudio, @@ -117,6 +121,17 @@ Future runInContext( processManager: globals.processManager, userMessages: globals.userMessages, ), + OhosValidator: () => OhosValidator( + ohosSdk: globals.ohosSdk, + fileSystem: globals.fs, + logger: globals.logger, + platform: globals.platform, + processManager: globals.processManager, + userMessages: userMessages), + OhosWorkflow: () => OhosWorkflow( + ohosSdk: globals.ohosSdk, + featureFlags: featureFlags, + ), AndroidWorkflow: () => AndroidWorkflow( androidSdk: globals.androidSdk, featureFlags: featureFlags, @@ -127,6 +142,7 @@ Future runInContext( logger: globals.logger, fileSystem: globals.fs, androidSdk: globals.androidSdk, + ohosSdk: globals.ohosSdk, ), Artifacts: () => CachedArtifacts( fileSystem: globals.fs, @@ -187,12 +203,14 @@ Future runInContext( processManager: globals.processManager, platform: globals.platform, androidSdk: globals.androidSdk, + ohosSdk: globals.ohosSdk, iosSimulatorUtils: globals.iosSimulatorUtils!, featureFlags: featureFlags, fileSystem: globals.fs, iosWorkflow: globals.iosWorkflow!, artifacts: globals.artifacts!, flutterVersion: globals.flutterVersion, + ohosWorkflow: ohosWorkflow!, androidWorkflow: androidWorkflow!, fuchsiaWorkflow: fuchsiaWorkflow!, xcDevice: globals.xcdevice!, diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart index 63318dfc4ef178ff637f8fa0ac360be0da33d90a..dd205ac645c239b13956017761a62c18b87f4b7f 100644 --- a/packages/flutter_tools/lib/src/device.dart +++ b/packages/flutter_tools/lib/src/device.dart @@ -55,6 +55,7 @@ class PlatformType { static const PlatformType macos = PlatformType._('macos'); static const PlatformType windows = PlatformType._('windows'); static const PlatformType fuchsia = PlatformType._('fuchsia'); + static const PlatformType ohos = PlatformType._('ohos'); static const PlatformType custom = PlatformType._('custom'); final String value; @@ -71,6 +72,7 @@ class PlatformType { 'macos': macos, 'windows': windows, 'fuchsia': fuchsia, + 'ohos':ohos, 'custom': custom, }[platformType]; } diff --git a/packages/flutter_tools/lib/src/doctor.dart b/packages/flutter_tools/lib/src/doctor.dart index 651dc6cf367aa3ac3ff2843b229184575fea7d3c..370eccbf469bd3c9f11f41d010cc0a2f418536c5 100644 --- a/packages/flutter_tools/lib/src/doctor.dart +++ b/packages/flutter_tools/lib/src/doctor.dart @@ -33,6 +33,7 @@ import 'linux/linux_doctor.dart'; import 'linux/linux_workflow.dart'; import 'macos/macos_workflow.dart'; import 'macos/xcode_validator.dart'; +import 'ohos/ohos_doctor.dart'; import 'proxy_validator.dart'; import 'reporting/reporting.dart'; import 'tester/flutter_tester.dart'; @@ -130,6 +131,7 @@ class _DefaultDoctorValidatorsProvider implements DoctorValidatorsProvider { flutterRoot: () => Cache.flutterRoot!, operatingSystemUtils: globals.os, ), + ohosValidator!, //OhosValidator if (platform.isWindows) WindowsVersionValidator( processManager: globals.processManager, diff --git a/packages/flutter_tools/lib/src/features.dart b/packages/flutter_tools/lib/src/features.dart index 1562375c785b9a761765823b5da935cc7665e97c..368f8ed425270ac4e5ccfdeb4b9d01900de426e7 100644 --- a/packages/flutter_tools/lib/src/features.dart +++ b/packages/flutter_tools/lib/src/features.dart @@ -20,6 +20,9 @@ abstract class FeatureFlags { /// const constructor so that subclasses can be const. const FeatureFlags(); + /// Whether flutter desktop for ohos is enabled. + bool get isOhosEnabled => false; + /// Whether flutter desktop for linux is enabled. bool get isLinuxEnabled => false; @@ -55,6 +58,7 @@ abstract class FeatureFlags { /// All current Flutter feature flags. const List allFeatures = [ + flutterOhosFeature, flutterWebFeature, flutterLinuxDesktopFeature, flutterMacOSDesktopFeature, @@ -142,6 +146,24 @@ const Feature flutterWindowsDesktopFeature = Feature( ), ); +/// The [Feature] for Ohos devices. +const Feature flutterOhosFeature = Feature( + name: 'Flutter for Ohos', + configSetting: 'enable-ohos', + master: FeatureChannelSetting( + available: true, + enabledByDefault: true, + ), + beta: FeatureChannelSetting( + available: true, + enabledByDefault: true, + ), + stable: FeatureChannelSetting( + available: true, + enabledByDefault: true, + ), +); + /// The [Feature] for Android devices. const Feature flutterAndroidFeature = Feature( name: 'Flutter for Android', @@ -160,7 +182,6 @@ const Feature flutterAndroidFeature = Feature( ), ); - /// The [Feature] for iOS devices. const Feature flutterIOSFeature = Feature( name: 'Flutter for iOS', @@ -228,15 +249,14 @@ const Feature singleWidgetReload = Feature( /// settings. class Feature { /// Creates a [Feature]. - const Feature({ - required this.name, - this.environmentOverride, - this.configSetting, - this.extraHelpText, - this.master = const FeatureChannelSetting(), - this.beta = const FeatureChannelSetting(), - this.stable = const FeatureChannelSetting() - }); + const Feature( + {required this.name, + this.environmentOverride, + this.configSetting, + this.extraHelpText, + this.master = const FeatureChannelSetting(), + this.beta = const FeatureChannelSetting(), + this.stable = const FeatureChannelSetting()}); /// The user visible name for this feature. final String name; @@ -286,8 +306,7 @@ class Feature { } else if (channels.length == 2) { buffer.write('the ${channels.join(' and ')} channels.'); } else { - final String prefix = (channels.toList() - ..removeLast()).join(', '); + final String prefix = (channels.toList()..removeLast()).join(', '); buffer.write('the $prefix, and ${channels.last} channels.'); } if (extraHelpText != null) { diff --git a/packages/flutter_tools/lib/src/flutter_application_package.dart b/packages/flutter_tools/lib/src/flutter_application_package.dart index 103f21c04394db5f150468d4b2b5893a049c9dc5..32d8ddf85521eab43bce47ace7d8b89ddc27973c 100644 --- a/packages/flutter_tools/lib/src/flutter_application_package.dart +++ b/packages/flutter_tools/lib/src/flutter_application_package.dart @@ -17,6 +17,8 @@ import 'globals.dart' as globals; import 'ios/application_package.dart'; import 'linux/application_package.dart'; import 'macos/application_package.dart'; +import 'ohos/application_package.dart'; +import 'ohos/ohos_sdk.dart'; import 'project.dart'; import 'tester/flutter_tester.dart'; import 'web/web_device.dart'; @@ -26,19 +28,22 @@ import 'windows/application_package.dart'; class FlutterApplicationPackageFactory extends ApplicationPackageFactory { FlutterApplicationPackageFactory({ required AndroidSdk? androidSdk, + required OhosSdk? ohosSdk, required ProcessManager processManager, required Logger logger, required UserMessages userMessages, required FileSystem fileSystem, - }) : _androidSdk = androidSdk, - _processManager = processManager, - _logger = logger, - _userMessages = userMessages, - _fileSystem = fileSystem, - _processUtils = ProcessUtils(logger: logger, processManager: processManager); - + }) : _androidSdk = androidSdk, + _ohosSdk = ohosSdk, + _processManager = processManager, + _logger = logger, + _userMessages = userMessages, + _fileSystem = fileSystem, + _processUtils = + ProcessUtils(logger: logger, processManager: processManager); final AndroidSdk? _androidSdk; + final OhosSdk? _ohosSdk; final ProcessManager _processManager; final Logger _logger; final ProcessUtils _processUtils; @@ -79,7 +84,8 @@ class FlutterApplicationPackageFactory extends ApplicationPackageFactory { ); case TargetPlatform.ios: return applicationBinary == null - ? await IOSApp.fromIosProject(FlutterProject.current().ios, buildInfo) + ? await IOSApp.fromIosProject( + FlutterProject.current().ios, buildInfo) : IOSApp.fromPrebuiltApp(applicationBinary); case TargetPlatform.tester: return FlutterTesterApp.fromCurrentDirectory(globals.fs); @@ -106,6 +112,30 @@ class FlutterApplicationPackageFactory extends ApplicationPackageFactory { return applicationBinary == null ? FuchsiaApp.fromFuchsiaProject(FlutterProject.current().fuchsia) : FuchsiaApp.fromPrebuiltApp(applicationBinary); + case TargetPlatform.ohos: + case TargetPlatform.ohos_arm64: + case TargetPlatform.ohos_arm: + case TargetPlatform.ohos_x64: + if (applicationBinary == null) { + return OhosHap.fromOhosProject( + FlutterProject.current().ohos, + processManager: _processManager, + processUtils: _processUtils, + logger: _logger, + ohosSdk: _ohosSdk, + userMessages: _userMessages, + fileSystem: _fileSystem, + buildInfo: buildInfo, + ); + } + return OhosHap.fromHap( + applicationBinary, + ohosSdk: _ohosSdk!, + processManager: _processManager, + logger: _logger, + userMessages: _userMessages, + processUtils: _processUtils, + ); } } } diff --git a/packages/flutter_tools/lib/src/flutter_device_manager.dart b/packages/flutter_tools/lib/src/flutter_device_manager.dart index 47411190ca349d08dd0f11001c2f29923205d551..84299ee89039f029064dcfee44543a8366758fb3 100644 --- a/packages/flutter_tools/lib/src/flutter_device_manager.dart +++ b/packages/flutter_tools/lib/src/flutter_device_manager.dart @@ -27,6 +27,9 @@ import 'macos/macos_device.dart'; import 'macos/macos_ipad_device.dart'; import 'macos/macos_workflow.dart'; import 'macos/xcdevice.dart'; +import 'ohos/ohos_device_discovery.dart'; +import 'ohos/ohos_sdk.dart'; +import 'ohos/ohos_workflow.dart'; import 'tester/flutter_tester.dart'; import 'version.dart'; import 'web/web_device.dart'; @@ -42,10 +45,12 @@ class FlutterDeviceManager extends DeviceManager { required ProcessManager processManager, required FileSystem fileSystem, required AndroidSdk? androidSdk, + required OhosSdk? ohosSdk, required FeatureFlags featureFlags, required IOSSimulatorUtils iosSimulatorUtils, required XCDevice xcDevice, required AndroidWorkflow androidWorkflow, + required OhosWorkflow ohosWorkflow, required IOSWorkflow iosWorkflow, required FuchsiaWorkflow fuchsiaWorkflow, required FlutterVersion flutterVersion, @@ -66,6 +71,15 @@ class FlutterDeviceManager extends DeviceManager { platform: platform, userMessages: userMessages, ), + OhosDevices( + logger: logger, + ohosSdk: ohosSdk, + processManager: processManager, + fileSystem: fileSystem, + platform: platform, + userMessages: userMessages, + ohosWorkflow: ohosWorkflow, + ), IOSDevices( platform: platform, xcdevice: xcDevice, diff --git a/packages/flutter_tools/lib/src/flutter_features.dart b/packages/flutter_tools/lib/src/flutter_features.dart index 9f4ce259850f82c13643a76c36466ae4a410eefd..55a801953f111b6d3f19fc4c2f1c050d3dec64b2 100644 --- a/packages/flutter_tools/lib/src/flutter_features.dart +++ b/packages/flutter_tools/lib/src/flutter_features.dart @@ -12,14 +12,17 @@ class FlutterFeatureFlags implements FeatureFlags { required FlutterVersion flutterVersion, required Config config, required Platform platform, - }) : _flutterVersion = flutterVersion, - _config = config, - _platform = platform; + }) : _flutterVersion = flutterVersion, + _config = config, + _platform = platform; final FlutterVersion _flutterVersion; final Config _config; final Platform _platform; + @override + bool get isOhosEnabled => isEnabled(flutterOhosFeature); + @override bool get isLinuxEnabled => isEnabled(flutterLinuxDesktopFeature); @@ -50,19 +53,22 @@ class FlutterFeatureFlags implements FeatureFlags { @override bool isEnabled(Feature feature) { final String currentChannel = _flutterVersion.channel; - final FeatureChannelSetting featureSetting = feature.getSettingForChannel(currentChannel); + final FeatureChannelSetting featureSetting = + feature.getSettingForChannel(currentChannel); if (!featureSetting.available) { return false; } bool isEnabled = featureSetting.enabledByDefault; if (feature.configSetting != null) { - final bool? configOverride = _config.getValue(feature.configSetting!) as bool?; + final bool? configOverride = + _config.getValue(feature.configSetting!) as bool?; if (configOverride != null) { isEnabled = configOverride; } } if (feature.environmentOverride != null) { - if (_platform.environment[feature.environmentOverride]?.toLowerCase() == 'true') { + if (_platform.environment[feature.environmentOverride]?.toLowerCase() == + 'true') { isEnabled = true; } } diff --git a/packages/flutter_tools/lib/src/globals.dart b/packages/flutter_tools/lib/src/globals.dart index 260eaf56653e4c3afac795068869cbf7ad8b97f9..6ca582a8aa61b5f7bf1ded5428eb701ec5066027 100644 --- a/packages/flutter_tools/lib/src/globals.dart +++ b/packages/flutter_tools/lib/src/globals.dart @@ -38,6 +38,7 @@ import 'macos/cocoapods.dart'; import 'macos/cocoapods_validator.dart'; import 'macos/xcdevice.dart'; import 'macos/xcode.dart'; +import 'ohos/ohos_sdk.dart'; import 'persistent_tool_state.dart'; import 'pre_run_validator.dart'; import 'project.dart'; @@ -61,6 +62,7 @@ OperatingSystemUtils get os => context.get()!; Signals get signals => context.get() ?? LocalSignals.instance; AndroidStudio? get androidStudio => context.get(); AndroidSdk? get androidSdk => context.get(); +OhosSdk? get ohosSdk => context.get(); FlutterVersion get flutterVersion => context.get()!; FuchsiaArtifacts? get fuchsiaArtifacts => context.get(); FuchsiaSdk? get fuchsiaSdk => context.get(); diff --git a/packages/flutter_tools/lib/src/ohos/application_package.dart b/packages/flutter_tools/lib/src/ohos/application_package.dart new file mode 100644 index 0000000000000000000000000000000000000000..c1d23c8a9736b4ba0ca6f711a6193038dc7edac2 --- /dev/null +++ b/packages/flutter_tools/lib/src/ohos/application_package.dart @@ -0,0 +1,130 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import 'package:json5/json5.dart'; +import 'package:process/process.dart'; + +import '../application_package.dart'; +import '../base/common.dart'; +import '../base/file_system.dart'; +import '../base/logger.dart'; +import '../base/process.dart'; +import '../base/user_messages.dart'; +import '../build_info.dart'; +import '../project.dart'; +import 'ohos_sdk.dart'; + +/// An application package created from an already built Ohos HAP. +class OhosHap extends ApplicationPackage implements PrebuiltApplicationPackage { + OhosHap({ + required super.id, + required this.applicationPackage, + required this.ohosBuildData, + }) : assert(applicationPackage != null), + assert(ohosBuildData != null); + + @override + final FileSystemEntity applicationPackage; + + OhosBuildData ohosBuildData; + + @override + String? get name => applicationPackage.basename; + + /// Creates a new OhosHap based on the information in the Ohos build-profile. + static Future fromOhosProject( + OhosProject ohosProject, { + required OhosSdk? ohosSdk, + required ProcessManager processManager, + required UserMessages userMessages, + required ProcessUtils processUtils, + required Logger logger, + required FileSystem fileSystem, + BuildInfo? buildInfo, + }) async { + /// parse the build data + final OhosBuildData ohosBuildData = + OhosBuildData.parseOhosBuildData(ohosProject, logger); + final String bundleName = ohosBuildData.appInfo.bundleName; + return OhosHap( + id: bundleName, + applicationPackage: ohosProject.getSignedHapFile(), + ohosBuildData: ohosBuildData); + } + + static Future fromHap( + File hap, { + required OhosSdk ohosSdk, + required ProcessManager processManager, + required UserMessages userMessages, + required Logger logger, + required ProcessUtils processUtils, + }) async { + // TODO(xc) parse build data from hap file + return null; + } +} + +class OhosBuildData { + OhosBuildData(this.appInfo, this.modeInfo); + + late AppInfo appInfo; + late ModuleInfo modeInfo; + + static OhosBuildData parseOhosBuildData( + OhosProject ohosProject, Logger logger) { + late AppInfo appInfo; + late ModuleInfo moduleInfo; + try { + final File appJson = ohosProject.getAppJsonFile(); + final String json = appJson.readAsStringSync(); + final dynamic obj = JSON5.parse(json); + appInfo = AppInfo.getAppInfo(obj); + final File moduleJson = ohosProject.getModuleJsonFile(); + final String moduleStr = moduleJson.readAsStringSync(); + final dynamic module = JSON5.parse(moduleStr); + moduleInfo = ModuleInfo.getModuleInfo(module); + } on Exception catch (err) { + throwToolExit('parse ohos project build data exception! $err'); + } + return OhosBuildData(appInfo, moduleInfo); + } +} + +class AppInfo { + AppInfo(this.bundleName, this.versionCode, this.versionName); + + late String bundleName; + late int versionCode; + late String versionName; + + static AppInfo getAppInfo(dynamic app) { + final String bundleName = app['app']['bundleName'] as String; + final int versionCode = app['app']['versionCode'] as int; + final String versionName = app['app']['versionName'] as String; + return AppInfo(bundleName, versionCode, versionName); + } +} + +class ModuleInfo { + ModuleInfo(this.mainElement); + + late String mainElement; + + static ModuleInfo getModuleInfo(dynamic module) { + final String mainElement = module['module']['mainElement'] as String; + return ModuleInfo(mainElement); + } +} diff --git a/packages/flutter_tools/lib/src/ohos/build_env.dart b/packages/flutter_tools/lib/src/ohos/build_env.dart new file mode 100644 index 0000000000000000000000000000000000000000..ffc2bbc2decd6022963fae73ccd7438bea584d65 --- /dev/null +++ b/packages/flutter_tools/lib/src/ohos/build_env.dart @@ -0,0 +1,49 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +class BuildEnv { + BuildEnv(this.ohpmHome, this.localEngine); + + final String ohpmHome; + final String localEngine; +} diff --git a/packages/flutter_tools/lib/src/ohos/build_hap.dart b/packages/flutter_tools/lib/src/ohos/build_hap.dart new file mode 100644 index 0000000000000000000000000000000000000000..e50cbf6a261c93309012bf8ebf8408a7808351d9 --- /dev/null +++ b/packages/flutter_tools/lib/src/ohos/build_hap.dart @@ -0,0 +1,437 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import 'dart:io'; + +import 'package:process/process.dart'; + +import '../artifacts.dart'; +import '../base/analyze_size.dart'; +import '../base/common.dart'; +import '../base/file_system.dart'; +import '../base/logger.dart'; +import '../base/os.dart'; +import '../build_info.dart'; +import '../build_system/build_system.dart'; +import '../build_system/targets/ohos.dart'; +import '../cache.dart'; +import '../compile.dart'; +import '../globals.dart' as globals; +import '../project.dart'; +import 'build_env.dart'; +import '../convert.dart'; + +/// if this constant set true , must config platform environment PUB_HOSTED_URL and FLUTTER_STORAGE_BASE_URL +const bool NEED_PUB_CN = true; + +const String OHOS_DTA_FILE_NAME = 'icudtl.dat'; + +const String FLUTTER_ASSETS_PATH = 'flutter_assets'; + +const String FLUTTER_ENGINE_SO = 'libflutter.so'; + +const String APP_SO_ORIGIN = 'app.so'; + +const String APP_SO = 'libapp.so'; + +const String HAR_FILE_NAME = 'flutter_embedding.har'; + +const String HVIGORW_FILE = 'hvigorw'; + +void checkPlatformEnvironment(String environment, Logger? logger) { + final String? environmentConfig = Platform.environment[environment]; + if (environmentConfig == null) { + throwToolExit( + 'error:current platform environment $environment have not set'); + } else { + logger?.printStatus( + 'current platform environment $environment = $environmentConfig'); + } +} + +void copyFlutterAssets(String orgPath, String desPath, Logger? logger) { + logger?.printStatus('copy directory from $orgPath to $desPath'); + final LocalFileSystem localFileSystem = globals.localFileSystem; + copyDirectory( + localFileSystem.directory(orgPath), localFileSystem.directory(desPath)); +} + +/// eg:entry/src/main/resources/rawfile +String getProjectAssetsPath(String ohosRootPath) { + return globals.fs.path.join( + ohosRootPath, 'entry/src/main/resources/rawfile', FLUTTER_ASSETS_PATH); +} + +/// eg:entry/src/main/resources/rawfile/flutter_assets/ +String getDatPath(String ohosRootPath) { + return globals.fs.path + .join(getProjectAssetsPath(ohosRootPath), OHOS_DTA_FILE_NAME); +} + +/// eg:entry/libs/arm64-v8a/libflutter.so +String getEngineSoPath(String ohosRootPath, TargetPlatform targetPlatform) { + return globals.fs.path.join( + getProjectArchPath(ohosRootPath, targetPlatform), FLUTTER_ENGINE_SO); +} + +/// eg:entry/libs/arm64-v8a/libapp.so +String getAppSoPath(String ohosRootPath, TargetPlatform targetPlatform) { + return globals.fs.path + .join(getProjectArchPath(ohosRootPath, targetPlatform), APP_SO); +} + +String getProjectArchPath(String ohosRootPath, TargetPlatform targetPlatform) { + final String archPath = getArchPath(targetPlatform); + return globals.fs.path.join(ohosRootPath, 'entry/libs', archPath); +} + +String getArchPath(TargetPlatform targetPlatform) { + final String targetPlatformName = getNameForTargetPlatform(targetPlatform); + final OhosArch ohosArch = getOhosArchForName(targetPlatformName); + return getNameForOhosArch(ohosArch); +} + +/// /hvigorw todo change the file to be hvigorw.bat on windows host +String getHvigorwPath(String ohosRootPath) { + return globals.fs.path.join(ohosRootPath, HVIGORW_FILE); +} + +String getEntryPath(String ohosRootPath) { + return globals.fs.path.join(ohosRootPath, 'entry'); +} + +/// Builds the ohos project through the hvigorw. +Future buildHap(FlutterProject flutterProject, BuildInfo buildInfo, + {required String target, + SizeAnalyzer? sizeAnalyzer, + bool needCrossBuild = false, + required TargetPlatform targetPlatform, + String targetSysroot = '/', + Logger? logger}) async { + logger?.printStatus('start hap build...'); + /** + * import the har in local path + * + * 1. excute flutter assemble + * 2. copy flutter asset to ohos project + * 3. excute hvigorw script (remember chmod xxx) + * 4. finish + */ + logger?.printStatus('check platform environment'); + if (NEED_PUB_CN) { + checkPlatformEnvironment('PUB_HOSTED_URL', logger); + checkPlatformEnvironment('FLUTTER_STORAGE_BASE_URL', logger); + } + checkPlatformEnvironment('OHPM_HOME', logger); + // checkPlatformEnvironment('LOCAL_FLUTTER_ENGINE', logger); + + // BuildEnv buildEnv = BuildEnv(Platform.environment['OHPM_HOME']!, + // Platform.environment['LOCAL_FLUTTER_ENGINE']!); + + /// + /// 1. OhosDebugApplicationTarget or OhosAotBundle + /// 2. copyAssetsToProject + /// 3. ./hvigorw clean assembleHap + /// + /// + /// + /// generate target name. + late String targetName; + if (buildInfo.isDebug) { + targetName = 'debug_ohos_application'; + } else { + // eg:ohos_aot_bundle_release_ohos-arm64 + targetName = + 'ohos_aot_bundle_release_${getNameForTargetPlatform(targetPlatform)}'; + } + final List selectTarget = + ohosTargets.where((Target e) => targetName == e.name).toList(); + if (selectTarget.isEmpty) { + throwToolExit('do not found compare target.'); + } else if (selectTarget.length > 1) { + throwToolExit('more than one target match.'); + } + final Target target = selectTarget[0]; + + final Status status = + globals.logger.startProgress('Compiling $targetName for the Ohos...'); + String output = globals.fs.directory(getOhosBuildDirectory()).path; + // If path is relative, make it absolute from flutter project. + output = getAbsolutePath(flutterProject, output); + try { + final BuildResult result = await globals.buildSystem.build( + target, + Environment( + projectDir: globals.fs.currentDirectory, + outputDir: globals.fs.directory(output), + buildDir: flutterProject.directory + .childDirectory('.dart_tool') + .childDirectory('flutter_build'), + defines: { + kTargetPlatform: 'ohos', + ...buildInfo.toBuildSystemEnvironment(), + }, + artifacts: globals.artifacts!, + fileSystem: globals.fs, + logger: globals.logger, + processManager: globals.processManager, + platform: globals.platform, + usage: globals.flutterUsage, + cacheDir: globals.cache.getRoot(), + engineVersion: globals.artifacts!.isLocalEngine + ? null + : globals.flutterVersion.engineRevision, + flutterRootDir: globals.fs.directory(Cache.flutterRoot), + generateDartPluginRegistry: true, + )); + if (!result.success) { + for (final ExceptionMeasurement measurement in result.exceptions.values) { + globals.printError( + 'Target ${measurement.target} failed: ${measurement.exception}', + stackTrace: measurement.fatal ? measurement.stackTrace : null, + ); + } + throwToolExit('Failed to compile application for the Ohos.'); + } + } on Exception catch (err) { + throwToolExit(err.toString()); + } finally { + status.stop(); + } + + final String ohosRootPath = + globals.fs.path.join(flutterProject.directory.path, 'ohos'); + + // clean flutter assets + final String desFlutterAssetsPath = getProjectAssetsPath(ohosRootPath); + final Directory desAssets = globals.fs.directory(desFlutterAssetsPath); + if (desAssets.existsSync()) { + desAssets.deleteSync(recursive: true); + } + + /// copy flutter assets + logger?.printStatus('start copy flutter assets to project'); + copyFlutterAssets(globals.fs.path.join(output, FLUTTER_ASSETS_PATH), + desFlutterAssetsPath, logger); + + // copy ohos font-family support + final LocalFileSystem localFileSystem = globals.localFileSystem; + final File ohosDta = localFileSystem + .file(globals.fs.path.join(ohosRootPath, 'dta', OHOS_DTA_FILE_NAME)); + final String copyDes = getDatPath(ohosRootPath); + ohosDta.copySync(copyDes); + + //copy ohos engine so + final String? flutterEngineSoPath = + globals.artifacts?.getArtifactPath(Artifact.flutterEngineSo); + if (flutterEngineSoPath == null) { + throwToolExit("flutter engine runtime file 'libflutter.so' no found"); + } + final File flutterEngineSoFile = localFileSystem.file(flutterEngineSoPath); + final String enginCopyDes = getEngineSoPath(ohosRootPath, targetPlatform); + final Directory directory = localFileSystem.file(enginCopyDes).parent; + if (!directory.existsSync()) { + directory.createSync(recursive: true); + } + flutterEngineSoFile.copySync(enginCopyDes); + + final String desAppSoPath = getAppSoPath(ohosRootPath, targetPlatform); + if (buildInfo.isRelease) { + // copy app.so + final String appSoPath = globals.fs.path + .join(output, getArchPath(targetPlatform), APP_SO_ORIGIN); + final File appSoFile = localFileSystem.file(appSoPath); + appSoFile.copySync(desAppSoPath); + } else { + final File appSo = globals.fs.file(desAppSoPath); + if (appSo.existsSync()) { + appSo.deleteSync(); + } + } + + //copy har + final String suffix = buildInfo.isDebug ? 'debug' : 'release'; + final String originHarPath = + globals.fs.path.join(ohosRootPath, 'har', '$HAR_FILE_NAME.$suffix'); + final String desHarPath = + globals.fs.path.join(ohosRootPath, 'har', HAR_FILE_NAME); + final File originHarFile = localFileSystem.file(originHarPath); + originHarFile.copySync(desHarPath); + + logger?.printStatus('copy flutter assets to project end'); + + /// ohpm install + final String ohpmHome = Platform.environment['OHPM_HOME']!; + await ohpmInstall( + processManager: globals.processManager, + ohpmHome: ohpmHome, + entryPath: getEntryPath(ohosRootPath), + logger: logger); + + /// change hvigorw modle + final OperatingSystemUtils operatingSystemUtils = globals.os; + final String hvigorwPath = getHvigorwPath(ohosRootPath); + final File file = localFileSystem.file(hvigorwPath); + operatingSystemUtils.chmod(file, '755'); + + /// last ,invoke hvigow task generate hap file. + await assembleHap( + processManager: globals.processManager, + ohosRootPath: ohosRootPath, + hvigorwPath: hvigorwPath, + logger: logger); + + /// signer hap , this part should throw to ide + String signToolHome = Platform.environment['SIGN_TOOL_HOME'] ?? + '/home/xc/sdk/developtools_hapsigner/autosign'; + + // todo change bundleName + final String unsignedFile = globals.fs.path.join(ohosRootPath, + 'entry/build/default/outputs/default', 'entry-default-unsigned.hap'); + final String desFile = + globals.fs.path.join(signToolHome, 'app1-unsigned.hap'); + final File unsignedHap = localFileSystem.file(unsignedFile); + unsignedHap.copySync(desFile); + + // first delete cache ,and copy backup + Directory cache = + localFileSystem.directory(globals.fs.path.join(signToolHome, 'result')); + cache.deleteSync(recursive: true); + Directory cacheBackup = localFileSystem + .directory(globals.fs.path.join(signToolHome, 'result.bak')); + copyDirectory(cacheBackup, cache); + + String signtool = + globals.fs.path.join(signToolHome, 'create_appcert_sign_profile.sh'); + final List command = [signtool]; + await invokeCmd( + command: command, + workDirectory: signToolHome, + processManager: globals.processManager, + logger: logger); + + String signtool2 = globals.fs.path.join(signToolHome, 'sign_hap.sh'); + final List command2 = [signtool2]; + await invokeCmd( + command: command2, + workDirectory: signToolHome, + processManager: globals.processManager, + logger: logger); + + String signedFile = + globals.fs.path.join(signToolHome, 'result', 'app1-signed.hap'); + String desSignedFile = globals.fs.path.join(ohosRootPath, + 'entry/build/default/outputs/default', 'entry-default-signed.hap'); + final File signedHap = localFileSystem.file(signedFile); + signedHap.copySync(desSignedFile); + + return; +} + +String getAbsolutePath(FlutterProject flutterProject, String path) { + if (globals.fs.path.isRelative(path)) { + return globals.fs.path.join(flutterProject.directory.path, path); + } + return path; +} + +Future invokeCmd( + {required List command, + required String workDirectory, + required ProcessManager processManager, + Logger? logger}) async { + final String cmd = command.join(' '); + logger?.printTrace(cmd); + final Process server = + await processManager.start(command, workingDirectory: workDirectory); + + server.stderr.transform(utf8.decoder).listen(logger?.printError); + final StdoutHandler stdoutHandler = + StdoutHandler(logger: logger!, fileSystem: globals.localFileSystem); + server.stdout + .transform(utf8.decoder) + .transform(const LineSplitter()) + .listen(stdoutHandler.handler); + final int exitCode = await server.exitCode; + if (exitCode == 0) { + logger.printStatus('$cmd invoke success.'); + } else { + logger.printError('$cmd invoke error.'); + } + return; +} + +///TODO(xuchang) ohpm init first +Future ohpmInstall( + {required ProcessManager processManager, + required String ohpmHome, + required String entryPath, + Logger? logger}) async { + String ohpmPath = globals.fs.path.join(ohpmHome, 'bin', 'ohpm'); + final List command = [ + ohpmPath, + 'install', + ]; + logger?.printTrace(command.join(' ')); + final Process server = + await processManager.start(command, workingDirectory: entryPath); + + server.stderr.transform(utf8.decoder).listen(logger?.printError); + final StdoutHandler stdoutHandler = + StdoutHandler(logger: logger!, fileSystem: globals.localFileSystem); + server.stdout + .transform(utf8.decoder) + .transform(const LineSplitter()) + .listen(stdoutHandler.handler); + final int exitCode = await server.exitCode; + if (exitCode == 0) { + logger.printStatus('ohpm install success.'); + } else { + logger.printError('ohpm install error.'); + } + return; +} + +Future assembleHap( + {required ProcessManager processManager, + required String ohosRootPath, + required String hvigorwPath, + Logger? logger}) async { + /// todo change to hvigrow.bat on windows host + final List command = [ + hvigorwPath, + 'clean', + 'assembleHap', + ]; + + logger?.printTrace(command.join(' ')); + final Process server = + await processManager.start(command, workingDirectory: ohosRootPath); + + server.stderr.transform(utf8.decoder).listen(logger?.printError); + final StdoutHandler stdoutHandler = + StdoutHandler(logger: logger!, fileSystem: globals.localFileSystem); + server.stdout + .transform(utf8.decoder) + .transform(const LineSplitter()) + .listen(stdoutHandler.handler); + final int exitCode = await server.exitCode; + if (exitCode == 0) { + logger.printStatus('assembleHap success.'); + } else { + logger.printError('assembleHap error.'); + } + return; +} diff --git a/packages/flutter_tools/lib/src/ohos/hdc_server.dart b/packages/flutter_tools/lib/src/ohos/hdc_server.dart new file mode 100644 index 0000000000000000000000000000000000000000..525d2f7055530caae411f5eedadc5991e4a4614e --- /dev/null +++ b/packages/flutter_tools/lib/src/ohos/hdc_server.dart @@ -0,0 +1,49 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +import 'dart:io'; + +const String HDC_SERVER_KEY = 'HDC_SERVER'; +const String HDC_SERVER_PORT_KEY = 'HDC_SERVER_PORT'; + +/// +/// return the hdc server config in environment , like 192.168.18.67:8710 +/// +String? getHdcServer() { + final String? hdcServer = Platform.environment[HDC_SERVER_KEY]; + if (hdcServer == null) { + return null; + } + final String? hdcServerPort = Platform.environment[HDC_SERVER_PORT_KEY]; + if (hdcServerPort == null) { + return null; + } + return hdcServer + hdcServerPort; +} + +String? getHdcServerHost() { + final String? hdcServer = Platform.environment[HDC_SERVER_KEY]; + if (hdcServer == null) { + return null; + } + return hdcServer; +} + +String? getHdcServerPort() { + final String? hdcServerPort = Platform.environment[HDC_SERVER_PORT_KEY]; + if (hdcServerPort == null) { + return null; + } + return hdcServerPort; +} diff --git a/packages/flutter_tools/lib/src/ohos/ohos_device.dart b/packages/flutter_tools/lib/src/ohos/ohos_device.dart new file mode 100644 index 0000000000000000000000000000000000000000..de628373667f33db9d28729a5988b3f1b0379f42 --- /dev/null +++ b/packages/flutter_tools/lib/src/ohos/ohos_device.dart @@ -0,0 +1,827 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import 'dart:async'; +import 'dart:math'; + +import 'package:process/process.dart'; + +import '../application_package.dart'; +import '../base/common.dart'; +import '../base/file_system.dart'; +import '../base/io.dart'; +import '../base/logger.dart'; +import '../base/platform.dart'; +import '../base/process.dart'; +import '../build_info.dart'; +import '../convert.dart'; +import '../device.dart'; +import '../device_port_forwarder.dart'; +import '../globals.dart' as globals; +import '../project.dart'; +import '../protocol_discovery.dart'; +import 'application_package.dart'; +import 'build_hap.dart'; +import 'ohos_sdk.dart'; + +class OhosDevice extends Device { + OhosDevice( + super.id, { + this.deviceCodeName, + required Logger logger, + required ProcessManager processManager, + required Platform platform, + required OhosSdk ohosSdk, + required FileSystem fileSystem, + required String? hdcServer, + }) : _logger = logger, + _processManager = processManager, + _ohosSdk = ohosSdk, + _platform = platform, + _fileSystem = fileSystem, + _processUtils = + ProcessUtils(logger: logger, processManager: processManager), + _hdcServer = hdcServer, + super( + category: Category.mobile, + platformType: PlatformType.ohos, + ephemeral: true, + ); + + final Logger _logger; + final ProcessManager _processManager; + final OhosSdk _ohosSdk; + final Platform _platform; + final FileSystem _fileSystem; + final ProcessUtils _processUtils; + final String? _hdcServer; + final String? deviceCodeName; + + @override + void clearLogs() { + // clear hilog history + _processUtils + .runSync(hdcCommandForDevice(['shell', 'hilog', '-r'])); + } + + @override + Future dispose() async { + _logReader?._stop(); + _pastLogReader?._stop(); + } + + @override + Future get emulatorId async => id; + + HdcLogReader? _logReader; + HdcLogReader? _pastLogReader; + + @override + FutureOr getLogReader({ + ApplicationPackage? app, + bool includePastLogs = false, + }) async { + if (includePastLogs) { + return _pastLogReader ??= await HdcLogReader.createLogReader( + this, + _processManager, + includePastLogs: true, + ); + } else { + return _logReader ??= await HdcLogReader.createLogReader( + this, + _processManager, + ); + } + } + + @override + Future installApp(covariant ApplicationPackage app, + {String? userIdentifier}) async { + if (app is! OhosHap) { + throwToolExit('this project or file is not contain(a) Hap file'); + } + final OhosHap hap = app; + final List installAppCommand = + hdcCommandForDevice(['install', hap.applicationPackage.path]); + final File file = globals.fs.file(hap.applicationPackage.path); + if (!file.existsSync()) { + throwToolExit('the hap file not exists!'); + } + try { + _logger.printStatus('installing hap. bundleName: ${app.id} '); + final ProcessResult result = await _processManager.run( + installAppCommand, + stdoutEncoding: latin1, + stderrEncoding: latin1, + ); + final String? errMsg = getErrorMsg(result); + if (errMsg == null) { + _logger.printStatus('install hap finish. bundleName: ${app.id} '); + return true; + } else { + _logger.printError(errMsg); + return false; + } + } on ProcessException catch (error) { + _logger.printError('Error when install hap, $error'); + } + return false; + } + + String? getErrorMsg(ProcessResult result) { + if (result.exitCode != 0) { + return 'install hap error'; + } + final String out = result.stdout as String; + if (out.contains('failed')) { + return out; + } + return null; + } + + @override + Future isAppInstalled(covariant ApplicationPackage app, + {String? userIdentifier}) async { + final String bundleName = app.id; + final List propCommand = + hdcCommandForDevice(['shell', '"bm dump -n $bundleName"']); + _logger.printTrace(propCommand.join(' ')); + try { + final ProcessResult result = await _processManager.run( + propCommand, + stdoutEncoding: latin1, + stderrEncoding: latin1, + ); + if (result.exitCode == 0) { + final String cmdResult = result.stdout as String; + if (cmdResult.contains(bundleName)) { + return true; + } else if (cmdResult.contains('error: failed to get information')) { + return false; + } else { + throw ToolExit('unknown result for bm dump.'); + } + } else { + _logger.printError( + 'Error ${result.exitCode} retrieving device properties for $name:'); + _logger.printError(result.stderr as String); + } + } on ProcessException catch (error) { + _logger + .printError('Error retrieving device properties for $name: $error'); + } + return false; + } + + @override + Future isLatestBuildInstalled(covariant ApplicationPackage app) async { + return false; + } + + @override + late final Future isLocalEmulator = () async { + return false; + }(); + + @override + bool isSupported() { + return true; + } + + @override + bool isSupportedForProject(FlutterProject flutterProject) { + return flutterProject.ohos.existsSync(); + } + + @override + String get name => deviceCodeName ?? 'unknown'; + + @override + late final DevicePortForwarder? portForwarder = () { + final String? hdcPath = _ohosSdk.hdcPath; + if (hdcPath == null) { + return null; + } + return OhosDevicePortForwarder( + processManager: _processManager, + logger: _logger, + deviceId: id, + hdcPath: hdcPath, + ohosDevice: this, + ); + }(); + + @override + Future get sdkNameAndVersion async => + 'Ohos ${await _sdkVersion} (API ${await apiVersion})'; + + Future get _sdkVersion => _getProperty('const.ohos.fullname'); + + Future get apiVersion => _getProperty('const.ohos.apiversion'); + + OhosHap? _package; + + @override + Future startApp(covariant ApplicationPackage? package, + {String? mainPath, + String? route, + required DebuggingOptions debuggingOptions, + Map platformArgs = const {}, + bool prebuiltApplication = false, + bool ipv6 = false, + String? userIdentifier}) async { + /// + /// 1. check build status + /// 2. build or not + /// 3. install or not + /// 4. start app command + /// + + final TargetPlatform devicePlatform = await targetPlatform; + + OhosHap? builtPackage = package as OhosHap?; + OhosArch ohosArch; + switch (devicePlatform) { + case TargetPlatform.ohos_arm64: + ohosArch = OhosArch.arm64_v8a; + break; + case TargetPlatform.ohos_arm: + ohosArch = OhosArch.armeabi_v7a; + break; + case TargetPlatform.ohos_x64: + ohosArch = OhosArch.x86_64; + break; + case TargetPlatform.ohos: + case TargetPlatform.android: + case TargetPlatform.darwin: + case TargetPlatform.fuchsia_arm64: + case TargetPlatform.fuchsia_x64: + case TargetPlatform.ios: + case TargetPlatform.linux_arm64: + case TargetPlatform.linux_x64: + case TargetPlatform.tester: + case TargetPlatform.web_javascript: + case TargetPlatform.windows_x64: + case TargetPlatform.android_arm: + case TargetPlatform.android_arm64: + case TargetPlatform.android_x64: + case TargetPlatform.android_x86: + _logger.printError('Ohos platforms are only supported.'); + return LaunchResult.failed(); + } + + if (!prebuiltApplication) { + _logger.printTrace('Building Hap'); + final FlutterProject project = FlutterProject.current(); + await buildHap( + project, + debuggingOptions.buildInfo, + targetPlatform: devicePlatform, + logger: globals.logger, + target: getNameForTargetPlatform(devicePlatform), + ); + + builtPackage = await ApplicationPackageFactory.instance! + .getPackageForPlatform(devicePlatform, + buildInfo: debuggingOptions.buildInfo) as OhosHap?; + } + // There was a failure parsing the android project information. + if (builtPackage == null) { + throwToolExit('Problem building Ohos application: see above error(s).'); + } + + _logger.printTrace("Stopping app '${builtPackage.name}' on $name."); + await stopApp(builtPackage, userIdentifier: userIdentifier); + + if (await isAppInstalled(builtPackage, userIdentifier: userIdentifier)) { + globals.printStatus('Uninstalling old version...'); + if (!await uninstallApp(builtPackage, userIdentifier: userIdentifier)) { + globals.printWarning('Warning: uninstalling old version failed'); + } + } + + if (!await installApp(builtPackage, userIdentifier: userIdentifier)) { + return LaunchResult.failed(); + } + + final bool traceStartup = platformArgs['trace-startup'] as bool? ?? false; + ProtocolDiscovery? observatoryDiscovery; + + if (debuggingOptions.debuggingEnabled) { + observatoryDiscovery = ProtocolDiscovery.observatory( + // Avoid using getLogReader, which returns a singleton instance, because the + // observatory discovery will dipose at the end. creating a new logger here allows + // logs to be surfaced normally during `flutter drive`. + await HdcLogReader.createLogReader( + this, + _processManager, + ), + portForwarder: portForwarder, + hostPort: debuggingOptions.hostVmServicePort, + devicePort: debuggingOptions.deviceVmServicePort, + ipv6: ipv6, + logger: _logger, + ); + } + + final List cmd = [ + 'shell', + 'aa', + 'start', + '-a', + builtPackage.ohosBuildData.modeInfo.mainElement, + '-b', + builtPackage.ohosBuildData.appInfo.bundleName, + ]; + final String result = (await runHdcCheckedAsync(cmd)).stdout; + // This invocation returns 0 even when it fails. + if (result.contains('Error: ')) { + _logger.printError(result.trim(), wrap: false); + return LaunchResult.failed(); + } + + _package = builtPackage; + if (!debuggingOptions.debuggingEnabled) { + return LaunchResult.succeeded(); + } + + // Wait for the service protocol port here. This will complete once the + // device has printed "Observatory is listening on...". + _logger.printTrace('Waiting for observatory port to be available...'); + try { + Uri? observatoryUri; + if (debuggingOptions.buildInfo.isDebug || + debuggingOptions.buildInfo.isProfile) { + observatoryUri = await observatoryDiscovery?.uri; + if (observatoryUri == null) { + _logger.printError( + 'Error waiting for a debug connection: ' + 'The log reader stopped unexpectedly', + ); + return LaunchResult.failed(); + } + } + return LaunchResult.succeeded(observatoryUri: observatoryUri); + } on Exception catch (error) { + _logger.printError('Error waiting for a debug connection: $error'); + return LaunchResult.failed(); + } finally { + await observatoryDiscovery?.cancel(); + } + } + + @override + Future stopApp(covariant ApplicationPackage? app, + {String? userIdentifier}) async { + if (app == null) { + return false; + } + final List stopAppCommand = + hdcCommandForDevice(['shell', 'aa', 'force-stop', app.id]); + try { + final ProcessResult result = await _processManager.run( + stopAppCommand, + stdoutEncoding: latin1, + stderrEncoding: latin1, + ); + if (result.exitCode == 0) { + return true; + } else { + _logger.printError('stop hap error'); + return false; + } + } on ProcessException catch (error) { + _logger.printError('Error when stop hap, $error'); + } + return false; + } + + @override + late final Future targetPlatform = () async { + // const.product.cpu.abilist = arm64-v8a + final String? abilist = await _getProperty('const.product.cpu.abilist'); + if (abilist == null) { + return TargetPlatform.ohos_arm; + } else if (abilist.contains('arm64-v8a')) { + return TargetPlatform.ohos_arm64; + } else if (abilist.contains('x64')) { + return TargetPlatform.ohos_x64; + } else { + return TargetPlatform.ohos_arm; + } + }(); + + @override + Future uninstallApp(covariant ApplicationPackage app, + {String? userIdentifier}) async { + final List uninstallCommand = + hdcCommandForDevice(['uninstall', app.id]); + try { + final ProcessResult result = await _processManager.run( + uninstallCommand, + stdoutEncoding: latin1, + stderrEncoding: latin1, + ); + if (result.exitCode == 0) { + return true; + } else { + _logger.printError('uninstall hap error'); + return false; + } + } on ProcessException catch (error) { + _logger.printError('Error when uninstall hap, $error'); + } + return false; + } + + Future _getProperty(String name) async { + return (await _properties)[name]; + } + + List hdcCommandForDevice(List args) { + if (_platform.isLinux) { + final List hdcServerCommand = + _hdcServer == null ? [] : ['-s', _hdcServer!]; + return [ + _ohosSdk.hdcPath!, + '-t', + id, + ...hdcServerCommand, + ...args + ]; + } else { + return [_ohosSdk.hdcPath!, '-t', id, ...args]; + } + } + + Future runHdcCheckedAsync( + List params, { + String? workingDirectory, + bool allowReentrantFlutter = false, + }) async { + return _processUtils.run( + hdcCommandForDevice(params), + throwOnError: true, + workingDirectory: workingDirectory, + allowReentrantFlutter: allowReentrantFlutter, + ); + } + + late final Future> _properties = () async { + Map properties = {}; + + final List propCommand = + hdcCommandForDevice(['shell', 'param', 'get']); + _logger.printTrace(propCommand.join(' ')); + + try { + final ProcessResult result = await _processManager.run( + propCommand, + stdoutEncoding: latin1, + stderrEncoding: latin1, + ); + if (result.exitCode == 0) { + properties = parseHdcDeviceProperties(result.stdout as String); + } else { + _logger.printError( + 'Error ${result.exitCode} retrieving device properties for $name:'); + _logger.printError(result.stderr as String); + } + } on ProcessException catch (error) { + _logger + .printError('Error retrieving device properties for $name: $error'); + } + return properties; + }(); + + Map parseHdcDeviceProperties(String str) { + final Map properties = {}; + final List split = str.split('\r\n'); + for (final String line in split) { + // some properties value may contain '=' char,but key not + final int indexOf = line.indexOf('='); + if (indexOf == -1) { + continue; + } + final String key = line.substring(0, indexOf).trim(); + final String value = line.substring(indexOf + 1).trim(); + properties[key] = value; + } + return properties; + } +} + +/// A [DevicePortForwarder] implemented for Ohos devices that uses hdc. +class OhosDevicePortForwarder extends DevicePortForwarder { + OhosDevicePortForwarder({ + required ProcessManager processManager, + required Logger logger, + required String deviceId, + required String hdcPath, + required OhosDevice ohosDevice, + }) : _deviceId = deviceId, + _hdcPath = hdcPath, + _logger = logger, + _processUtils = + ProcessUtils(logger: logger, processManager: processManager), + _ohosDevice = ohosDevice; + + final String _deviceId; + final String _hdcPath; + final Logger _logger; + final ProcessUtils _processUtils; + final OhosDevice _ohosDevice; + + static int? _extractPort(String portString) { + return int.tryParse(portString.trim()); + } + + @override + List get forwardedPorts { + final List ports = []; + + String stdout; + try { + stdout = _processUtils + .runSync( + _ohosDevice.hdcCommandForDevice([ + 'fport', + 'ls', + ]), + throwOnError: true, + ) + .stdout + .trim(); + } on ProcessException catch (error) { + _logger.printError('Failed to list forwarded ports: $error.'); + return ports; + } + + final List lines = LineSplitter.split(stdout).toList(); + for (final String line in lines) { + if (!line.startsWith(_deviceId)) { + continue; + } + final List splitLine = line.split('tcp:'); + + // Sanity check splitLine. + if (splitLine.length != 3) { + continue; + } + + // Attempt to extract ports. + final int? hostPort = _extractPort(splitLine[1]); + final int? devicePort = _extractPort(splitLine[2]); + + // Failed, skip. + if (hostPort == null || devicePort == null) { + continue; + } + + ports.add(ForwardedPort(hostPort, devicePort)); + } + + return ports; + } + + /// return one random port num , between [50000 ~ 65535] + int getOneRandomPort() { + const int min = 50000; + const int max = 65535; + return min + Random().nextInt(max - min); + } + + @override + Future forward(int devicePort, {int? hostPort}) async { + /// if host port == 0 , hdc will tip '[Fail]Forward parament failed' , so give a random port + hostPort ??= getOneRandomPort(); + + final RunResult process = await _processUtils.run( + _ohosDevice.hdcCommandForDevice([ + 'fport', + 'tcp:$hostPort', + 'tcp:$devicePort', + ]), + throwOnError: true, + ); + + if (process.stderr.isNotEmpty) { + process.throwException('hdc returned error:\n${process.stderr}'); + } + + if (process.exitCode != 0) { + if (process.stdout.isNotEmpty) { + process.throwException('hdc returned error:\n${process.stdout}'); + } + process.throwException('hdc failed without a message'); + } + + if (hostPort == 0) { + if (process.stdout.isEmpty) { + process.throwException('hdc did not report forwarded port'); + } + hostPort = int.tryParse(process.stdout); + if (hostPort == null) { + process.throwException('hdc forward error:\n${process.stdout}'); + } + } else { + if (process.stdout.isNotEmpty && !process.stdout.trim().contains('OK')) { + process.throwException('hdc returned error:\n${process.stdout}'); + } + } + + return hostPort!; + } + + @override + Future unforward(ForwardedPort forwardedPort) async { + final RunResult runResult = await _processUtils.run( + _ohosDevice.hdcCommandForDevice([ + 'fport', + 'rm', + 'tcp:${forwardedPort.hostPort}', + 'tcp:${forwardedPort.devicePort}', + ]), + ); + if (runResult.exitCode == 0) { + return; + } + _logger.printError('Failed to unforward port: $runResult'); + } + + @override + Future dispose() async { + for (final ForwardedPort port in forwardedPorts) { + await unforward(port); + } + } +} + +/// A log reader that logs from `hdc hilog`. +class HdcLogReader extends DeviceLogReader { + HdcLogReader._(this._hdcProcess, this.name); + + /// Create a new [HdcLogReader] from an [OhosDevice] instance. + static Future createLogReader( + OhosDevice device, + ProcessManager processManager, { + bool includePastLogs = false, + }) async { + final List args = [ + 'shell', + 'hilog', + ]; + + // If past logs are included then filter for 'flutter' logs only. + if (includePastLogs) { + args.addAll(['-T', 'flutter']); + } else { + // if not includePastLogs, execute clear log. + device.clearLogs(); + } + final Process process = + await processManager.start(device.hdcCommandForDevice(args)); + return HdcLogReader._(process, device.name); + } + + final Process _hdcProcess; + + @override + final String name; + + late final StreamController _linesController = + StreamController.broadcast( + onListen: _start, + onCancel: _stop, + ); + + @override + Stream get logLines => _linesController.stream; + + void _start() { + const Utf8Decoder decoder = Utf8Decoder(reportErrors: false); + _hdcProcess.stdout + .transform(decoder) + .transform(const LineSplitter()) + .listen(_onLine); + _hdcProcess.stderr + .transform(decoder) + .transform(const LineSplitter()) + .listen(_onLine); + unawaited(_hdcProcess.exitCode.whenComplete(() { + if (_linesController.hasListener) { + _linesController.close(); + } + })); + } + + // 'W/ActivityManager(pid): ' + static final RegExp _logFormat = RegExp(r'^[VDIWEF]\/.*?\(\s*(\d+)\):\s'); + + static final List _allowedTags = [ + RegExp(r'^[VDIWEF]\/flutter[^:]*:\s+', caseSensitive: false), + RegExp(r'^[IE]\/DartVM[^:]*:\s+'), + RegExp(r'^[WEF]\/System\.err:\s+'), + RegExp(r'^[F]\/[\S^:]+:\s+'), + ]; + + // 'F/libc(pid): Fatal signal 11' + static final RegExp _fatalLog = + RegExp(r'^F\/libc\s*\(\s*\d+\):\sFatal signal (\d+)'); + + // 'I/DEBUG(pid): ...' + static final RegExp _tombstoneLine = + RegExp(r'^[IF]\/DEBUG\s*\(\s*\d+\):\s(.+)$'); + + // 'I/DEBUG(pid): Tombstone written to: ' + static final RegExp _tombstoneTerminator = + RegExp(r'^Tombstone written to:\s'); + + // we default to true in case none of the log lines match + bool _acceptedLastLine = true; + + // Whether a fatal crash is happening or not. + // During a fatal crash only lines from the crash are accepted, the rest are + // dropped. + bool _fatalCrash = false; + + // The format of the line is controlled by the '-v' parameter passed to + // adb logcat. We are currently passing 'time', which has the format: + // mm-dd hh:mm:ss.milliseconds Priority/Tag( PID): .... + void _onLine(String line) { + // This line might be processed after the subscription is closed but before + // adb stops streaming logs. + if (_linesController.isClosed) { + return; + } + final Match? logMatch = _logFormat.firstMatch(line); + if (logMatch != null) { + bool acceptLine = false; + + if (_fatalCrash) { + // While a fatal crash is going on, only accept lines from the crash + // Otherwise the crash log in the console may get interrupted + final Match? fatalMatch = _tombstoneLine.firstMatch(line); + + if (fatalMatch != null) { + acceptLine = true; + + line = fatalMatch[1]!; + + if (_tombstoneTerminator.hasMatch(line)) { + // Hit crash terminator, stop logging the crash info + _fatalCrash = false; + } + } + } else if (appPid != null && int.parse(logMatch.group(1)!) == appPid) { + acceptLine = true; + + if (_fatalLog.hasMatch(line)) { + // Hit fatal signal, app is now crashing + _fatalCrash = true; + } + } else { + // Filter on approved names and levels. + acceptLine = _allowedTags.any((RegExp re) => re.hasMatch(line)); + } + + if (acceptLine) { + _acceptedLastLine = true; + _linesController.add(line); + return; + } + _acceptedLastLine = false; + } else if (line == '--------- beginning of system' || + line == '--------- beginning of main') { + _acceptedLastLine = false; + } else { + if (_acceptedLastLine) { + _linesController.add(line); + return; + } + } + } + + void _stop() { + _linesController.close(); + _hdcProcess.kill(); + } + + @override + void dispose() { + _stop(); + } +} diff --git a/packages/flutter_tools/lib/src/ohos/ohos_device_discovery.dart b/packages/flutter_tools/lib/src/ohos/ohos_device_discovery.dart new file mode 100644 index 0000000000000000000000000000000000000000..676c70f00480cde57ae07e971f08b5a1b9b29c7c --- /dev/null +++ b/packages/flutter_tools/lib/src/ohos/ohos_device_discovery.dart @@ -0,0 +1,143 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import 'package:process/process.dart'; + +import '../base/common.dart'; +import '../base/file_system.dart'; +import '../base/io.dart'; +import '../base/logger.dart'; +import '../base/platform.dart'; +import '../base/process.dart'; +import '../base/user_messages.dart'; +import '../device.dart'; +import 'hdc_server.dart'; +import 'ohos_device.dart'; +import 'ohos_sdk.dart'; +import 'ohos_workflow.dart'; + +class OhosDevices extends PollingDeviceDiscovery { + OhosDevices({ + required OhosWorkflow ohosWorkflow, + required ProcessManager processManager, + required Logger logger, + OhosSdk? ohosSdk, + required FileSystem fileSystem, + required Platform platform, + required UserMessages userMessages, + }) : _ohosWorkflow = ohosWorkflow, + _processUtils = ProcessUtils( + logger: logger, + processManager: processManager, + ), + _ohosSdk = ohosSdk, + _processManager = processManager, + _logger = logger, + _fileSystem = fileSystem, + _platform = platform, + _userMessages = userMessages, + super('Android devices'); + + final OhosWorkflow _ohosWorkflow; + final ProcessUtils _processUtils; + final ProcessManager _processManager; + final Logger _logger; + final FileSystem _fileSystem; + final Platform _platform; + final UserMessages _userMessages; + final OhosSdk? _ohosSdk; + + bool _doesNotHaveHdc() { + return _ohosSdk == null || + _ohosSdk?.hdcPath == null || + !_processManager.canRun(_ohosSdk!.hdcPath); + } + + @override + Future> pollingGetDevices({Duration? timeout}) async { + if (_doesNotHaveHdc()) { + return []; + } + String text; + + List cmd = [_ohosSdk!.hdcPath!, 'list', 'targets']; + + /// if your host is virtual machine linux, need hdc server on wins to hdc connect ohos device. + if (_platform.isLinux) { + final String? hdcServer = getHdcServer(); + if (hdcServer != null) { + cmd = [_ohosSdk!.hdcPath!, '-s', hdcServer, 'list', 'targets']; + } else { + cmd = [_ohosSdk!.hdcPath!, 'list', 'targets']; + } + } + try { + text = (await _processUtils.run( + cmd, + throwOnError: true, + )) + .stdout + .trim(); + // _logger.printStatus('hdc list result:\n$text'); + } on ProcessException catch (exception) { + throwToolExit( + 'Unable to run "hdc", check your Ohos SDK installation and ' + '$kOhosSdkRoot environment variable: ${exception.executable}', + ); + } + final List devices = []; + _parseHdcDeviceOutput( + text, + devices: devices, + ); + return devices; + } + + @override + bool get supportsPlatform => _ohosWorkflow.appliesToHostPlatform; + + @override + bool get canListAnything => _ohosWorkflow.canListDevices; + + void _parseHdcDeviceOutput( + String text, { + List? devices, + List? diagnostics, + String? hdcServer, + }) { + // return empty if do not discovery any devices + if (text.contains('[Empty]') || text.contains('connect failed')) { + diagnostics?.add(text); + return; + } + + for (final String line in text.trim().split('\n')) { + final String deviceId = line.trim(); + devices?.add(OhosDevice( + deviceId, + deviceCodeName: deviceId, + ohosSdk: _ohosSdk!, + fileSystem: _fileSystem, + logger: _logger, + platform: _platform, + processManager: _processManager, + hdcServer: hdcServer, + )); + } + } + + @override + List get wellKnownIds => const []; +} diff --git a/packages/flutter_tools/lib/src/ohos/ohos_doctor.dart b/packages/flutter_tools/lib/src/ohos/ohos_doctor.dart new file mode 100644 index 0000000000000000000000000000000000000000..ee70794bd4e1760cf2bd0af6f17510b6d2e04b0a --- /dev/null +++ b/packages/flutter_tools/lib/src/ohos/ohos_doctor.dart @@ -0,0 +1,167 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import 'package:process/process.dart'; + +import '../base/context.dart'; +import '../base/file_system.dart'; +import '../base/io.dart'; +import '../base/logger.dart'; +import '../base/os.dart'; +import '../base/platform.dart'; +import '../base/user_messages.dart'; +import '../base/version.dart'; +import '../doctor_validator.dart'; +import 'ohos_sdk.dart'; + +OhosValidator? get ohosValidator => context.get(); + +/// A combination of version description and parsed version number. +class _VersionInfo { + /// Constructs a VersionInfo from a version description string. + /// + /// This should contain a version number. For example: + /// "clang version 9.0.1-6+build1" + _VersionInfo(this.description) { + final String? versionString = RegExp(r'[0-9]+\.[0-9]+(?:\.[0-9]+)?') + .firstMatch(description) + ?.group(0); + number = Version.parse(versionString); + } + + // The full info string reported by the binary. + String description; + + // The parsed Version. + Version? number; +} + +class OhosValidator extends DoctorValidator { + OhosValidator({ + required OhosSdk? ohosSdk, + required FileSystem fileSystem, + required Logger logger, + required Platform platform, + required ProcessManager processManager, + required UserMessages userMessages, + }) : _ohosSdk = ohosSdk, + _fileSystem = fileSystem, + _logger = logger, + _operatingSystemUtils = OperatingSystemUtils( + fileSystem: fileSystem, + logger: logger, + platform: platform, + processManager: processManager, + ), + _platform = platform, + _processManager = processManager, + _userMessages = userMessages, + super('OpenHarmony toolchain - develop for OpenHarmony devices'); + + final OhosSdk? _ohosSdk; + final FileSystem _fileSystem; + final Logger _logger; + final OperatingSystemUtils _operatingSystemUtils; + final Platform _platform; + final ProcessManager _processManager; + final UserMessages _userMessages; + + static const String ohpmBinary = 'ohpm'; + static const String hdcBinary = 'hdc'; + + @override + Future validate() async { + ValidationType validationType = ValidationType.installed; + final List messages = []; + + /// check ohos sdk exist and version correct + if (_ohosSdk != null && _ohosSdk?.hdcPath != null) { + messages.add(ValidationMessage(_userMessages.ohosSdkVersion(_ohosSdk!))); + + /// check hdc + final _VersionInfo? hdcVersion = await _getBinaryVersion(hdcBinary); + if (hdcVersion == null) { + validationType = ValidationType.missing; + messages.add(ValidationMessage.error(_userMessages.hdcMissing())); + } else { + messages.add(ValidationMessage( + _userMessages.hdcVersion(hdcVersion.number.toString()))); + } + } else { + validationType = ValidationType.missing; + if (_ohosSdk != null) { + messages.add(ValidationMessage.error( + _userMessages.ohosSdkMissing((_ohosSdk?.sdkPath) ?? ''))); + } + messages + .add(ValidationMessage.error(_userMessages.ohosSdkInstallation())); + } + + /// check ohpm + final Ohpm? ohpm = Ohpm.local(); + String? ohpmVersionString; + if (ohpm != null && ohpm.getOhpmBinPath() != null) { + final String ohpmPath = ohpm.getOhpmBinPath() ?? ohpmBinary; + final _VersionInfo? ohpmVersion = await _getBinaryVersion(ohpmPath); + if (ohpmVersion != null) { + ohpmVersionString = ohpmVersion.number.toString(); + } + } + if (ohpmVersionString == null) { + validationType = ValidationType.missing; + messages.add(ValidationMessage.error(_userMessages.ohpmMissing())); + } else { + messages + .add(ValidationMessage(_userMessages.ohpmVersion(ohpmVersionString))); + } + + /// check sign tool environment + final SignTool? signTool = SignTool.local(); + if (signTool == null || !signTool.validJar()) { + validationType = ValidationType.missing; + messages.add(ValidationMessage.error(_userMessages.signToolMissing())); + } else { + messages.add(ValidationMessage( + _userMessages.signToolVersion(signTool.signToolHome))); + } + + /// todo: check local engine environment + + return ValidationResult(validationType, messages); + } + + /// Returns the installed version of [binary], or null if it's not installed. + /// + /// Requires tha [binary] take a '--version' flag, and print a version of the + /// form x.y.z somewhere on the first line of output. + Future<_VersionInfo?> _getBinaryVersion(String binary) async { + ProcessResult? result; + try { + result = await _processManager.run([ + binary, + '--version', + ]); + } on ArgumentError { + // ignore error. + } on ProcessException { + // ignore error. + } + if (result == null || result.exitCode != 0) { + return null; + } + final String firstLine = (result.stdout as String).split('\n').first.trim(); + return _VersionInfo(firstLine); + } +} diff --git a/packages/flutter_tools/lib/src/ohos/ohos_sdk.dart b/packages/flutter_tools/lib/src/ohos/ohos_sdk.dart new file mode 100644 index 0000000000000000000000000000000000000000..452be17b84bbbd065c45cd12b20f249290003e2b --- /dev/null +++ b/packages/flutter_tools/lib/src/ohos/ohos_sdk.dart @@ -0,0 +1,177 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import '../base/file_system.dart'; +import '../globals.dart' as globals; + +const String kOhosHome = 'OHOS_HOME'; +const String kOhosSdkRoot = 'OHOS_SDK_HOME'; + +const List supportSdkVersion = ['8', '9', '10']; + +class OhosSdk { + OhosSdk(this._sdkDir) { + init(); + } + + final Directory _sdkDir; + + String get sdkPath => _sdkDir.path; + + String? hdcPath; + + List? apiAvailable; + + static OhosSdk? localOhosSdk() { + String? findOhosHomeDir() { + String? ohosHomeDir; + if (globals.config.containsKey('ohos-sdk')) { + ohosHomeDir = globals.config.getValue('ohos-sdk') as String?; + } else if (globals.platform.environment.containsKey(kOhosHome)) { + ohosHomeDir = globals.platform.environment[kOhosHome]; + } else if (globals.platform.environment.containsKey(kOhosSdkRoot)) { + ohosHomeDir = globals.platform.environment[kOhosSdkRoot]; + } + + if (ohosHomeDir != null) { + if (validSdkDirectory(ohosHomeDir)) { + return ohosHomeDir; + } + if (validSdkDirectory(globals.fs.path.join(ohosHomeDir, 'sdk'))) { + return globals.fs.path.join(ohosHomeDir, 'sdk'); + } + } + return null; + } + + final String? ohosHomeDir = findOhosHomeDir(); + if (ohosHomeDir == null) { + // No dice. + globals.printTrace('Unable to locate an Ohos SDK.'); + return null; + } + + return OhosSdk(globals.fs.directory(ohosHomeDir)); + } + + static bool validSdkDirectory(String dir) { + return hdcExists(dir); + } + + static bool hdcExists(String dir) { + return getHdcPath(dir) != null; + } + + static String? getHdcPath(String sdkPath) { + for (final String folder in supportSdkVersion) { + final File file = globals.fs + .file(globals.fs.path.join(sdkPath, folder, 'toolchains', 'hdc')); + if (file.existsSync()) { + return file.path; + } + } + return null; + } + + List getAvailableApi() { + final List list = []; + for (final String folder in supportSdkVersion) { + final Directory directory = + globals.fs.directory(globals.fs.path.join(sdkPath, folder)); + if (directory.existsSync()) { + list.add(folder); + } + } + return list; + } + + void init() { + hdcPath = getHdcPath(_sdkDir.path); + apiAvailable = getAvailableApi(); + } +} + +/// help user to sign hap file +class SignTool { + SignTool(this.signToolHome); + + static const String SIGN_TOOL_HOME_KEY = 'SIGN_TOOL_HOME'; + + static const String SIGN_TOOL_CONFIG_KEY = 'signTool-home'; + + static SignTool? local() { + String? signToolHome; + if (globals.config.containsKey(SIGN_TOOL_CONFIG_KEY)) { + signToolHome = globals.config.getValue(SIGN_TOOL_CONFIG_KEY) as String?; + } else if (globals.platform.environment.containsKey(SIGN_TOOL_HOME_KEY)) { + signToolHome = globals.platform.environment[SIGN_TOOL_HOME_KEY]; + } + if (signToolHome != null) { + return SignTool(signToolHome); + } else { + return null; + } + } + + final String signToolHome; + + bool validJar() { + // _signToolHome: ~/sdk/developtools_hapsigner/autosign + // ~/sdk/developtools_hapsigner/hapsigntool/hap_sign_tool/build/libs/hap-sign-tool.jar + final File hapSignToolJar = globals.fs + .directory(signToolHome) + .parent + .childDirectory('hapsigntool') + .childDirectory('hap_sign_tool') + .childDirectory('build') + .childDirectory('libs') + .childFile('hap-sign-tool.jar'); + return hapSignToolJar.existsSync(); + } +} + +/// OpenHarmony package manager tool +class Ohpm { + Ohpm(this._ohpmHome); + + static const String OHPM_HOME = 'OHPM_HOME'; + + static const String OHPM_CONFIG_KEY = 'ohpm-home'; + + static Ohpm? local() { + String? ohpmHome; + if (globals.config.containsKey(OHPM_CONFIG_KEY)) { + ohpmHome = globals.config.getValue(OHPM_CONFIG_KEY) as String?; + } else if (globals.platform.environment.containsKey(OHPM_HOME)) { + ohpmHome = globals.platform.environment[OHPM_HOME]; + } + if (ohpmHome != null) { + return Ohpm(ohpmHome); + } else { + return null; + } + } + + final String _ohpmHome; + + String? getOhpmBinPath() { + final bool isWindows = globals.platform.isWindows; + final File ohpm = globals.fs + .directory(_ohpmHome) + .childDirectory('bin') + .childFile(isWindows ? 'ohpm.bat' : 'ohpm'); + return ohpm.existsSync() ? ohpm.path : null; + } +} diff --git a/packages/flutter_tools/lib/src/ohos/ohos_workflow.dart b/packages/flutter_tools/lib/src/ohos/ohos_workflow.dart new file mode 100644 index 0000000000000000000000000000000000000000..146c4d6518c47742134377ca3bdea7236ede9ef9 --- /dev/null +++ b/packages/flutter_tools/lib/src/ohos/ohos_workflow.dart @@ -0,0 +1,48 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import '../base/context.dart'; +import '../doctor_validator.dart'; +import '../features.dart'; +import 'ohos_sdk.dart'; + +OhosWorkflow? get ohosWorkflow => context.get(); + +class OhosWorkflow implements Workflow { + OhosWorkflow({ + required OhosSdk? ohosSdk, + required FeatureFlags featureFlags, + }) : _ohosSdk = ohosSdk, + _featureFlags = featureFlags; + + final OhosSdk? _ohosSdk; + final FeatureFlags _featureFlags; + + @override + bool get appliesToHostPlatform => _featureFlags.isOhosEnabled; + + @override + bool get canListDevices => + appliesToHostPlatform && _ohosSdk != null && _ohosSdk?.hdcPath != null; + + @override + bool get canLaunchDevices => + appliesToHostPlatform && _ohosSdk != null && _ohosSdk?.hdcPath != null; + + @override + bool get canListEmulators => canListDevices + // && _ohosSdk?.emulatorPath != null + ; +} diff --git a/packages/flutter_tools/lib/src/platform_plugins.dart b/packages/flutter_tools/lib/src/platform_plugins.dart index 8fb8c71ac75f4315ab5538c8528d63a51cbb09d3..238768ca8af3a5c2b749b67d53ece8bcbb14caeb 100644 --- a/packages/flutter_tools/lib/src/platform_plugins.dart +++ b/packages/flutter_tools/lib/src/platform_plugins.dart @@ -579,6 +579,20 @@ class WebPlugin extends PluginPlatform { } } + +// todo 补充plugin +class OhosPlugin extends PluginPlatform{ + + static const String kConfigKey = 'ohos'; + + @override + Map toMap() { + // TODO: implement toMap + throw UnimplementedError(); + } + +} + final RegExp _internalCapitalLetterRegex = RegExp(r'(?=(?!^)[A-Z])'); String _filenameForCppClass(String className) { return className.splitMapJoin( diff --git a/packages/flutter_tools/lib/src/project.dart b/packages/flutter_tools/lib/src/project.dart index 4e4e4e02e4a2ed1e287ca33c4461fb2a5f550f1b..3cb2e92b3eba16d13670a9893e45bf2e01a53756 100644 --- a/packages/flutter_tools/lib/src/project.dart +++ b/packages/flutter_tools/lib/src/project.dart @@ -29,6 +29,7 @@ export 'xcode_project.dart'; /// Emum for each officially supported platform. enum SupportedPlatform { + ohos, android, ios, linux, @@ -43,15 +44,14 @@ class FlutterProjectFactory { FlutterProjectFactory({ required Logger logger, required FileSystem fileSystem, - }) : _logger = logger, - _fileSystem = fileSystem; + }) : _logger = logger, + _fileSystem = fileSystem; final Logger _logger; final FileSystem _fileSystem; @visibleForTesting - final Map projects = - {}; + final Map projects = {}; /// Returns a [FlutterProject] view of the given directory or a ToolExit error, /// if `pubspec.yaml` or `example/pubspec.yaml` is invalid. @@ -87,21 +87,24 @@ class FlutterProjectFactory { class FlutterProject { @visibleForTesting FlutterProject(this.directory, this.manifest, this._exampleManifest) - : assert(directory != null), - assert(manifest != null), - assert(_exampleManifest != null); + : assert(directory != null), + assert(manifest != null), + assert(_exampleManifest != null); /// Returns a [FlutterProject] view of the given directory or a ToolExit error, /// if `pubspec.yaml` or `example/pubspec.yaml` is invalid. - static FlutterProject fromDirectory(Directory directory) => globals.projectFactory.fromDirectory(directory); + static FlutterProject fromDirectory(Directory directory) => + globals.projectFactory.fromDirectory(directory); /// Returns a [FlutterProject] view of the current directory or a ToolExit error, /// if `pubspec.yaml` or `example/pubspec.yaml` is invalid. - static FlutterProject current() => globals.projectFactory.fromDirectory(globals.fs.currentDirectory); + static FlutterProject current() => + globals.projectFactory.fromDirectory(globals.fs.currentDirectory); /// Create a [FlutterProject] and bypass the project caching. @visibleForTesting - static FlutterProject fromDirectoryTest(Directory directory, [Logger? logger]) { + static FlutterProject fromDirectoryTest(Directory directory, + [Logger? logger]) { final FileSystem fileSystem = directory.fileSystem; logger ??= BufferLogger.test(); final FlutterManifest manifest = FlutterProject._readManifest( @@ -111,8 +114,8 @@ class FlutterProject { ); final FlutterManifest exampleManifest = FlutterProject._readManifest( FlutterProject._exampleDirectory(directory) - .childFile(bundle.defaultManifestPath) - .path, + .childFile(bundle.defaultManifestPath) + .path, logger: logger, fileSystem: fileSystem, ); @@ -139,7 +142,8 @@ class FlutterProject { // used during create as best-effort, use the // default target bundle identifier. try { - final String? bundleIdentifier = await ios.productBundleIdentifier(null); + final String? bundleIdentifier = + await ios.productBundleIdentifier(null); if (bundleIdentifier != null) { candidates.add(bundleIdentifier); } @@ -154,10 +158,8 @@ class FlutterProject { final String? applicationId = android.applicationId; final String? group = android.group; candidates.addAll([ - if (applicationId != null) - applicationId, - if (group != null) - group, + if (applicationId != null) applicationId, + if (group != null) group, ]); } if (example.android.existsSync()) { @@ -167,12 +169,15 @@ class FlutterProject { } } if (example.ios.existsSync()) { - final String? bundleIdentifier = await example.ios.productBundleIdentifier(null); + final String? bundleIdentifier = + await example.ios.productBundleIdentifier(null); if (bundleIdentifier != null) { candidates.add(bundleIdentifier); } } - return Set.of(candidates.map(_organizationNameFromPackageName).whereType()); + return Set.of(candidates + .map(_organizationNameFromPackageName) + .whereType()); } String? _organizationNameFromPackageName(String packageName) { @@ -203,6 +208,9 @@ class FlutterProject { /// The Fuchsia sub project of this project. late final FuchsiaProject fuchsia = FuchsiaProject._(this); + /// The Ohos sub project of this project. + late final OhosProject ohos = OhosProject._(this); + /// The `pubspec.yaml` file of this project. File get pubspecFile => directory.childFile('pubspec.yaml'); @@ -213,7 +221,8 @@ class FlutterProject { /// /// This is the replacement for .packages which contains language /// version information. - File get packageConfigFile => directory.childDirectory('.dart_tool').childFile('package_config.json'); + File get packageConfigFile => + directory.childDirectory('.dart_tool').childFile('package_config.json'); /// The `.metadata` file of this project. File get metadataFile => directory.childFile('.metadata'); @@ -223,30 +232,30 @@ class FlutterProject { /// The `.flutter-plugins-dependencies` file of this project, /// which contains the dependencies each plugin depends on. - File get flutterPluginsDependenciesFile => directory.childFile('.flutter-plugins-dependencies'); + File get flutterPluginsDependenciesFile => + directory.childFile('.flutter-plugins-dependencies'); /// The `.dart-tool` directory of this project. Directory get dartTool => directory.childDirectory('.dart_tool'); /// The directory containing the generated code for this project. - Directory get generated => directory - .absolute - .childDirectory('.dart_tool') - .childDirectory('build') - .childDirectory('generated') - .childDirectory(manifest.appName); + Directory get generated => directory.absolute + .childDirectory('.dart_tool') + .childDirectory('build') + .childDirectory('generated') + .childDirectory(manifest.appName); /// The generated Dart plugin registrant for non-web platforms. File get dartPluginRegistrant => dartTool - .childDirectory('flutter_build') - .childFile('dart_plugin_registrant.dart'); + .childDirectory('flutter_build') + .childFile('dart_plugin_registrant.dart'); /// The example sub-project of this project. FlutterProject get example => FlutterProject( - _exampleDirectory(directory), - _exampleManifest, - FlutterManifest.empty(logger: globals.logger), - ); + _exampleDirectory(directory), + _exampleManifest, + FlutterManifest.empty(logger: globals.logger), + ); /// True if this project is a Flutter module project. bool get isModule => manifest.isModule; @@ -262,7 +271,9 @@ class FlutterProject { /// Returns a list of platform names that are supported by the project. List getSupportedPlatforms({bool includeRoot = false}) { - final List platforms = includeRoot ? [SupportedPlatform.root] : []; + final List platforms = includeRoot + ? [SupportedPlatform.root] + : []; if (android.existsSync()) { platforms.add(SupportedPlatform.android); } @@ -288,14 +299,16 @@ class FlutterProject { } /// The directory that will contain the example if an example exists. - static Directory _exampleDirectory(Directory directory) => directory.childDirectory('example'); + static Directory _exampleDirectory(Directory directory) => + directory.childDirectory('example'); /// Reads and validates the `pubspec.yaml` file at [path], asynchronously /// returning a [FlutterManifest] representation of the contents. /// /// Completes with an empty [FlutterManifest], if the file does not exist. /// Completes with a ToolExit on validation error. - static FlutterManifest _readManifest(String path, { + static FlutterManifest _readManifest( + String path, { required Logger logger, required FileSystem fileSystem, }) { @@ -310,10 +323,12 @@ class FlutterProject { logger.printStatus('Error detected in pubspec.yaml:', emphasis: true); logger.printError('$e'); } on FormatException catch (e) { - logger.printError('Error detected while parsing pubspec.yaml:', emphasis: true); + logger.printError('Error detected while parsing pubspec.yaml:', + emphasis: true); logger.printError('$e'); } on FileSystemException catch (e) { - logger.printError('Error detected while reading pubspec.yaml:', emphasis: true); + logger.printError('Error detected while reading pubspec.yaml:', + emphasis: true); logger.printError('$e'); } if (manifest == null) { @@ -326,7 +341,9 @@ class FlutterProject { /// registrants for app and module projects only. /// /// Will not create project platform directories if they do not already exist. - Future regeneratePlatformSpecificTooling({DeprecationBehavior deprecationBehavior = DeprecationBehavior.none}) async { + Future regeneratePlatformSpecificTooling( + {DeprecationBehavior deprecationBehavior = + DeprecationBehavior.none}) async { return ensureReadyForPlatformSpecificTooling( androidPlatform: android.existsSync(), iosPlatform: ios.existsSync(), @@ -349,14 +366,17 @@ class FlutterProject { bool macOSPlatform = false, bool windowsPlatform = false, bool webPlatform = false, + bool ohosPlatform = false, DeprecationBehavior deprecationBehavior = DeprecationBehavior.none, }) async { if (!directory.existsSync() || isPlugin) { return; } - await refreshPluginsList(this, iosPlatform: iosPlatform, macOSPlatform: macOSPlatform); + await refreshPluginsList(this, + iosPlatform: iosPlatform, macOSPlatform: macOSPlatform); if (androidPlatform) { - await android.ensureReadyForPlatformSpecificTooling(deprecationBehavior: deprecationBehavior); + await android.ensureReadyForPlatformSpecificTooling( + deprecationBehavior: deprecationBehavior); } if (iosPlatform) { await ios.ensureReadyForPlatformSpecificTooling(); @@ -383,22 +403,21 @@ class FlutterProject { ); } - void checkForDeprecation({DeprecationBehavior deprecationBehavior = DeprecationBehavior.none}) { + void checkForDeprecation( + {DeprecationBehavior deprecationBehavior = DeprecationBehavior.none}) { if (android.existsSync() && pubspecFile.existsSync()) { android.checkForDeprecation(deprecationBehavior: deprecationBehavior); } } /// Returns a json encoded string containing the [appName], [version], and [buildNumber] that is used to generate version.json - String getVersionInfo() { + String getVersionInfo() { final String? buildName = manifest.buildName; final String? buildNumber = manifest.buildNumber; final Map versionFileJson = { 'app_name': manifest.appName, - if (buildName != null) - 'version': buildName, - if (buildNumber != null) - 'build_number': buildNumber, + if (buildName != null) 'version': buildName, + if (buildNumber != null) 'build_number': buildNumber, 'package_name': manifest.appName, }; return jsonEncode(versionFileJson); @@ -407,7 +426,6 @@ class FlutterProject { /// Base class for projects per platform. abstract class FlutterProjectPlatform { - /// Plugin's platform config key, e.g., "macos", "ios". String get pluginConfigKey; @@ -428,9 +446,12 @@ class AndroidProject extends FlutterProjectPlatform { @override String get pluginConfigKey => AndroidPlugin.kConfigKey; - static final RegExp _applicationIdPattern = RegExp('^\\s*applicationId\\s+[\'"](.*)[\'"]\\s*\$'); - static final RegExp _kotlinPluginPattern = RegExp('^\\s*apply plugin\\:\\s+[\'"]kotlin-android[\'"]\\s*\$'); - static final RegExp _groupPattern = RegExp('^\\s*group\\s+[\'"](.*)[\'"]\\s*\$'); + static final RegExp _applicationIdPattern = + RegExp('^\\s*applicationId\\s+[\'"](.*)[\'"]\\s*\$'); + static final RegExp _kotlinPluginPattern = + RegExp('^\\s*apply plugin\\:\\s+[\'"]kotlin-android[\'"]\\s*\$'); + static final RegExp _groupPattern = + RegExp('^\\s*group\\s+[\'"](.*)[\'"]\\s*\$'); /// The Gradle root directory of the Android host app. This is the directory /// containing the `app/` subdirectory and the `settings.gradle` file that @@ -445,10 +466,14 @@ class AndroidProject extends FlutterProjectPlatform { /// The Gradle root directory of the Android wrapping of Flutter and plugins. /// This is the same as [hostAppGradleRoot] except when the project is /// a Flutter module with an editable host app. - Directory get _flutterLibGradleRoot => isModule ? ephemeralDirectory : _editableHostAppDirectory; + Directory get _flutterLibGradleRoot => + isModule ? ephemeralDirectory : _editableHostAppDirectory; + + Directory get ephemeralDirectory => + parent.directory.childDirectory('.android'); - Directory get ephemeralDirectory => parent.directory.childDirectory('.android'); - Directory get _editableHostAppDirectory => parent.directory.childDirectory('android'); + Directory get _editableHostAppDirectory => + parent.directory.childDirectory('android'); /// True if the parent Flutter project is a module. bool get isModule => parent.isModule; @@ -464,13 +489,13 @@ class AndroidProject extends FlutterProjectPlatform { bool _computeSupportedVersion() { final FileSystem fileSystem = hostAppGradleRoot.fileSystem; - final File plugin = hostAppGradleRoot.childFile( - fileSystem.path.join('buildSrc', 'src', 'main', 'groovy', 'FlutterPlugin.groovy')); + final File plugin = hostAppGradleRoot.childFile(fileSystem.path + .join('buildSrc', 'src', 'main', 'groovy', 'FlutterPlugin.groovy')); if (plugin.existsSync()) { return false; } - final File appGradle = hostAppGradleRoot.childFile( - fileSystem.path.join('app', 'build.gradle')); + final File appGradle = hostAppGradleRoot + .childFile(fileSystem.path.join('app', 'build.gradle')); if (!appGradle.existsSync()) { return false; } @@ -485,20 +510,24 @@ class AndroidProject extends FlutterProjectPlatform { /// True, if the app project is using Kotlin. bool get isKotlin { - final File gradleFile = hostAppGradleRoot.childDirectory('app').childFile('build.gradle'); + final File gradleFile = + hostAppGradleRoot.childDirectory('app').childFile('build.gradle'); return firstMatchInFile(gradleFile, _kotlinPluginPattern) != null; } File get appManifestFile { return isUsingGradle - ? globals.fs.file(globals.fs.path.join(hostAppGradleRoot.path, 'app', 'src', 'main', 'AndroidManifest.xml')) + ? globals.fs.file(globals.fs.path.join(hostAppGradleRoot.path, 'app', + 'src', 'main', 'AndroidManifest.xml')) : hostAppGradleRoot.childFile('AndroidManifest.xml'); } - File get gradleAppOutV1File => gradleAppOutV1Directory.childFile('app-debug.apk'); + File get gradleAppOutV1File => + gradleAppOutV1Directory.childFile('app-debug.apk'); Directory get gradleAppOutV1Directory { - return globals.fs.directory(globals.fs.path.join(hostAppGradleRoot.path, 'app', 'build', 'outputs', 'apk')); + return globals.fs.directory(globals.fs.path + .join(hostAppGradleRoot.path, 'app', 'build', 'outputs', 'apk')); } /// Whether the current flutter project has an Android sub-project. @@ -512,7 +541,8 @@ class AndroidProject extends FlutterProjectPlatform { } String? get applicationId { - final File gradleFile = hostAppGradleRoot.childDirectory('app').childFile('build.gradle'); + final File gradleFile = + hostAppGradleRoot.childDirectory('app').childFile('build.gradle'); return firstMatchInFile(gradleFile, _applicationIdPattern)?.group(1); } @@ -526,13 +556,19 @@ class AndroidProject extends FlutterProjectPlatform { return parent.directory.childDirectory('build'); } - Future ensureReadyForPlatformSpecificTooling({DeprecationBehavior deprecationBehavior = DeprecationBehavior.none}) async { + Future ensureReadyForPlatformSpecificTooling( + {DeprecationBehavior deprecationBehavior = + DeprecationBehavior.none}) async { if (isModule && _shouldRegenerateFromTemplate()) { await _regenerateLibrary(); // Add ephemeral host app, if an editable host app does not already exist. if (!_editableHostAppDirectory.existsSync()) { - await _overwriteFromTemplate(globals.fs.path.join('module', 'android', 'host_app_common'), ephemeralDirectory); - await _overwriteFromTemplate(globals.fs.path.join('module', 'android', 'host_app_ephemeral'), ephemeralDirectory); + await _overwriteFromTemplate( + globals.fs.path.join('module', 'android', 'host_app_common'), + ephemeralDirectory); + await _overwriteFromTemplate( + globals.fs.path.join('module', 'android', 'host_app_ephemeral'), + ephemeralDirectory); } } if (!hostAppGradleRoot.existsSync()) { @@ -543,23 +579,30 @@ class AndroidProject extends FlutterProjectPlatform { bool _shouldRegenerateFromTemplate() { return globals.fsUtils.isOlderThanReference( - entity: ephemeralDirectory, - referenceFile: parent.pubspecFile, - ) || globals.cache.isOlderThanToolsStamp(ephemeralDirectory); + entity: ephemeralDirectory, + referenceFile: parent.pubspecFile, + ) || + globals.cache.isOlderThanToolsStamp(ephemeralDirectory); } - File get localPropertiesFile => _flutterLibGradleRoot.childFile('local.properties'); + File get localPropertiesFile => + _flutterLibGradleRoot.childFile('local.properties'); - Directory get pluginRegistrantHost => _flutterLibGradleRoot.childDirectory(isModule ? 'Flutter' : 'app'); + Directory get pluginRegistrantHost => + _flutterLibGradleRoot.childDirectory(isModule ? 'Flutter' : 'app'); Future _regenerateLibrary() async { ErrorHandlingFileSystem.deleteIfExists(ephemeralDirectory, recursive: true); - await _overwriteFromTemplate(globals.fs.path.join( - 'module', - 'android', - 'library_new_embedding', - ), ephemeralDirectory); - await _overwriteFromTemplate(globals.fs.path.join('module', 'android', 'gradle'), ephemeralDirectory); + await _overwriteFromTemplate( + globals.fs.path.join( + 'module', + 'android', + 'library_new_embedding', + ), + ephemeralDirectory); + await _overwriteFromTemplate( + globals.fs.path.join('module', 'android', 'gradle'), + ephemeralDirectory); globals.gradleUtils?.injectGradleWrapperIfNeeded(ephemeralDirectory); } @@ -571,7 +614,8 @@ class AndroidProject extends FlutterProjectPlatform { logger: globals.logger, templateRenderer: globals.templateRenderer, ); - final String androidIdentifier = parent.manifest.androidPackage ?? 'com.example.${parent.manifest.appName}'; + final String androidIdentifier = parent.manifest.androidPackage ?? + 'com.example.${parent.manifest.appName}'; template.render( target, { @@ -592,7 +636,8 @@ class AndroidProject extends FlutterProjectPlatform { ); } - void checkForDeprecation({DeprecationBehavior deprecationBehavior = DeprecationBehavior.none}) { + void checkForDeprecation( + {DeprecationBehavior deprecationBehavior = DeprecationBehavior.none}) { if (deprecationBehavior == DeprecationBehavior.none) { return; } @@ -600,8 +645,7 @@ class AndroidProject extends FlutterProjectPlatform { if (result.version != AndroidEmbeddingVersion.v1) { return; } - globals.printStatus( -''' + globals.printStatus(''' ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Warning ────────────────────────────────────────────────────────────────────────────── @@ -618,9 +662,14 @@ The detected reason was: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ '''); if (deprecationBehavior == DeprecationBehavior.ignore) { - BuildEvent('deprecated-v1-android-embedding-ignored', type: 'gradle', flutterUsage: globals.flutterUsage).send(); - } else { // DeprecationBehavior.exit - BuildEvent('deprecated-v1-android-embedding-failed', type: 'gradle', flutterUsage: globals.flutterUsage).send(); + BuildEvent('deprecated-v1-android-embedding-ignored', + type: 'gradle', flutterUsage: globals.flutterUsage) + .send(); + } else { + // DeprecationBehavior.exit + BuildEvent('deprecated-v1-android-embedding-failed', + type: 'gradle', flutterUsage: globals.flutterUsage) + .send(); throwToolExit( 'Build failed due to use of deprecated Android v1 embedding.', exitCode: 1, @@ -636,47 +685,56 @@ The detected reason was: if (isModule) { // A module type's Android project is used in add-to-app scenarios and // only supports the V2 embedding. - return AndroidEmbeddingVersionResult(AndroidEmbeddingVersion.v2, 'Is add-to-app module'); + return AndroidEmbeddingVersionResult( + AndroidEmbeddingVersion.v2, 'Is add-to-app module'); } if (isPlugin) { // Plugins do not use an appManifest, so we stop here. // // TODO(garyq): This method does not currently check for code references to // the v1 embedding, we should check for this once removal is further along. - return AndroidEmbeddingVersionResult(AndroidEmbeddingVersion.v2, 'Is plugin'); + return AndroidEmbeddingVersionResult( + AndroidEmbeddingVersion.v2, 'Is plugin'); } if (appManifestFile == null || !appManifestFile.existsSync()) { - return AndroidEmbeddingVersionResult(AndroidEmbeddingVersion.v1, 'No `${appManifestFile.absolute.path}` file'); + return AndroidEmbeddingVersionResult(AndroidEmbeddingVersion.v1, + 'No `${appManifestFile.absolute.path}` file'); } XmlDocument document; try { document = XmlDocument.parse(appManifestFile.readAsStringSync()); } on XmlException { throwToolExit('Error parsing $appManifestFile ' - 'Please ensure that the android manifest is a valid XML document and try again.'); + 'Please ensure that the android manifest is a valid XML document and try again.'); } on FileSystemException { throwToolExit('Error reading $appManifestFile even though it exists. ' - 'Please ensure that you have read permission to this file and try again.'); + 'Please ensure that you have read permission to this file and try again.'); } - for (final XmlElement application in document.findAllElements('application')) { + for (final XmlElement application + in document.findAllElements('application')) { final String? applicationName = application.getAttribute('android:name'); if (applicationName == 'io.flutter.app.FlutterApplication') { - return AndroidEmbeddingVersionResult(AndroidEmbeddingVersion.v1, '${appManifestFile.absolute.path} uses `android:name="io.flutter.app.FlutterApplication"`'); + return AndroidEmbeddingVersionResult(AndroidEmbeddingVersion.v1, + '${appManifestFile.absolute.path} uses `android:name="io.flutter.app.FlutterApplication"`'); } } for (final XmlElement metaData in document.findAllElements('meta-data')) { final String? name = metaData.getAttribute('android:name'); if (name == 'flutterEmbedding') { - final String? embeddingVersionString = metaData.getAttribute('android:value'); + final String? embeddingVersionString = + metaData.getAttribute('android:value'); if (embeddingVersionString == '1') { - return AndroidEmbeddingVersionResult(AndroidEmbeddingVersion.v1, '${appManifestFile.absolute.path} `` in ${appManifestFile.absolute.path}'); + return AndroidEmbeddingVersionResult(AndroidEmbeddingVersion.v1, + 'No `` in ${appManifestFile.absolute.path}'); } } @@ -684,6 +742,7 @@ The detected reason was: enum AndroidEmbeddingVersion { /// V1 APIs based on io.flutter.app.FlutterActivity. v1, + /// V2 APIs based on io.flutter.embedding.android.FlutterActivity. v2, } @@ -723,8 +782,8 @@ class WebProject extends FlutterProjectPlatform { /// Whether this flutter project has a web sub-project. @override bool existsSync() { - return parent.directory.childDirectory('web').existsSync() - && indexFile.existsSync(); + return parent.directory.childDirectory('web').existsSync() && + indexFile.existsSync(); } /// The 'lib' directory for the application. @@ -734,14 +793,12 @@ class WebProject extends FlutterProjectPlatform { Directory get directory => parent.directory.childDirectory('web'); /// The html file used to host the flutter web application. - File get indexFile => parent.directory - .childDirectory('web') - .childFile('index.html'); + File get indexFile => + parent.directory.childDirectory('web').childFile('index.html'); /// The .dart_tool/dartpad directory - Directory get dartpadToolDirectory => parent.directory - .childDirectory('.dart_tool') - .childDirectory('dartpad'); + Directory get dartpadToolDirectory => + parent.directory.childDirectory('.dart_tool').childDirectory('dartpad'); Future ensureReadyForPlatformSpecificTooling() async { /// Create .dart_tool/dartpad/web_plugin_registrant.dart. @@ -761,12 +818,55 @@ class FuchsiaProject { final FlutterProject project; Directory? _editableHostAppDirectory; + Directory get editableHostAppDirectory => _editableHostAppDirectory ??= project.directory.childDirectory('fuchsia'); bool existsSync() => editableHostAppDirectory.existsSync(); Directory? _meta; + Directory get meta => _meta ??= editableHostAppDirectory.childDirectory('meta'); } + +/// The Ohos sub project. +class OhosProject extends FlutterProjectPlatform { + OhosProject._(this.parent); + + final FlutterProject parent; + + /// Whether this flutter project has a web sub-project. + @override + bool existsSync() { + return ohosRootPath().existsSync(); + } + + @override + String get pluginConfigKey => OhosPlugin.kConfigKey; + + Directory ohosRootPath() => parent.directory.childDirectory('ohos'); + + File getAppJsonFile() => + ohosRootPath().childDirectory('AppScope').childFile('app.json5'); + + // entry/src/main/module.json5 + File getModuleJsonFile() => ohosRootPath() + .childDirectory('entry') + .childDirectory('src') + .childDirectory('main') + .childFile('module.json5'); + + // entry/build/default/outputs/default/entry-default-signed.hap + File getSignedHapFile() => ohosRootPath() + .childDirectory('entry') + .childDirectory('build') + .childDirectory('default') + .childDirectory('outputs') + .childDirectory('default') + .childFile('entry-default-signed.hap'); + + bool hasSignedHapBuild() { + return getSignedHapFile().existsSync(); + } +} diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart index 7f4e8388e50726694b58147174de8700e0e3caa5..5bd5fe1f9f323765296f48ffb671ffb10968af83 100644 --- a/packages/flutter_tools/lib/src/resident_runner.dart +++ b/packages/flutter_tools/lib/src/resident_runner.dart @@ -35,6 +35,7 @@ import 'devfs.dart'; import 'device.dart'; import 'features.dart'; import 'globals.dart' as globals; +import 'ohos/hdc_server.dart'; import 'project.dart'; import 'resident_devtools_handler.dart'; import 'run_cold.dart'; @@ -247,6 +248,13 @@ class FlutterDevice { bool isWaitingForVm = false; subscription = observatoryUris!.listen((Uri? observatoryUri) async { + // when on hdc server mode,the host is not local,change to hdc server + final String? hdcServerHost = getHdcServerHost(); + if(hdcServerHost!=null){ + const String localHost = '0.0.0.0'; + observatoryUri = Uri.parse(observatoryUri?.toString()?.replaceAll(localHost, hdcServerHost)??localHost); + } + // FYI, this message is used as a sentinel in tests. globals.printTrace('Connecting to service protocol: $observatoryUri'); isWaitingForVm = true; diff --git a/packages/flutter_tools/lib/src/runner/local_engine.dart b/packages/flutter_tools/lib/src/runner/local_engine.dart index e89a15a9bfa67759b6278aa4a8cfe71a5593575e..f99e40823add3f7ac766986a7b2e1b74217e31d6 100644 --- a/packages/flutter_tools/lib/src/runner/local_engine.dart +++ b/packages/flutter_tools/lib/src/runner/local_engine.dart @@ -152,7 +152,8 @@ class LocalEngineLocator { String _getHostEngineBasename(String localEngineBasename) { if (localEngineBasename.startsWith('web_') || localEngineBasename.startsWith('wasm_') || - localEngineBasename.startsWith('host_')) { + localEngineBasename.startsWith('host_') || + localEngineBasename.startsWith('ohos_')) { // Don't modify the web or host local engine's basename. return localEngineBasename; } diff --git a/packages/flutter_tools/lib/src/template.dart b/packages/flutter_tools/lib/src/template.dart index 60fc5e7828122044a97d5ccb3990a5c3985cdc51..fbf2a3d0964f3d3252cb038f9a235b65e86f287a 100644 --- a/packages/flutter_tools/lib/src/template.dart +++ b/packages/flutter_tools/lib/src/template.dart @@ -215,6 +215,12 @@ class Template { return null; } + //Only build a ohos project if explicitly asked. + final bool ohos = (context['ohos'] as bool?) ?? false; + if (relativeDestinationPath.startsWith('ohos.tmpl') && !ohos) { + return null; + } + final String? projectName = context['projectName'] as String?; final String? androidIdentifier = context['androidIdentifier'] as String?; final String? pluginClass = context['pluginClass'] as String?; diff --git a/packages/flutter_tools/lib/src/vmservice.dart b/packages/flutter_tools/lib/src/vmservice.dart index 423e4a58aafa8681b73385d96ae6fa7d8f06ff22..b1035b704b0c36d4a5713ac278ab8266afad3a1a 100644 --- a/packages/flutter_tools/lib/src/vmservice.dart +++ b/packages/flutter_tools/lib/src/vmservice.dart @@ -14,6 +14,7 @@ import 'base/logger.dart'; import 'base/utils.dart'; import 'convert.dart'; import 'device.dart'; +import 'ohos/hdc_server.dart'; import 'version.dart'; const String kGetSkSLsMethod = '_flutter.getSkSLs'; @@ -148,6 +149,12 @@ Future _defaultOpenChannel(String url, { while (socket == null) { attempts += 1; try { + final String? hdcServerHost = getHdcServerHost(); + // when on hdc server mode,the host is not local,change to hdc server + if(hdcServerHost!=null){ + url = url.replaceAll('0.0.0.0', hdcServerHost); + logger.printStatus('io.WebSocket.connect change url to $url'); + } socket = await constructor(url, compression: compression, logger: logger); } on io.WebSocketException catch (e) { await handleError(e); diff --git a/packages/flutter_tools/pubspec.yaml b/packages/flutter_tools/pubspec.yaml index bed29c71b85a3295538b8c6c1dce02bad5ba6955..5a8e8912a80e19cb6fe9d85e8157f83388444eb9 100644 --- a/packages/flutter_tools/pubspec.yaml +++ b/packages/flutter_tools/pubspec.yaml @@ -48,6 +48,8 @@ dependencies: http_multi_server: 3.2.1 convert: 3.1.1 async: 2.10.0 + # this dependence use to parse json5 config file + json5: ^0.8.0 # We depend on very specific internal implementation details of the # 'test' package, which change between versions, so when upgrading diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/.gitignore b/packages/flutter_tools/templates/app_shared/ohos.tmpl/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..fbabf771011fe78f9919db0b1195ab6cadffc2b0 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/.gitignore @@ -0,0 +1,11 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test \ No newline at end of file diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/AppScope/app.json5.tmpl b/packages/flutter_tools/templates/app_shared/ohos.tmpl/AppScope/app.json5.tmpl new file mode 100644 index 0000000000000000000000000000000000000000..bb6326c08830be0e38e479c30358aef71577ed69 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/AppScope/app.json5.tmpl @@ -0,0 +1,10 @@ +{ + "app": { + "bundleName": "{{ohosIdentifier}}", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/AppScope/resources/base/element/string.json.tmpl b/packages/flutter_tools/templates/app_shared/ohos.tmpl/AppScope/resources/base/element/string.json.tmpl new file mode 100644 index 0000000000000000000000000000000000000000..36b4fe45600e9f7d95b18c78ed20ef49ea3c5ebd --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/AppScope/resources/base/element/string.json.tmpl @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "{{projectName}}" + } + ] +} diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/AppScope/resources/base/media/app_icon.png b/packages/flutter_tools/templates/app_shared/ohos.tmpl/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/packages/flutter_tools/templates/app_shared/ohos.tmpl/AppScope/resources/base/media/app_icon.png differ diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/build-profile.json5.tmpl b/packages/flutter_tools/templates/app_shared/ohos.tmpl/build-profile.json5.tmpl new file mode 100644 index 0000000000000000000000000000000000000000..e752f800ef1c0e2a7a5178f8d4e854b4e449f044 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/build-profile.json5.tmpl @@ -0,0 +1,42 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +{ + "app": { + "signingConfigs": [], + "compileSdkVersion": 9, + "compatibleSdkVersion": 9, + "products": [ + { + "name": "default", + "signingConfig": "default", + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/dta/icudtl.dat b/packages/flutter_tools/templates/app_shared/ohos.tmpl/dta/icudtl.dat new file mode 100644 index 0000000000000000000000000000000000000000..d1f10917ab52e3ebd251abd7f5377d7196b80d67 Binary files /dev/null and b/packages/flutter_tools/templates/app_shared/ohos.tmpl/dta/icudtl.dat differ diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/.gitignore b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..2795a1c5b1fe53659dd1b71d90ba0592eaf7e043 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/.gitignore @@ -0,0 +1,7 @@ + +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/build-profile.json5.tmpl b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/build-profile.json5.tmpl new file mode 100644 index 0000000000000000000000000000000000000000..f02a52e08c8fa1c3a33b9faa4592e9f695cd1c54 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/build-profile.json5.tmpl @@ -0,0 +1,29 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +{ + "apiType": 'stageMode', + "buildOption": { + }, + "targets": [ + { + "name": "default", + "runtimeOS": "OpenHarmony" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/hvigorfile.ts.tmpl b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/hvigorfile.ts.tmpl new file mode 100644 index 0000000000000000000000000000000000000000..894fc15c6b793f085e6c8506e43d719af658e8ff --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/hvigorfile.ts.tmpl @@ -0,0 +1,17 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +export { hapTasks } from '@ohos/hvigor-ohos-plugin'; diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/libs/arm64-v8a/libc++_shared.so b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/libs/arm64-v8a/libc++_shared.so new file mode 100644 index 0000000000000000000000000000000000000000..831c9353702073d45889352a4dafb93103d67d20 Binary files /dev/null and b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/libs/arm64-v8a/libc++_shared.so differ diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/oh-package.json5.tmpl b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/oh-package.json5.tmpl new file mode 100644 index 0000000000000000000000000000000000000000..f51430d9c49c0dee125cf93f39f6f41729f817ae --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/oh-package.json5.tmpl @@ -0,0 +1,27 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": { + "@ohos/flutter_embedding": "file:../har/flutter_embedding.har" + } +} + diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/ets/entryability/EntryAbility.ts.tmpl b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/ets/entryability/EntryAbility.ts.tmpl new file mode 100644 index 0000000000000000000000000000000000000000..2b895a95ba10e906765de1ee72db415b4c7f5380 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/ets/entryability/EntryAbility.ts.tmpl @@ -0,0 +1,22 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import { FlutterAbility } from '@ohos/flutter_embedding' + +export default class EntryAbility extends FlutterAbility { + onFlutterEngineReady(): void { + super.onFlutterEngineReady() + } +} diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/ets/pages/Index.ets.tmpl b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/ets/pages/Index.ets.tmpl new file mode 100644 index 0000000000000000000000000000000000000000..e93b52e51b6dc7e85719f7053cf0f70be7b2b8e3 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/ets/pages/Index.ets.tmpl @@ -0,0 +1 @@ +/* * Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { FlutterPage } from '@ohos/flutter_embedding' @Entry @Component struct Index { build() { Column() { FlutterPage() } } } \ No newline at end of file diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/module.json5 b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..7049a3d05756a93d00d1e348d850be84bb1dbd18 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/module.json5 @@ -0,0 +1,53 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "phone" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ts", + "description": "$string:EntryAbility_desc", + "icon": "$media:icon", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "requestPermissions": [ + {"name" : "ohos.permission.INTERNET"}, + ] + } +} \ No newline at end of file diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/resources/base/element/color.json b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/resources/base/element/string.json b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..f94595515a99e0c828807e243494f57f09251930 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/resources/base/media/icon.png b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/resources/base/media/icon.png differ diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/resources/base/profile/main_pages.json b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/resources/en_US/element/string.json b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..f94595515a99e0c828807e243494f57f09251930 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/resources/en_US/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/resources/zh_CN/element/string.json b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..597ecf95e61d7e30367c22fe2f8638008361b044 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "模块描述" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/ets/test/Ability.test.ets b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..25d4c71ff3cd584f5d64f6f8c0ac864928c234c4 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,50 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import hilog from '@ohos.hilog'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' + +export default function abilityTest() { + describe('ActsAbilityTest', function () { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(function () { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(function () { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(function () { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(function () { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain',0, function () { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc' + let b = 'b' + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b) + expect(a).assertEqual(a) + }) + }) +} \ No newline at end of file diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/ets/test/List.test.ets b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f4140030e65d20df6af30a6bf51e464dea8f8aa6 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,20 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import abilityTest from './Ability.test' + +export default function testsuite() { + abilityTest() +} \ No newline at end of file diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/ets/testability/TestAbility.ets b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/ets/testability/TestAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..4ca645e6013cfce8e7dbb728313cb8840c4da660 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/ets/testability/TestAbility.ets @@ -0,0 +1,63 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import UIAbility from '@ohos.app.ability.UIAbility'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import hilog from '@ohos.hilog'; +import { Hypium } from '@ohos/hypium'; +import testsuite from '../test/List.test'; +import window from '@ohos.window'; + +export default class TestAbility extends UIAbility { + onCreate(want, launchParam) { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate'); + hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? ''); + hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:'+ JSON.stringify(launchParam) ?? ''); + var abilityDelegator: any + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var abilityDelegatorArguments: any + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!'); + Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) + } + + onDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage) { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate'); + windowStage.loadContent('testability/pages/Index', (err, data) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', + JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy'); + } + + onForeground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground'); + } + + onBackground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground'); + } +} \ No newline at end of file diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/ets/testability/pages/Index.ets b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/ets/testability/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..cef0447cd2f137ef82d223ead2e156808878ab90 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/ets/testability/pages/Index.ets @@ -0,0 +1,49 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import hilog from '@ohos.hilog'; + +@Entry +@Component +struct Index { + aboutToAppear() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility index aboutToAppear'); + } + @State message: string = 'Hello World' + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('35%') + .height('5%') + .onClick(()=>{ + }) + } + .width('100%') + } + .height('100%') + } + } \ No newline at end of file diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts new file mode 100644 index 0000000000000000000000000000000000000000..1def08f2e9dcbfa3454a07b7a3b82b173bb90d02 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts @@ -0,0 +1,64 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import hilog from '@ohos.hilog'; +import TestRunner from '@ohos.application.testRunner'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; + +var abilityDelegator = undefined +var abilityDelegatorArguments = undefined + +async function onAbilityCreateCallback() { + hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback'); +} + +async function addAbilityMonitorCallback(err: any) { + hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? ''); +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare '); + } + + async onRun() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run'); + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var testAbilityName = abilityDelegatorArguments.bundleName + '.TestAbility' + let lMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + var cmd = 'aa start -d 0 -a TestAbility' + ' -b ' + abilityDelegatorArguments.bundleName + var debug = abilityDelegatorArguments.parameters['-D'] + if (debug == 'true') + { + cmd += ' -D' + } + hilog.info(0x0000, 'testTag', 'cmd : %{public}s', cmd); + abilityDelegator.executeShellCommand(cmd, + (err: any, d: any) => { + hilog.info(0x0000, 'testTag', 'executeShellCommand : err : %{public}s', JSON.stringify(err) ?? ''); + hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.stdResult ?? ''); + hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.exitCode ?? ''); + }) + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end'); + } +} \ No newline at end of file diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/module.json5.tmpl b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/module.json5.tmpl new file mode 100644 index 0000000000000000000000000000000000000000..fab77ce2e0c61e3ad010bab5b27ccbd15f9a8c96 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/module.json5.tmpl @@ -0,0 +1,51 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +{ + "module": { + "name": "entry_test", + "type": "feature", + "description": "$string:module_test_desc", + "mainElement": "TestAbility", + "deviceTypes": [ + "phone" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:test_pages", + "abilities": [ + { + "name": "TestAbility", + "srcEntry": "./ets/testability/TestAbility.ets", + "description": "$string:TestAbility_desc", + "icon": "$media:icon", + "label": "$string:TestAbility_label", + "exported": true, + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:start_window_background", + "skills": [ + { + "actions": [ + "action.system.home" + ], + "entities": [ + "entity.system.home" + ] + } + ] + } + ] + } +} diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/resources/base/element/color.json b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/resources/base/element/string.json b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..65d8fa5a7cf54aa3943dcd0214f58d1771bc1f6c --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_test_desc", + "value": "test ability description" + }, + { + "name": "TestAbility_desc", + "value": "the test ability" + }, + { + "name": "TestAbility_label", + "value": "test label" + } + ] +} \ No newline at end of file diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/resources/base/media/icon.png b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/resources/base/media/icon.png differ diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/resources/base/profile/test_pages.json.tmpl b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/resources/base/profile/test_pages.json.tmpl new file mode 100644 index 0000000000000000000000000000000000000000..b7e7343cacb32ce982a45e76daad86e435e054fe --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/entry/src/ohosTest/resources/base/profile/test_pages.json.tmpl @@ -0,0 +1,5 @@ +{ + "src": [ + "testability/pages/Index" + ] +} diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/har/flutter_embedding.har.debug b/packages/flutter_tools/templates/app_shared/ohos.tmpl/har/flutter_embedding.har.debug new file mode 100644 index 0000000000000000000000000000000000000000..f0df4ca0064821178bf4254b16e8d23d873827da Binary files /dev/null and b/packages/flutter_tools/templates/app_shared/ohos.tmpl/har/flutter_embedding.har.debug differ diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/har/flutter_embedding.har.release b/packages/flutter_tools/templates/app_shared/ohos.tmpl/har/flutter_embedding.har.release new file mode 100644 index 0000000000000000000000000000000000000000..ba52754a80826e5614438b3faf931ed2f487eaab Binary files /dev/null and b/packages/flutter_tools/templates/app_shared/ohos.tmpl/har/flutter_embedding.har.release differ diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/hvigor/hvigor-config.json5.tmpl b/packages/flutter_tools/templates/app_shared/ohos.tmpl/hvigor/hvigor-config.json5.tmpl new file mode 100644 index 0000000000000000000000000000000000000000..990085f6621b0d3e876a162e42eb2bc1bf441434 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/hvigor/hvigor-config.json5.tmpl @@ -0,0 +1,21 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +{ + "hvigorVersion": "2.1.1", + "dependencies": { + "@ohos/hvigor-ohos-plugin": "2.1.1" + } +} diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/hvigor/hvigor-wrapper.js.tmpl b/packages/flutter_tools/templates/app_shared/ohos.tmpl/hvigor/hvigor-wrapper.js.tmpl new file mode 100644 index 0000000000000000000000000000000000000000..994f22987bd0739b9faa07c966b066c2d9218602 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/hvigor/hvigor-wrapper.js.tmpl @@ -0,0 +1,2 @@ +"use strict";var e=require("fs"),t=require("path"),n=require("os"),r=require("crypto"),u=require("child_process"),o=require("constants"),i=require("stream"),s=require("util"),c=require("assert"),a=require("tty"),l=require("zlib"),f=require("net");function d(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var D=d(e),p=d(t),E=d(n),m=d(r),h=d(u),y=d(o),C=d(i),F=d(s),g=d(c),A=d(a),v=d(l),S=d(f),w="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},O={},b={},_={},B=w&&w.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(_,"__esModule",{value:!0}),_.isMac=_.isLinux=_.isWindows=void 0;const P=B(E.default),k="Windows_NT",x="Linux",N="Darwin";_.isWindows=function(){return P.default.type()===k},_.isLinux=function(){return P.default.type()===x},_.isMac=function(){return P.default.type()===N};var I={},T=w&&w.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n);var u=Object.getOwnPropertyDescriptor(t,n);u&&!("get"in u?!t.__esModule:u.writable||u.configurable)||(u={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,r,u)}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),R=w&&w.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),M=w&&w.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.prototype.hasOwnProperty.call(e,n)&&T(t,e,n);return R(t,e),t};Object.defineProperty(I,"__esModule",{value:!0}),I.hash=void 0;const L=M(m.default);I.hash=function(e,t="md5"){return L.createHash(t).update(e,"utf-8").digest("hex")},function(e){var t=w&&w.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n);var u=Object.getOwnPropertyDescriptor(t,n);u&&!("get"in u?!t.__esModule:u.writable||u.configurable)||(u={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,r,u)}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),n=w&&w.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),r=w&&w.__importStar||function(e){if(e&&e.__esModule)return e;var r={};if(null!=e)for(var u in e)"default"!==u&&Object.prototype.hasOwnProperty.call(e,u)&&t(r,e,u);return n(r,e),r};Object.defineProperty(e,"__esModule",{value:!0}),e.HVIGOR_BOOT_JS_FILE_PATH=e.HVIGOR_PROJECT_DEPENDENCY_PACKAGE_JSON_PATH=e.HVIGOR_PROJECT_DEPENDENCIES_HOME=e.HVIGOR_PROJECT_WRAPPER_HOME=e.HVIGOR_PROJECT_NAME=e.HVIGOR_PROJECT_ROOT_DIR=e.HVIGOR_PROJECT_CACHES_HOME=e.HVIGOR_PNPM_STORE_PATH=e.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH=e.HVIGOR_WRAPPER_TOOLS_HOME=e.HVIGOR_USER_HOME=e.DEFAULT_PACKAGE_JSON=e.DEFAULT_HVIGOR_CONFIG_JSON_FILE_NAME=e.PNPM=e.HVIGOR=e.NPM_TOOL=e.PNPM_TOOL=e.HVIGOR_ENGINE_PACKAGE_NAME=void 0;const u=r(p.default),o=r(E.default),i=_,s=I;e.HVIGOR_ENGINE_PACKAGE_NAME="@ohos/hvigor",e.PNPM_TOOL=(0,i.isWindows)()?"pnpm.cmd":"pnpm",e.NPM_TOOL=(0,i.isWindows)()?"npm.cmd":"npm",e.HVIGOR="hvigor",e.PNPM="pnpm",e.DEFAULT_HVIGOR_CONFIG_JSON_FILE_NAME="hvigor-config.json5",e.DEFAULT_PACKAGE_JSON="package.json",e.HVIGOR_USER_HOME=u.resolve(o.homedir(),".hvigor"),e.HVIGOR_WRAPPER_TOOLS_HOME=u.resolve(e.HVIGOR_USER_HOME,"wrapper","tools"),e.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH=u.resolve(e.HVIGOR_WRAPPER_TOOLS_HOME,"node_modules",".bin",e.PNPM_TOOL),e.HVIGOR_PNPM_STORE_PATH=u.resolve(e.HVIGOR_USER_HOME,"caches"),e.HVIGOR_PROJECT_CACHES_HOME=u.resolve(e.HVIGOR_USER_HOME,"project_caches"),e.HVIGOR_PROJECT_ROOT_DIR=process.cwd(),e.HVIGOR_PROJECT_NAME=u.basename((0,s.hash)(e.HVIGOR_PROJECT_ROOT_DIR)),e.HVIGOR_PROJECT_WRAPPER_HOME=u.resolve(e.HVIGOR_PROJECT_ROOT_DIR,e.HVIGOR),e.HVIGOR_PROJECT_DEPENDENCIES_HOME=u.resolve(e.HVIGOR_PROJECT_CACHES_HOME,e.HVIGOR_PROJECT_NAME,"workspace"),e.HVIGOR_PROJECT_DEPENDENCY_PACKAGE_JSON_PATH=u.resolve(e.HVIGOR_PROJECT_DEPENDENCIES_HOME,e.DEFAULT_PACKAGE_JSON),e.HVIGOR_BOOT_JS_FILE_PATH=u.resolve(e.HVIGOR_PROJECT_DEPENDENCIES_HOME,"node_modules","@ohos","hvigor","bin","hvigor.js")}(b);var j={},$={};Object.defineProperty($,"__esModule",{value:!0}),$.logInfoPrintConsole=$.logErrorAndExit=void 0,$.logErrorAndExit=function(e){e instanceof Error?console.error(e.message):console.error(e),process.exit(-1)},$.logInfoPrintConsole=function(e){console.log(e)};var H=w&&w.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n);var u=Object.getOwnPropertyDescriptor(t,n);u&&!("get"in u?!t.__esModule:u.writable||u.configurable)||(u={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,r,u)}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),J=w&&w.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),G=w&&w.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.prototype.hasOwnProperty.call(e,n)&&H(t,e,n);return J(t,e),t},V=w&&w.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(j,"__esModule",{value:!0}),j.isFileExists=j.offlinePluginConversion=j.executeCommand=j.getNpmPath=j.hasNpmPackInPaths=void 0;const U=h.default,W=G(p.default),z=b,K=$,q=V(D.default);j.hasNpmPackInPaths=function(e,t){try{return require.resolve(e,{paths:[...t]}),!0}catch(e){return!1}},j.getNpmPath=function(){const e=process.execPath;return W.join(W.dirname(e),z.NPM_TOOL)},j.executeCommand=function(e,t,n){0!==(0,U.spawnSync)(e,t,n).status&&(0,K.logErrorAndExit)(`Error: ${e} ${t} execute failed.See above for details.`)},j.offlinePluginConversion=function(e,t){return t.startsWith("file:")||t.endsWith(".tgz")?W.resolve(e,z.HVIGOR,t.replace("file:","")):t},j.isFileExists=function(e){return q.default.existsSync(e)&&q.default.statSync(e).isFile()},function(e){var t=w&&w.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n);var u=Object.getOwnPropertyDescriptor(t,n);u&&!("get"in u?!t.__esModule:u.writable||u.configurable)||(u={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,r,u)}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),n=w&&w.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),r=w&&w.__importStar||function(e){if(e&&e.__esModule)return e;var r={};if(null!=e)for(var u in e)"default"!==u&&Object.prototype.hasOwnProperty.call(e,u)&&t(r,e,u);return n(r,e),r},u=w&&w.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(e,"__esModule",{value:!0}),e.executeInstallPnpm=e.isPnpmAvailable=e.environmentHandler=e.checkNpmConifg=e.PNPM_VERSION=void 0;const o=r(D.default),i=b,s=j,c=r(p.default),a=$,l=h.default,f=u(E.default);e.PNPM_VERSION="7.30.0",e.checkNpmConifg=function(){const e=c.resolve(i.HVIGOR_PROJECT_ROOT_DIR,".npmrc"),t=c.resolve(f.default.homedir(),".npmrc");if((0,s.isFileExists)(e)||(0,s.isFileExists)(t))return;const n=(0,s.getNpmPath)(),r=(0,l.spawnSync)(n,["config","get","prefix"],{cwd:i.HVIGOR_PROJECT_ROOT_DIR});if(0!==r.status||!r.stdout)return void(0,a.logErrorAndExit)("Error: The hvigor depends on the npmrc file. Configure the npmrc file first.");const u=c.resolve(`${r.stdout}`.replace(/[\r\n]/gi,""),".npmrc");(0,s.isFileExists)(u)||(0,a.logErrorAndExit)("Error: The hvigor depends on the npmrc file. Configure the npmrc file first.")},e.environmentHandler=function(){process.env["npm_config_update-notifier"]="false"},e.isPnpmAvailable=function(){return!!o.existsSync(i.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH)&&(0,s.hasNpmPackInPaths)("pnpm",[i.HVIGOR_WRAPPER_TOOLS_HOME])},e.executeInstallPnpm=function(){(0,a.logInfoPrintConsole)(`Installing pnpm@${e.PNPM_VERSION}...`);const t=(0,s.getNpmPath)();!function(){const t=c.resolve(i.HVIGOR_WRAPPER_TOOLS_HOME,i.DEFAULT_PACKAGE_JSON);try{o.existsSync(i.HVIGOR_WRAPPER_TOOLS_HOME)||o.mkdirSync(i.HVIGOR_WRAPPER_TOOLS_HOME,{recursive:!0});const n={dependencies:{}};n.dependencies[i.PNPM]=e.PNPM_VERSION,o.writeFileSync(t,JSON.stringify(n))}catch(e){(0,a.logErrorAndExit)(`Error: EPERM: operation not permitted,create ${t} failed.`)}}(),(0,s.executeCommand)(t,["install","pnpm"],{cwd:i.HVIGOR_WRAPPER_TOOLS_HOME,stdio:["inherit","inherit","inherit"],env:process.env}),(0,a.logInfoPrintConsole)("Pnpm install success.")}}(O);var Y={},X={},Z={},Q={};Object.defineProperty(Q,"__esModule",{value:!0}),Q.Unicode=void 0;class ee{}Q.Unicode=ee,ee.Space_Separator=/[\u1680\u2000-\u200A\u202F\u205F\u3000]/,ee.ID_Start=/[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]/,ee.ID_Continue=/[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u08D4-\u08E1\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u09FC\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9-\u0AFF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C80-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D00-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D54-\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1CD0-\u1CD2\u1CD4-\u1CF9\u1D00-\u1DF9\u1DFB-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C5\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE3E\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC00-\uDC4A\uDC50-\uDC59\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDE00-\uDE3E\uDE47\uDE50-\uDE83\uDE86-\uDE99\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC36\uDC38-\uDC40\uDC50-\uDC59\uDC72-\uDC8F\uDC92-\uDCA7\uDCA9-\uDCB6\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD47\uDD50-\uDD59]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6\uDD00-\uDD4A\uDD50-\uDD59]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/,Object.defineProperty(Z,"__esModule",{value:!0}),Z.JudgeUtil=void 0;const te=Q;Z.JudgeUtil=class{static isIgnoreChar(e){return"string"==typeof e&&("\t"===e||"\v"===e||"\f"===e||" "===e||" "===e||"\ufeff"===e||"\n"===e||"\r"===e||"\u2028"===e||"\u2029"===e)}static isSpaceSeparator(e){return"string"==typeof e&&te.Unicode.Space_Separator.test(e)}static isIdStartChar(e){return"string"==typeof e&&(e>="a"&&e<="z"||e>="A"&&e<="Z"||"$"===e||"_"===e||te.Unicode.ID_Start.test(e))}static isIdContinueChar(e){return"string"==typeof e&&(e>="a"&&e<="z"||e>="A"&&e<="Z"||e>="0"&&e<="9"||"$"===e||"_"===e||"‌"===e||"‍"===e||te.Unicode.ID_Continue.test(e))}static isDigitWithoutZero(e){return/[1-9]/.test(e)}static isDigit(e){return"string"==typeof e&&/[0-9]/.test(e)}static isHexDigit(e){return"string"==typeof e&&/[0-9A-Fa-f]/.test(e)}};var ne={},re={fromCallback:function(e){return Object.defineProperty((function(...t){if("function"!=typeof t[t.length-1])return new Promise(((n,r)=>{e.call(this,...t,((e,t)=>null!=e?r(e):n(t)))}));e.apply(this,t)}),"name",{value:e.name})},fromPromise:function(e){return Object.defineProperty((function(...t){const n=t[t.length-1];if("function"!=typeof n)return e.apply(this,t);e.apply(this,t.slice(0,-1)).then((e=>n(null,e)),n)}),"name",{value:e.name})}},ue=y.default,oe=process.cwd,ie=null,se=process.env.GRACEFUL_FS_PLATFORM||process.platform;process.cwd=function(){return ie||(ie=oe.call(process)),ie};try{process.cwd()}catch(e){}if("function"==typeof process.chdir){var ce=process.chdir;process.chdir=function(e){ie=null,ce.call(process,e)},Object.setPrototypeOf&&Object.setPrototypeOf(process.chdir,ce)}var ae=function(e){ue.hasOwnProperty("O_SYMLINK")&&process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)&&function(e){e.lchmod=function(t,n,r){e.open(t,ue.O_WRONLY|ue.O_SYMLINK,n,(function(t,u){t?r&&r(t):e.fchmod(u,n,(function(t){e.close(u,(function(e){r&&r(t||e)}))}))}))},e.lchmodSync=function(t,n){var r,u=e.openSync(t,ue.O_WRONLY|ue.O_SYMLINK,n),o=!0;try{r=e.fchmodSync(u,n),o=!1}finally{if(o)try{e.closeSync(u)}catch(e){}else e.closeSync(u)}return r}}(e);e.lutimes||function(e){ue.hasOwnProperty("O_SYMLINK")&&e.futimes?(e.lutimes=function(t,n,r,u){e.open(t,ue.O_SYMLINK,(function(t,o){t?u&&u(t):e.futimes(o,n,r,(function(t){e.close(o,(function(e){u&&u(t||e)}))}))}))},e.lutimesSync=function(t,n,r){var u,o=e.openSync(t,ue.O_SYMLINK),i=!0;try{u=e.futimesSync(o,n,r),i=!1}finally{if(i)try{e.closeSync(o)}catch(e){}else e.closeSync(o)}return u}):e.futimes&&(e.lutimes=function(e,t,n,r){r&&process.nextTick(r)},e.lutimesSync=function(){})}(e);e.chown=r(e.chown),e.fchown=r(e.fchown),e.lchown=r(e.lchown),e.chmod=t(e.chmod),e.fchmod=t(e.fchmod),e.lchmod=t(e.lchmod),e.chownSync=u(e.chownSync),e.fchownSync=u(e.fchownSync),e.lchownSync=u(e.lchownSync),e.chmodSync=n(e.chmodSync),e.fchmodSync=n(e.fchmodSync),e.lchmodSync=n(e.lchmodSync),e.stat=o(e.stat),e.fstat=o(e.fstat),e.lstat=o(e.lstat),e.statSync=i(e.statSync),e.fstatSync=i(e.fstatSync),e.lstatSync=i(e.lstatSync),e.chmod&&!e.lchmod&&(e.lchmod=function(e,t,n){n&&process.nextTick(n)},e.lchmodSync=function(){});e.chown&&!e.lchown&&(e.lchown=function(e,t,n,r){r&&process.nextTick(r)},e.lchownSync=function(){});"win32"===se&&(e.rename="function"!=typeof e.rename?e.rename:function(t){function n(n,r,u){var o=Date.now(),i=0;t(n,r,(function s(c){if(c&&("EACCES"===c.code||"EPERM"===c.code||"EBUSY"===c.code)&&Date.now()-o<6e4)return setTimeout((function(){e.stat(r,(function(e,o){e&&"ENOENT"===e.code?t(n,r,s):u(c)}))}),i),void(i<100&&(i+=10));u&&u(c)}))}return Object.setPrototypeOf&&Object.setPrototypeOf(n,t),n}(e.rename));function t(t){return t?function(n,r,u){return t.call(e,n,r,(function(e){s(e)&&(e=null),u&&u.apply(this,arguments)}))}:t}function n(t){return t?function(n,r){try{return t.call(e,n,r)}catch(e){if(!s(e))throw e}}:t}function r(t){return t?function(n,r,u,o){return t.call(e,n,r,u,(function(e){s(e)&&(e=null),o&&o.apply(this,arguments)}))}:t}function u(t){return t?function(n,r,u){try{return t.call(e,n,r,u)}catch(e){if(!s(e))throw e}}:t}function o(t){return t?function(n,r,u){function o(e,t){t&&(t.uid<0&&(t.uid+=4294967296),t.gid<0&&(t.gid+=4294967296)),u&&u.apply(this,arguments)}return"function"==typeof r&&(u=r,r=null),r?t.call(e,n,r,o):t.call(e,n,o)}:t}function i(t){return t?function(n,r){var u=r?t.call(e,n,r):t.call(e,n);return u&&(u.uid<0&&(u.uid+=4294967296),u.gid<0&&(u.gid+=4294967296)),u}:t}function s(e){return!e||("ENOSYS"===e.code||!(process.getuid&&0===process.getuid()||"EINVAL"!==e.code&&"EPERM"!==e.code))}e.read="function"!=typeof e.read?e.read:function(t){function n(n,r,u,o,i,s){var c;if(s&&"function"==typeof s){var a=0;c=function(l,f,d){if(l&&"EAGAIN"===l.code&&a<10)return a++,t.call(e,n,r,u,o,i,c);s.apply(this,arguments)}}return t.call(e,n,r,u,o,i,c)}return Object.setPrototypeOf&&Object.setPrototypeOf(n,t),n}(e.read),e.readSync="function"!=typeof e.readSync?e.readSync:(c=e.readSync,function(t,n,r,u,o){for(var i=0;;)try{return c.call(e,t,n,r,u,o)}catch(e){if("EAGAIN"===e.code&&i<10){i++;continue}throw e}});var c};var le=C.default.Stream,fe=function(e){return{ReadStream:function t(n,r){if(!(this instanceof t))return new t(n,r);le.call(this);var u=this;this.path=n,this.fd=null,this.readable=!0,this.paused=!1,this.flags="r",this.mode=438,this.bufferSize=65536,r=r||{};for(var o=Object.keys(r),i=0,s=o.length;ithis.end)throw new Error("start must be <= end");this.pos=this.start}if(null!==this.fd)return void process.nextTick((function(){u._read()}));e.open(this.path,this.flags,this.mode,(function(e,t){if(e)return u.emit("error",e),void(u.readable=!1);u.fd=t,u.emit("open",t),u._read()}))},WriteStream:function t(n,r){if(!(this instanceof t))return new t(n,r);le.call(this),this.path=n,this.fd=null,this.writable=!0,this.flags="w",this.encoding="binary",this.mode=438,this.bytesWritten=0,r=r||{};for(var u=Object.keys(r),o=0,i=u.length;o= zero");this.pos=this.start}this.busy=!1,this._queue=[],null===this.fd&&(this._open=e.open,this._queue.push([this._open,this.path,this.flags,this.mode,void 0]),this.flush())}}};var de=function(e){if(null===e||"object"!=typeof e)return e;if(e instanceof Object)var t={__proto__:De(e)};else t=Object.create(null);return Object.getOwnPropertyNames(e).forEach((function(n){Object.defineProperty(t,n,Object.getOwnPropertyDescriptor(e,n))})),t},De=Object.getPrototypeOf||function(e){return e.__proto__};var pe,Ee,me=D.default,he=ae,ye=fe,Ce=de,Fe=F.default;function ge(e,t){Object.defineProperty(e,pe,{get:function(){return t}})}"function"==typeof Symbol&&"function"==typeof Symbol.for?(pe=Symbol.for("graceful-fs.queue"),Ee=Symbol.for("graceful-fs.previous")):(pe="___graceful-fs.queue",Ee="___graceful-fs.previous");var Ae=function(){};if(Fe.debuglog?Ae=Fe.debuglog("gfs4"):/\bgfs4\b/i.test(process.env.NODE_DEBUG||"")&&(Ae=function(){var e=Fe.format.apply(Fe,arguments);e="GFS4: "+e.split(/\n/).join("\nGFS4: "),console.error(e)}),!me[pe]){var ve=w[pe]||[];ge(me,ve),me.close=function(e){function t(t,n){return e.call(me,t,(function(e){e||_e(),"function"==typeof n&&n.apply(this,arguments)}))}return Object.defineProperty(t,Ee,{value:e}),t}(me.close),me.closeSync=function(e){function t(t){e.apply(me,arguments),_e()}return Object.defineProperty(t,Ee,{value:e}),t}(me.closeSync),/\bgfs4\b/i.test(process.env.NODE_DEBUG||"")&&process.on("exit",(function(){Ae(me[pe]),g.default.equal(me[pe].length,0)}))}w[pe]||ge(w,me[pe]);var Se,we=Oe(Ce(me));function Oe(e){he(e),e.gracefulify=Oe,e.createReadStream=function(t,n){return new e.ReadStream(t,n)},e.createWriteStream=function(t,n){return new e.WriteStream(t,n)};var t=e.readFile;e.readFile=function(e,n,r){"function"==typeof n&&(r=n,n=null);return function e(n,r,u,o){return t(n,r,(function(t){!t||"EMFILE"!==t.code&&"ENFILE"!==t.code?"function"==typeof u&&u.apply(this,arguments):be([e,[n,r,u],t,o||Date.now(),Date.now()])}))}(e,n,r)};var n=e.writeFile;e.writeFile=function(e,t,r,u){"function"==typeof r&&(u=r,r=null);return function e(t,r,u,o,i){return n(t,r,u,(function(n){!n||"EMFILE"!==n.code&&"ENFILE"!==n.code?"function"==typeof o&&o.apply(this,arguments):be([e,[t,r,u,o],n,i||Date.now(),Date.now()])}))}(e,t,r,u)};var r=e.appendFile;r&&(e.appendFile=function(e,t,n,u){"function"==typeof n&&(u=n,n=null);return function e(t,n,u,o,i){return r(t,n,u,(function(r){!r||"EMFILE"!==r.code&&"ENFILE"!==r.code?"function"==typeof o&&o.apply(this,arguments):be([e,[t,n,u,o],r,i||Date.now(),Date.now()])}))}(e,t,n,u)});var u=e.copyFile;u&&(e.copyFile=function(e,t,n,r){"function"==typeof n&&(r=n,n=0);return function e(t,n,r,o,i){return u(t,n,r,(function(u){!u||"EMFILE"!==u.code&&"ENFILE"!==u.code?"function"==typeof o&&o.apply(this,arguments):be([e,[t,n,r,o],u,i||Date.now(),Date.now()])}))}(e,t,n,r)});var o=e.readdir;e.readdir=function(e,t,n){"function"==typeof t&&(n=t,t=null);var r=i.test(process.version)?function(e,t,n,r){return o(e,u(e,t,n,r))}:function(e,t,n,r){return o(e,t,u(e,t,n,r))};return r(e,t,n);function u(e,t,n,u){return function(o,i){!o||"EMFILE"!==o.code&&"ENFILE"!==o.code?(i&&i.sort&&i.sort(),"function"==typeof n&&n.call(this,o,i)):be([r,[e,t,n],o,u||Date.now(),Date.now()])}}};var i=/^v[0-5]\./;if("v0.8"===process.version.substr(0,4)){var s=ye(e);d=s.ReadStream,D=s.WriteStream}var c=e.ReadStream;c&&(d.prototype=Object.create(c.prototype),d.prototype.open=function(){var e=this;E(e.path,e.flags,e.mode,(function(t,n){t?(e.autoClose&&e.destroy(),e.emit("error",t)):(e.fd=n,e.emit("open",n),e.read())}))});var a=e.WriteStream;a&&(D.prototype=Object.create(a.prototype),D.prototype.open=function(){var e=this;E(e.path,e.flags,e.mode,(function(t,n){t?(e.destroy(),e.emit("error",t)):(e.fd=n,e.emit("open",n))}))}),Object.defineProperty(e,"ReadStream",{get:function(){return d},set:function(e){d=e},enumerable:!0,configurable:!0}),Object.defineProperty(e,"WriteStream",{get:function(){return D},set:function(e){D=e},enumerable:!0,configurable:!0});var l=d;Object.defineProperty(e,"FileReadStream",{get:function(){return l},set:function(e){l=e},enumerable:!0,configurable:!0});var f=D;function d(e,t){return this instanceof d?(c.apply(this,arguments),this):d.apply(Object.create(d.prototype),arguments)}function D(e,t){return this instanceof D?(a.apply(this,arguments),this):D.apply(Object.create(D.prototype),arguments)}Object.defineProperty(e,"FileWriteStream",{get:function(){return f},set:function(e){f=e},enumerable:!0,configurable:!0});var p=e.open;function E(e,t,n,r){return"function"==typeof n&&(r=n,n=null),function e(t,n,r,u,o){return p(t,n,r,(function(i,s){!i||"EMFILE"!==i.code&&"ENFILE"!==i.code?"function"==typeof u&&u.apply(this,arguments):be([e,[t,n,r,u],i,o||Date.now(),Date.now()])}))}(e,t,n,r)}return e.open=E,e}function be(e){Ae("ENQUEUE",e[0].name,e[1]),me[pe].push(e),Be()}function _e(){for(var e=Date.now(),t=0;t2&&(me[pe][t][3]=e,me[pe][t][4]=e);Be()}function Be(){if(clearTimeout(Se),Se=void 0,0!==me[pe].length){var e=me[pe].shift(),t=e[0],n=e[1],r=e[2],u=e[3],o=e[4];if(void 0===u)Ae("RETRY",t.name,n),t.apply(null,n);else if(Date.now()-u>=6e4){Ae("TIMEOUT",t.name,n);var i=n.pop();"function"==typeof i&&i.call(null,r)}else{var s=Date.now()-o,c=Math.max(o-u,1);s>=Math.min(1.2*c,100)?(Ae("RETRY",t.name,n),t.apply(null,n.concat([u]))):me[pe].push(e)}void 0===Se&&(Se=setTimeout(Be,0))}}process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH&&!me.__patched&&(we=Oe(me),me.__patched=!0),function(e){const t=re.fromCallback,n=we,r=["access","appendFile","chmod","chown","close","copyFile","fchmod","fchown","fdatasync","fstat","fsync","ftruncate","futimes","lchmod","lchown","link","lstat","mkdir","mkdtemp","open","opendir","readdir","readFile","readlink","realpath","rename","rm","rmdir","stat","symlink","truncate","unlink","utimes","writeFile"].filter((e=>"function"==typeof n[e]));Object.assign(e,n),r.forEach((r=>{e[r]=t(n[r])})),e.realpath.native=t(n.realpath.native),e.exists=function(e,t){return"function"==typeof t?n.exists(e,t):new Promise((t=>n.exists(e,t)))},e.read=function(e,t,r,u,o,i){return"function"==typeof i?n.read(e,t,r,u,o,i):new Promise(((i,s)=>{n.read(e,t,r,u,o,((e,t,n)=>{if(e)return s(e);i({bytesRead:t,buffer:n})}))}))},e.write=function(e,t,...r){return"function"==typeof r[r.length-1]?n.write(e,t,...r):new Promise(((u,o)=>{n.write(e,t,...r,((e,t,n)=>{if(e)return o(e);u({bytesWritten:t,buffer:n})}))}))},"function"==typeof n.writev&&(e.writev=function(e,t,...r){return"function"==typeof r[r.length-1]?n.writev(e,t,...r):new Promise(((u,o)=>{n.writev(e,t,...r,((e,t,n)=>{if(e)return o(e);u({bytesWritten:t,buffers:n})}))}))})}(ne);var Pe={},ke={};const xe=p.default;ke.checkPath=function(e){if("win32"===process.platform){if(/[<>:"|?*]/.test(e.replace(xe.parse(e).root,""))){const t=new Error(`Path contains invalid characters: ${e}`);throw t.code="EINVAL",t}}};const Ne=ne,{checkPath:Ie}=ke,Te=e=>"number"==typeof e?e:{mode:511,...e}.mode;Pe.makeDir=async(e,t)=>(Ie(e),Ne.mkdir(e,{mode:Te(t),recursive:!0})),Pe.makeDirSync=(e,t)=>(Ie(e),Ne.mkdirSync(e,{mode:Te(t),recursive:!0}));const Re=re.fromPromise,{makeDir:Me,makeDirSync:Le}=Pe,je=Re(Me);var $e={mkdirs:je,mkdirsSync:Le,mkdirp:je,mkdirpSync:Le,ensureDir:je,ensureDirSync:Le};const He=re.fromPromise,Je=ne;var Ge={pathExists:He((function(e){return Je.access(e).then((()=>!0)).catch((()=>!1))})),pathExistsSync:Je.existsSync};const Ve=we;var Ue=function(e,t,n,r){Ve.open(e,"r+",((e,u)=>{if(e)return r(e);Ve.futimes(u,t,n,(e=>{Ve.close(u,(t=>{r&&r(e||t)}))}))}))},We=function(e,t,n){const r=Ve.openSync(e,"r+");return Ve.futimesSync(r,t,n),Ve.closeSync(r)};const ze=ne,Ke=p.default,qe=F.default;function Ye(e,t,n){const r=n.dereference?e=>ze.stat(e,{bigint:!0}):e=>ze.lstat(e,{bigint:!0});return Promise.all([r(e),r(t).catch((e=>{if("ENOENT"===e.code)return null;throw e}))]).then((([e,t])=>({srcStat:e,destStat:t})))}function Xe(e,t){return t.ino&&t.dev&&t.ino===e.ino&&t.dev===e.dev}function Ze(e,t){const n=Ke.resolve(e).split(Ke.sep).filter((e=>e)),r=Ke.resolve(t).split(Ke.sep).filter((e=>e));return n.reduce(((e,t,n)=>e&&r[n]===t),!0)}function Qe(e,t,n){return`Cannot ${n} '${e}' to a subdirectory of itself, '${t}'.`}var et={checkPaths:function(e,t,n,r,u){qe.callbackify(Ye)(e,t,r,((r,o)=>{if(r)return u(r);const{srcStat:i,destStat:s}=o;if(s){if(Xe(i,s)){const r=Ke.basename(e),o=Ke.basename(t);return"move"===n&&r!==o&&r.toLowerCase()===o.toLowerCase()?u(null,{srcStat:i,destStat:s,isChangingCase:!0}):u(new Error("Source and destination must not be the same."))}if(i.isDirectory()&&!s.isDirectory())return u(new Error(`Cannot overwrite non-directory '${t}' with directory '${e}'.`));if(!i.isDirectory()&&s.isDirectory())return u(new Error(`Cannot overwrite directory '${t}' with non-directory '${e}'.`))}return i.isDirectory()&&Ze(e,t)?u(new Error(Qe(e,t,n))):u(null,{srcStat:i,destStat:s})}))},checkPathsSync:function(e,t,n,r){const{srcStat:u,destStat:o}=function(e,t,n){let r;const u=n.dereference?e=>ze.statSync(e,{bigint:!0}):e=>ze.lstatSync(e,{bigint:!0}),o=u(e);try{r=u(t)}catch(e){if("ENOENT"===e.code)return{srcStat:o,destStat:null};throw e}return{srcStat:o,destStat:r}}(e,t,r);if(o){if(Xe(u,o)){const r=Ke.basename(e),i=Ke.basename(t);if("move"===n&&r!==i&&r.toLowerCase()===i.toLowerCase())return{srcStat:u,destStat:o,isChangingCase:!0};throw new Error("Source and destination must not be the same.")}if(u.isDirectory()&&!o.isDirectory())throw new Error(`Cannot overwrite non-directory '${t}' with directory '${e}'.`);if(!u.isDirectory()&&o.isDirectory())throw new Error(`Cannot overwrite directory '${t}' with non-directory '${e}'.`)}if(u.isDirectory()&&Ze(e,t))throw new Error(Qe(e,t,n));return{srcStat:u,destStat:o}},checkParentPaths:function e(t,n,r,u,o){const i=Ke.resolve(Ke.dirname(t)),s=Ke.resolve(Ke.dirname(r));if(s===i||s===Ke.parse(s).root)return o();ze.stat(s,{bigint:!0},((i,c)=>i?"ENOENT"===i.code?o():o(i):Xe(n,c)?o(new Error(Qe(t,r,u))):e(t,n,s,u,o)))},checkParentPathsSync:function e(t,n,r,u){const o=Ke.resolve(Ke.dirname(t)),i=Ke.resolve(Ke.dirname(r));if(i===o||i===Ke.parse(i).root)return;let s;try{s=ze.statSync(i,{bigint:!0})}catch(e){if("ENOENT"===e.code)return;throw e}if(Xe(n,s))throw new Error(Qe(t,r,u));return e(t,n,i,u)},isSrcSubdir:Ze,areIdentical:Xe};const tt=we,nt=p.default,rt=$e.mkdirs,ut=Ge.pathExists,ot=Ue,it=et;function st(e,t,n,r,u){const o=nt.dirname(n);ut(o,((i,s)=>i?u(i):s?at(e,t,n,r,u):void rt(o,(o=>o?u(o):at(e,t,n,r,u)))))}function ct(e,t,n,r,u,o){Promise.resolve(u.filter(n,r)).then((i=>i?e(t,n,r,u,o):o()),(e=>o(e)))}function at(e,t,n,r,u){(r.dereference?tt.stat:tt.lstat)(t,((o,i)=>o?u(o):i.isDirectory()?function(e,t,n,r,u,o){return t?Dt(n,r,u,o):function(e,t,n,r,u){tt.mkdir(n,(o=>{if(o)return u(o);Dt(t,n,r,(t=>t?u(t):dt(n,e,u)))}))}(e.mode,n,r,u,o)}(i,e,t,n,r,u):i.isFile()||i.isCharacterDevice()||i.isBlockDevice()?function(e,t,n,r,u,o){return t?function(e,t,n,r,u){if(!r.overwrite)return r.errorOnExist?u(new Error(`'${n}' already exists`)):u();tt.unlink(n,(o=>o?u(o):lt(e,t,n,r,u)))}(e,n,r,u,o):lt(e,n,r,u,o)}(i,e,t,n,r,u):i.isSymbolicLink()?function(e,t,n,r,u){tt.readlink(t,((t,o)=>t?u(t):(r.dereference&&(o=nt.resolve(process.cwd(),o)),e?void tt.readlink(n,((t,i)=>t?"EINVAL"===t.code||"UNKNOWN"===t.code?tt.symlink(o,n,u):u(t):(r.dereference&&(i=nt.resolve(process.cwd(),i)),it.isSrcSubdir(o,i)?u(new Error(`Cannot copy '${o}' to a subdirectory of itself, '${i}'.`)):e.isDirectory()&&it.isSrcSubdir(i,o)?u(new Error(`Cannot overwrite '${i}' with '${o}'.`)):function(e,t,n){tt.unlink(t,(r=>r?n(r):tt.symlink(e,t,n)))}(o,n,u)))):tt.symlink(o,n,u))))}(e,t,n,r,u):i.isSocket()?u(new Error(`Cannot copy a socket file: ${t}`)):i.isFIFO()?u(new Error(`Cannot copy a FIFO pipe: ${t}`)):u(new Error(`Unknown file: ${t}`))))}function lt(e,t,n,r,u){tt.copyFile(t,n,(o=>o?u(o):r.preserveTimestamps?function(e,t,n,r){if(function(e){return 0==(128&e)}(e))return function(e,t,n){return dt(e,128|t,n)}(n,e,(u=>u?r(u):ft(e,t,n,r)));return ft(e,t,n,r)}(e.mode,t,n,u):dt(n,e.mode,u)))}function ft(e,t,n,r){!function(e,t,n){tt.stat(e,((e,r)=>e?n(e):ot(t,r.atime,r.mtime,n)))}(t,n,(t=>t?r(t):dt(n,e,r)))}function dt(e,t,n){return tt.chmod(e,t,n)}function Dt(e,t,n,r){tt.readdir(e,((u,o)=>u?r(u):pt(o,e,t,n,r)))}function pt(e,t,n,r,u){const o=e.pop();return o?function(e,t,n,r,u,o){const i=nt.join(n,t),s=nt.join(r,t);it.checkPaths(i,s,"copy",u,((t,c)=>{if(t)return o(t);const{destStat:a}=c;!function(e,t,n,r,u){r.filter?ct(at,e,t,n,r,u):at(e,t,n,r,u)}(a,i,s,u,(t=>t?o(t):pt(e,n,r,u,o)))}))}(e,o,t,n,r,u):u()}var Et=function(e,t,n,r){"function"!=typeof n||r?"function"==typeof n&&(n={filter:n}):(r=n,n={}),r=r||function(){},(n=n||{}).clobber=!("clobber"in n)||!!n.clobber,n.overwrite="overwrite"in n?!!n.overwrite:n.clobber,n.preserveTimestamps&&"ia32"===process.arch&&console.warn("fs-extra: Using the preserveTimestamps option in 32-bit node is not recommended;\n\n see https://github.com/jprichardson/node-fs-extra/issues/269"),it.checkPaths(e,t,"copy",n,((u,o)=>{if(u)return r(u);const{srcStat:i,destStat:s}=o;it.checkParentPaths(e,i,t,"copy",(u=>u?r(u):n.filter?ct(st,s,e,t,n,r):st(s,e,t,n,r)))}))};const mt=we,ht=p.default,yt=$e.mkdirsSync,Ct=We,Ft=et;function gt(e,t,n,r){const u=(r.dereference?mt.statSync:mt.lstatSync)(t);if(u.isDirectory())return function(e,t,n,r,u){return t?St(n,r,u):function(e,t,n,r){return mt.mkdirSync(n),St(t,n,r),vt(n,e)}(e.mode,n,r,u)}(u,e,t,n,r);if(u.isFile()||u.isCharacterDevice()||u.isBlockDevice())return function(e,t,n,r,u){return t?function(e,t,n,r){if(r.overwrite)return mt.unlinkSync(n),At(e,t,n,r);if(r.errorOnExist)throw new Error(`'${n}' already exists`)}(e,n,r,u):At(e,n,r,u)}(u,e,t,n,r);if(u.isSymbolicLink())return function(e,t,n,r){let u=mt.readlinkSync(t);r.dereference&&(u=ht.resolve(process.cwd(),u));if(e){let e;try{e=mt.readlinkSync(n)}catch(e){if("EINVAL"===e.code||"UNKNOWN"===e.code)return mt.symlinkSync(u,n);throw e}if(r.dereference&&(e=ht.resolve(process.cwd(),e)),Ft.isSrcSubdir(u,e))throw new Error(`Cannot copy '${u}' to a subdirectory of itself, '${e}'.`);if(mt.statSync(n).isDirectory()&&Ft.isSrcSubdir(e,u))throw new Error(`Cannot overwrite '${e}' with '${u}'.`);return function(e,t){return mt.unlinkSync(t),mt.symlinkSync(e,t)}(u,n)}return mt.symlinkSync(u,n)}(e,t,n,r);if(u.isSocket())throw new Error(`Cannot copy a socket file: ${t}`);if(u.isFIFO())throw new Error(`Cannot copy a FIFO pipe: ${t}`);throw new Error(`Unknown file: ${t}`)}function At(e,t,n,r){return mt.copyFileSync(t,n),r.preserveTimestamps&&function(e,t,n){(function(e){return 0==(128&e)})(e)&&function(e,t){vt(e,128|t)}(n,e);(function(e,t){const n=mt.statSync(e);Ct(t,n.atime,n.mtime)})(t,n)}(e.mode,t,n),vt(n,e.mode)}function vt(e,t){return mt.chmodSync(e,t)}function St(e,t,n){mt.readdirSync(e).forEach((r=>function(e,t,n,r){const u=ht.join(t,e),o=ht.join(n,e),{destStat:i}=Ft.checkPathsSync(u,o,"copy",r);return function(e,t,n,r){if(!r.filter||r.filter(t,n))return gt(e,t,n,r)}(i,u,o,r)}(r,e,t,n)))}var wt=function(e,t,n){"function"==typeof n&&(n={filter:n}),(n=n||{}).clobber=!("clobber"in n)||!!n.clobber,n.overwrite="overwrite"in n?!!n.overwrite:n.clobber,n.preserveTimestamps&&"ia32"===process.arch&&console.warn("fs-extra: Using the preserveTimestamps option in 32-bit node is not recommended;\n\n see https://github.com/jprichardson/node-fs-extra/issues/269");const{srcStat:r,destStat:u}=Ft.checkPathsSync(e,t,"copy",n);return Ft.checkParentPathsSync(e,r,t,"copy"),function(e,t,n,r){if(r.filter&&!r.filter(t,n))return;const u=ht.dirname(n);mt.existsSync(u)||yt(u);return gt(e,t,n,r)}(u,e,t,n)};var Ot={copy:(0,re.fromCallback)(Et),copySync:wt};const bt=we,_t=p.default,Bt=g.default,Pt="win32"===process.platform;function kt(e){["unlink","chmod","stat","lstat","rmdir","readdir"].forEach((t=>{e[t]=e[t]||bt[t],e[t+="Sync"]=e[t]||bt[t]})),e.maxBusyTries=e.maxBusyTries||3}function xt(e,t,n){let r=0;"function"==typeof t&&(n=t,t={}),Bt(e,"rimraf: missing path"),Bt.strictEqual(typeof e,"string","rimraf: path should be a string"),Bt.strictEqual(typeof n,"function","rimraf: callback function required"),Bt(t,"rimraf: invalid options argument provided"),Bt.strictEqual(typeof t,"object","rimraf: options should be object"),kt(t),Nt(e,t,(function u(o){if(o){if(("EBUSY"===o.code||"ENOTEMPTY"===o.code||"EPERM"===o.code)&&rNt(e,t,u)),100*r)}"ENOENT"===o.code&&(o=null)}n(o)}))}function Nt(e,t,n){Bt(e),Bt(t),Bt("function"==typeof n),t.lstat(e,((r,u)=>r&&"ENOENT"===r.code?n(null):r&&"EPERM"===r.code&&Pt?It(e,t,r,n):u&&u.isDirectory()?Rt(e,t,r,n):void t.unlink(e,(r=>{if(r){if("ENOENT"===r.code)return n(null);if("EPERM"===r.code)return Pt?It(e,t,r,n):Rt(e,t,r,n);if("EISDIR"===r.code)return Rt(e,t,r,n)}return n(r)}))))}function It(e,t,n,r){Bt(e),Bt(t),Bt("function"==typeof r),t.chmod(e,438,(u=>{u?r("ENOENT"===u.code?null:n):t.stat(e,((u,o)=>{u?r("ENOENT"===u.code?null:n):o.isDirectory()?Rt(e,t,n,r):t.unlink(e,r)}))}))}function Tt(e,t,n){let r;Bt(e),Bt(t);try{t.chmodSync(e,438)}catch(e){if("ENOENT"===e.code)return;throw n}try{r=t.statSync(e)}catch(e){if("ENOENT"===e.code)return;throw n}r.isDirectory()?Lt(e,t,n):t.unlinkSync(e)}function Rt(e,t,n,r){Bt(e),Bt(t),Bt("function"==typeof r),t.rmdir(e,(u=>{!u||"ENOTEMPTY"!==u.code&&"EEXIST"!==u.code&&"EPERM"!==u.code?u&&"ENOTDIR"===u.code?r(n):r(u):function(e,t,n){Bt(e),Bt(t),Bt("function"==typeof n),t.readdir(e,((r,u)=>{if(r)return n(r);let o,i=u.length;if(0===i)return t.rmdir(e,n);u.forEach((r=>{xt(_t.join(e,r),t,(r=>{if(!o)return r?n(o=r):void(0==--i&&t.rmdir(e,n))}))}))}))}(e,t,r)}))}function Mt(e,t){let n;kt(t=t||{}),Bt(e,"rimraf: missing path"),Bt.strictEqual(typeof e,"string","rimraf: path should be a string"),Bt(t,"rimraf: missing options"),Bt.strictEqual(typeof t,"object","rimraf: options should be object");try{n=t.lstatSync(e)}catch(n){if("ENOENT"===n.code)return;"EPERM"===n.code&&Pt&&Tt(e,t,n)}try{n&&n.isDirectory()?Lt(e,t,null):t.unlinkSync(e)}catch(n){if("ENOENT"===n.code)return;if("EPERM"===n.code)return Pt?Tt(e,t,n):Lt(e,t,n);if("EISDIR"!==n.code)throw n;Lt(e,t,n)}}function Lt(e,t,n){Bt(e),Bt(t);try{t.rmdirSync(e)}catch(r){if("ENOTDIR"===r.code)throw n;if("ENOTEMPTY"===r.code||"EEXIST"===r.code||"EPERM"===r.code)!function(e,t){if(Bt(e),Bt(t),t.readdirSync(e).forEach((n=>Mt(_t.join(e,n),t))),!Pt){return t.rmdirSync(e,t)}{const n=Date.now();do{try{return t.rmdirSync(e,t)}catch{}}while(Date.now()-n<500)}}(e,t);else if("ENOENT"!==r.code)throw r}}var jt=xt;xt.sync=Mt;const $t=we,Ht=re.fromCallback,Jt=jt;var Gt={remove:Ht((function(e,t){if($t.rm)return $t.rm(e,{recursive:!0,force:!0},t);Jt(e,t)})),removeSync:function(e){if($t.rmSync)return $t.rmSync(e,{recursive:!0,force:!0});Jt.sync(e)}};const Vt=re.fromPromise,Ut=ne,Wt=p.default,zt=$e,Kt=Gt,qt=Vt((async function(e){let t;try{t=await Ut.readdir(e)}catch{return zt.mkdirs(e)}return Promise.all(t.map((t=>Kt.remove(Wt.join(e,t)))))}));function Yt(e){let t;try{t=Ut.readdirSync(e)}catch{return zt.mkdirsSync(e)}t.forEach((t=>{t=Wt.join(e,t),Kt.removeSync(t)}))}var Xt={emptyDirSync:Yt,emptydirSync:Yt,emptyDir:qt,emptydir:qt};const Zt=re.fromCallback,Qt=p.default,en=we,tn=$e;var nn={createFile:Zt((function(e,t){function n(){en.writeFile(e,"",(e=>{if(e)return t(e);t()}))}en.stat(e,((r,u)=>{if(!r&&u.isFile())return t();const o=Qt.dirname(e);en.stat(o,((e,r)=>{if(e)return"ENOENT"===e.code?tn.mkdirs(o,(e=>{if(e)return t(e);n()})):t(e);r.isDirectory()?n():en.readdir(o,(e=>{if(e)return t(e)}))}))}))})),createFileSync:function(e){let t;try{t=en.statSync(e)}catch{}if(t&&t.isFile())return;const n=Qt.dirname(e);try{en.statSync(n).isDirectory()||en.readdirSync(n)}catch(e){if(!e||"ENOENT"!==e.code)throw e;tn.mkdirsSync(n)}en.writeFileSync(e,"")}};const rn=re.fromCallback,un=p.default,on=we,sn=$e,cn=Ge.pathExists,{areIdentical:an}=et;var ln={createLink:rn((function(e,t,n){function r(e,t){on.link(e,t,(e=>{if(e)return n(e);n(null)}))}on.lstat(t,((u,o)=>{on.lstat(e,((u,i)=>{if(u)return u.message=u.message.replace("lstat","ensureLink"),n(u);if(o&&an(i,o))return n(null);const s=un.dirname(t);cn(s,((u,o)=>u?n(u):o?r(e,t):void sn.mkdirs(s,(u=>{if(u)return n(u);r(e,t)}))))}))}))})),createLinkSync:function(e,t){let n;try{n=on.lstatSync(t)}catch{}try{const t=on.lstatSync(e);if(n&&an(t,n))return}catch(e){throw e.message=e.message.replace("lstat","ensureLink"),e}const r=un.dirname(t);return on.existsSync(r)||sn.mkdirsSync(r),on.linkSync(e,t)}};const fn=p.default,dn=we,Dn=Ge.pathExists;var pn={symlinkPaths:function(e,t,n){if(fn.isAbsolute(e))return dn.lstat(e,(t=>t?(t.message=t.message.replace("lstat","ensureSymlink"),n(t)):n(null,{toCwd:e,toDst:e})));{const r=fn.dirname(t),u=fn.join(r,e);return Dn(u,((t,o)=>t?n(t):o?n(null,{toCwd:u,toDst:e}):dn.lstat(e,(t=>t?(t.message=t.message.replace("lstat","ensureSymlink"),n(t)):n(null,{toCwd:e,toDst:fn.relative(r,e)})))))}},symlinkPathsSync:function(e,t){let n;if(fn.isAbsolute(e)){if(n=dn.existsSync(e),!n)throw new Error("absolute srcpath does not exist");return{toCwd:e,toDst:e}}{const r=fn.dirname(t),u=fn.join(r,e);if(n=dn.existsSync(u),n)return{toCwd:u,toDst:e};if(n=dn.existsSync(e),!n)throw new Error("relative srcpath does not exist");return{toCwd:e,toDst:fn.relative(r,e)}}}};const En=we;var mn={symlinkType:function(e,t,n){if(n="function"==typeof t?t:n,t="function"!=typeof t&&t)return n(null,t);En.lstat(e,((e,r)=>{if(e)return n(null,"file");t=r&&r.isDirectory()?"dir":"file",n(null,t)}))},symlinkTypeSync:function(e,t){let n;if(t)return t;try{n=En.lstatSync(e)}catch{return"file"}return n&&n.isDirectory()?"dir":"file"}};const hn=re.fromCallback,yn=p.default,Cn=ne,Fn=$e.mkdirs,gn=$e.mkdirsSync,An=pn.symlinkPaths,vn=pn.symlinkPathsSync,Sn=mn.symlinkType,wn=mn.symlinkTypeSync,On=Ge.pathExists,{areIdentical:bn}=et;function _n(e,t,n,r){An(e,t,((u,o)=>{if(u)return r(u);e=o.toDst,Sn(o.toCwd,n,((n,u)=>{if(n)return r(n);const o=yn.dirname(t);On(o,((n,i)=>n?r(n):i?Cn.symlink(e,t,u,r):void Fn(o,(n=>{if(n)return r(n);Cn.symlink(e,t,u,r)}))))}))}))}var Bn={createSymlink:hn((function(e,t,n,r){r="function"==typeof n?n:r,n="function"!=typeof n&&n,Cn.lstat(t,((u,o)=>{!u&&o.isSymbolicLink()?Promise.all([Cn.stat(e),Cn.stat(t)]).then((([u,o])=>{if(bn(u,o))return r(null);_n(e,t,n,r)})):_n(e,t,n,r)}))})),createSymlinkSync:function(e,t,n){let r;try{r=Cn.lstatSync(t)}catch{}if(r&&r.isSymbolicLink()){const n=Cn.statSync(e),r=Cn.statSync(t);if(bn(n,r))return}const u=vn(e,t);e=u.toDst,n=wn(u.toCwd,n);const o=yn.dirname(t);return Cn.existsSync(o)||gn(o),Cn.symlinkSync(e,t,n)}};const{createFile:Pn,createFileSync:kn}=nn,{createLink:xn,createLinkSync:Nn}=ln,{createSymlink:In,createSymlinkSync:Tn}=Bn;var Rn={createFile:Pn,createFileSync:kn,ensureFile:Pn,ensureFileSync:kn,createLink:xn,createLinkSync:Nn,ensureLink:xn,ensureLinkSync:Nn,createSymlink:In,createSymlinkSync:Tn,ensureSymlink:In,ensureSymlinkSync:Tn};var Mn={stringify:function(e,{EOL:t="\n",finalEOL:n=!0,replacer:r=null,spaces:u}={}){const o=n?t:"";return JSON.stringify(e,r,u).replace(/\n/g,t)+o},stripBom:function(e){return Buffer.isBuffer(e)&&(e=e.toString("utf8")),e.replace(/^\uFEFF/,"")}};let Ln;try{Ln=we}catch(e){Ln=D.default}const jn=re,{stringify:$n,stripBom:Hn}=Mn;const Jn=jn.fromPromise((async function(e,t={}){"string"==typeof t&&(t={encoding:t});const n=t.fs||Ln,r=!("throws"in t)||t.throws;let u,o=await jn.fromCallback(n.readFile)(e,t);o=Hn(o);try{u=JSON.parse(o,t?t.reviver:null)}catch(t){if(r)throw t.message=`${e}: ${t.message}`,t;return null}return u}));const Gn=jn.fromPromise((async function(e,t,n={}){const r=n.fs||Ln,u=$n(t,n);await jn.fromCallback(r.writeFile)(e,u,n)}));const Vn={readFile:Jn,readFileSync:function(e,t={}){"string"==typeof t&&(t={encoding:t});const n=t.fs||Ln,r=!("throws"in t)||t.throws;try{let r=n.readFileSync(e,t);return r=Hn(r),JSON.parse(r,t.reviver)}catch(t){if(r)throw t.message=`${e}: ${t.message}`,t;return null}},writeFile:Gn,writeFileSync:function(e,t,n={}){const r=n.fs||Ln,u=$n(t,n);return r.writeFileSync(e,u,n)}};var Un={readJson:Vn.readFile,readJsonSync:Vn.readFileSync,writeJson:Vn.writeFile,writeJsonSync:Vn.writeFileSync};const Wn=re.fromCallback,zn=we,Kn=p.default,qn=$e,Yn=Ge.pathExists;var Xn={outputFile:Wn((function(e,t,n,r){"function"==typeof n&&(r=n,n="utf8");const u=Kn.dirname(e);Yn(u,((o,i)=>o?r(o):i?zn.writeFile(e,t,n,r):void qn.mkdirs(u,(u=>{if(u)return r(u);zn.writeFile(e,t,n,r)}))))})),outputFileSync:function(e,...t){const n=Kn.dirname(e);if(zn.existsSync(n))return zn.writeFileSync(e,...t);qn.mkdirsSync(n),zn.writeFileSync(e,...t)}};const{stringify:Zn}=Mn,{outputFile:Qn}=Xn;var er=async function(e,t,n={}){const r=Zn(t,n);await Qn(e,r,n)};const{stringify:tr}=Mn,{outputFileSync:nr}=Xn;var rr=function(e,t,n){const r=tr(t,n);nr(e,r,n)};const ur=re.fromPromise,or=Un;or.outputJson=ur(er),or.outputJsonSync=rr,or.outputJSON=or.outputJson,or.outputJSONSync=or.outputJsonSync,or.writeJSON=or.writeJson,or.writeJSONSync=or.writeJsonSync,or.readJSON=or.readJson,or.readJSONSync=or.readJsonSync;var ir=or;const sr=we,cr=p.default,ar=Ot.copy,lr=Gt.remove,fr=$e.mkdirp,dr=Ge.pathExists,Dr=et;function pr(e,t,n,r,u){return r?Er(e,t,n,u):n?lr(t,(r=>r?u(r):Er(e,t,n,u))):void dr(t,((r,o)=>r?u(r):o?u(new Error("dest already exists.")):Er(e,t,n,u)))}function Er(e,t,n,r){sr.rename(e,t,(u=>u?"EXDEV"!==u.code?r(u):function(e,t,n,r){const u={overwrite:n,errorOnExist:!0};ar(e,t,u,(t=>t?r(t):lr(e,r)))}(e,t,n,r):r()))}var mr=function(e,t,n,r){"function"==typeof n&&(r=n,n={});const u=n.overwrite||n.clobber||!1;Dr.checkPaths(e,t,"move",n,((n,o)=>{if(n)return r(n);const{srcStat:i,isChangingCase:s=!1}=o;Dr.checkParentPaths(e,i,t,"move",(n=>n?r(n):function(e){const t=cr.dirname(e);return cr.parse(t).root===t}(t)?pr(e,t,u,s,r):void fr(cr.dirname(t),(n=>n?r(n):pr(e,t,u,s,r)))))}))};const hr=we,yr=p.default,Cr=Ot.copySync,Fr=Gt.removeSync,gr=$e.mkdirpSync,Ar=et;function vr(e,t,n){try{hr.renameSync(e,t)}catch(r){if("EXDEV"!==r.code)throw r;return function(e,t,n){const r={overwrite:n,errorOnExist:!0};return Cr(e,t,r),Fr(e)}(e,t,n)}}var Sr=function(e,t,n){const r=(n=n||{}).overwrite||n.clobber||!1,{srcStat:u,isChangingCase:o=!1}=Ar.checkPathsSync(e,t,"move",n);return Ar.checkParentPathsSync(e,u,t,"move"),function(e){const t=yr.dirname(e);return yr.parse(t).root===t}(t)||gr(yr.dirname(t)),function(e,t,n,r){if(r)return vr(e,t,n);if(n)return Fr(t),vr(e,t,n);if(hr.existsSync(t))throw new Error("dest already exists.");return vr(e,t,n)}(e,t,r,o)};var wr,Or,br,_r,Br,Pr={move:(0,re.fromCallback)(mr),moveSync:Sr},kr={...ne,...Ot,...Xt,...Rn,...ir,...$e,...Pr,...Xn,...Ge,...Gt},xr={},Nr={exports:{}},Ir={exports:{}};function Tr(){if(Or)return wr;Or=1;var e=1e3,t=60*e,n=60*t,r=24*n,u=7*r,o=365.25*r;function i(e,t,n,r){var u=t>=1.5*n;return Math.round(e/n)+" "+r+(u?"s":"")}return wr=function(s,c){c=c||{};var a=typeof s;if("string"===a&&s.length>0)return function(i){if((i=String(i)).length>100)return;var s=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(i);if(!s)return;var c=parseFloat(s[1]);switch((s[2]||"ms").toLowerCase()){case"years":case"year":case"yrs":case"yr":case"y":return c*o;case"weeks":case"week":case"w":return c*u;case"days":case"day":case"d":return c*r;case"hours":case"hour":case"hrs":case"hr":case"h":return c*n;case"minutes":case"minute":case"mins":case"min":case"m":return c*t;case"seconds":case"second":case"secs":case"sec":case"s":return c*e;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return c;default:return}}(s);if("number"===a&&isFinite(s))return c.long?function(u){var o=Math.abs(u);if(o>=r)return i(u,o,r,"day");if(o>=n)return i(u,o,n,"hour");if(o>=t)return i(u,o,t,"minute");if(o>=e)return i(u,o,e,"second");return u+" ms"}(s):function(u){var o=Math.abs(u);if(o>=r)return Math.round(u/r)+"d";if(o>=n)return Math.round(u/n)+"h";if(o>=t)return Math.round(u/t)+"m";if(o>=e)return Math.round(u/e)+"s";return u+"ms"}(s);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(s))}}function Rr(){if(_r)return br;return _r=1,br=function(e){function t(e){let r,u,o,i=null;function s(...e){if(!s.enabled)return;const n=s,u=Number(new Date),o=u-(r||u);n.diff=o,n.prev=r,n.curr=u,r=u,e[0]=t.coerce(e[0]),"string"!=typeof e[0]&&e.unshift("%O");let i=0;e[0]=e[0].replace(/%([a-zA-Z%])/g,((r,u)=>{if("%%"===r)return"%";i++;const o=t.formatters[u];if("function"==typeof o){const t=e[i];r=o.call(n,t),e.splice(i,1),i--}return r})),t.formatArgs.call(n,e);(n.log||t.log).apply(n,e)}return s.namespace=e,s.useColors=t.useColors(),s.color=t.selectColor(e),s.extend=n,s.destroy=t.destroy,Object.defineProperty(s,"enabled",{enumerable:!0,configurable:!1,get:()=>null!==i?i:(u!==t.namespaces&&(u=t.namespaces,o=t.enabled(e)),o),set:e=>{i=e}}),"function"==typeof t.init&&t.init(s),s}function n(e,n){const r=t(this.namespace+(void 0===n?":":n)+e);return r.log=this.log,r}function r(e){return e.toString().substring(2,e.toString().length-2).replace(/\.\*\?$/,"*")}return t.debug=t,t.default=t,t.coerce=function(e){if(e instanceof Error)return e.stack||e.message;return e},t.disable=function(){const e=[...t.names.map(r),...t.skips.map(r).map((e=>"-"+e))].join(",");return t.enable(""),e},t.enable=function(e){let n;t.save(e),t.namespaces=e,t.names=[],t.skips=[];const r=("string"==typeof e?e:"").split(/[\s,]+/),u=r.length;for(n=0;n{t[n]=e[n]})),t.names=[],t.skips=[],t.formatters={},t.selectColor=function(e){let n=0;for(let t=0;t{const n=e.startsWith("-")?"":1===e.length?"-":"--",r=t.indexOf(n+e),u=t.indexOf("--");return-1!==r&&(-1===u||r{}),"Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."),t.colors=[6,2,3,4,5,1];try{const e=function(){if($r)return jr;$r=1;const e=E.default,t=A.default,n=Vr(),{env:r}=process;let u;function o(e){return 0!==e&&{level:e,hasBasic:!0,has256:e>=2,has16m:e>=3}}function i(t,o){if(0===u)return 0;if(n("color=16m")||n("color=full")||n("color=truecolor"))return 3;if(n("color=256"))return 2;if(t&&!o&&void 0===u)return 0;const i=u||0;if("dumb"===r.TERM)return i;if("win32"===process.platform){const t=e.release().split(".");return Number(t[0])>=10&&Number(t[2])>=10586?Number(t[2])>=14931?3:2:1}if("CI"in r)return["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI","GITHUB_ACTIONS","BUILDKITE"].some((e=>e in r))||"codeship"===r.CI_NAME?1:i;if("TEAMCITY_VERSION"in r)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(r.TEAMCITY_VERSION)?1:0;if("truecolor"===r.COLORTERM)return 3;if("TERM_PROGRAM"in r){const e=parseInt((r.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(r.TERM_PROGRAM){case"iTerm.app":return e>=3?3:2;case"Apple_Terminal":return 2}}return/-256(color)?$/i.test(r.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(r.TERM)||"COLORTERM"in r?1:i}return n("no-color")||n("no-colors")||n("color=false")||n("color=never")?u=0:(n("color")||n("colors")||n("color=true")||n("color=always"))&&(u=1),"FORCE_COLOR"in r&&(u="true"===r.FORCE_COLOR?1:"false"===r.FORCE_COLOR?0:0===r.FORCE_COLOR.length?1:Math.min(parseInt(r.FORCE_COLOR,10),3)),jr={supportsColor:function(e){return o(i(e,e&&e.isTTY))},stdout:o(i(!0,t.isatty(1))),stderr:o(i(!0,t.isatty(2)))}}();e&&(e.stderr||e).level>=2&&(t.colors=[20,21,26,27,32,33,38,39,40,41,42,43,44,45,56,57,62,63,68,69,74,75,76,77,78,79,80,81,92,93,98,99,112,113,128,129,134,135,148,149,160,161,162,163,164,165,166,167,168,169,170,171,172,173,178,179,184,185,196,197,198,199,200,201,202,203,204,205,206,207,208,209,214,215,220,221])}catch(e){}t.inspectOpts=Object.keys(process.env).filter((e=>/^debug_/i.test(e))).reduce(((e,t)=>{const n=t.substring(6).toLowerCase().replace(/_([a-z])/g,((e,t)=>t.toUpperCase()));let r=process.env[t];return r=!!/^(yes|on|true|enabled)$/i.test(r)||!/^(no|off|false|disabled)$/i.test(r)&&("null"===r?null:Number(r)),e[n]=r,e}),{}),e.exports=Rr()(t);const{formatters:u}=e.exports;u.o=function(e){return this.inspectOpts.colors=this.useColors,r.inspect(e,this.inspectOpts).split("\n").map((e=>e.trim())).join(" ")},u.O=function(e){return this.inspectOpts.colors=this.useColors,r.inspect(e,this.inspectOpts)}}(Gr,Gr.exports)),Gr.exports}Jr=Nr,"undefined"==typeof process||"renderer"===process.type||!0===process.browser||process.__nwjs?Jr.exports=(Br||(Br=1,function(e,t){t.formatArgs=function(t){if(t[0]=(this.useColors?"%c":"")+this.namespace+(this.useColors?" %c":" ")+t[0]+(this.useColors?"%c ":" ")+"+"+e.exports.humanize(this.diff),!this.useColors)return;const n="color: "+this.color;t.splice(1,0,n,"color: inherit");let r=0,u=0;t[0].replace(/%[a-zA-Z%]/g,(e=>{"%%"!==e&&(r++,"%c"===e&&(u=r))})),t.splice(u,0,n)},t.save=function(e){try{e?t.storage.setItem("debug",e):t.storage.removeItem("debug")}catch(e){}},t.load=function(){let e;try{e=t.storage.getItem("debug")}catch(e){}return!e&&"undefined"!=typeof process&&"env"in process&&(e=process.env.DEBUG),e},t.useColors=function(){return!("undefined"==typeof window||!window.process||"renderer"!==window.process.type&&!window.process.__nwjs)||("undefined"==typeof navigator||!navigator.userAgent||!navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/))&&("undefined"!=typeof document&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||"undefined"!=typeof window&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||"undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&parseInt(RegExp.$1,10)>=31||"undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/))},t.storage=function(){try{return localStorage}catch(e){}}(),t.destroy=(()=>{let e=!1;return()=>{e||(e=!0,console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."))}})(),t.colors=["#0000CC","#0000FF","#0033CC","#0033FF","#0066CC","#0066FF","#0099CC","#0099FF","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#3300CC","#3300FF","#3333CC","#3333FF","#3366CC","#3366FF","#3399CC","#3399FF","#33CC00","#33CC33","#33CC66","#33CC99","#33CCCC","#33CCFF","#6600CC","#6600FF","#6633CC","#6633FF","#66CC00","#66CC33","#9900CC","#9900FF","#9933CC","#9933FF","#99CC00","#99CC33","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF","#CC6600","#CC6633","#CC9900","#CC9933","#CCCC00","#CCCC33","#FF0000","#FF0033","#FF0066","#FF0099","#FF00CC","#FF00FF","#FF3300","#FF3333","#FF3366","#FF3399","#FF33CC","#FF33FF","#FF6600","#FF6633","#FF9900","#FF9933","#FFCC00","#FFCC33"],t.log=console.debug||console.log||(()=>{}),e.exports=Rr()(t);const{formatters:n}=e.exports;n.j=function(e){try{return JSON.stringify(e)}catch(e){return"[UnexpectedJSONParseError]: "+e.message}}}(Ir,Ir.exports)),Ir.exports):Jr.exports=Ur();var Wr=function(e){return(e=e||{}).circles?function(e){var t=[],n=[];return e.proto?function e(u){if("object"!=typeof u||null===u)return u;if(u instanceof Date)return new Date(u);if(Array.isArray(u))return r(u,e);if(u instanceof Map)return new Map(r(Array.from(u),e));if(u instanceof Set)return new Set(r(Array.from(u),e));var o={};for(var i in t.push(u),n.push(o),u){var s=u[i];if("object"!=typeof s||null===s)o[i]=s;else if(s instanceof Date)o[i]=new Date(s);else if(s instanceof Map)o[i]=new Map(r(Array.from(s),e));else if(s instanceof Set)o[i]=new Set(r(Array.from(s),e));else if(ArrayBuffer.isView(s))o[i]=zr(s);else{var c=t.indexOf(s);o[i]=-1!==c?n[c]:e(s)}}return t.pop(),n.pop(),o}:function e(u){if("object"!=typeof u||null===u)return u;if(u instanceof Date)return new Date(u);if(Array.isArray(u))return r(u,e);if(u instanceof Map)return new Map(r(Array.from(u),e));if(u instanceof Set)return new Set(r(Array.from(u),e));var o={};for(var i in t.push(u),n.push(o),u)if(!1!==Object.hasOwnProperty.call(u,i)){var s=u[i];if("object"!=typeof s||null===s)o[i]=s;else if(s instanceof Date)o[i]=new Date(s);else if(s instanceof Map)o[i]=new Map(r(Array.from(s),e));else if(s instanceof Set)o[i]=new Set(r(Array.from(s),e));else if(ArrayBuffer.isView(s))o[i]=zr(s);else{var c=t.indexOf(s);o[i]=-1!==c?n[c]:e(s)}}return t.pop(),n.pop(),o};function r(e,r){for(var u=Object.keys(e),o=new Array(u.length),i=0;i!e,Qr=e=>e&&"object"==typeof e&&!Array.isArray(e),eu=(e,t,n)=>{(Array.isArray(t)?t:[t]).forEach((t=>{if(t)throw new Error(`Problem with log4js configuration: (${Kr.inspect(e,{depth:5})}) - ${n}`)}))};var tu={configure:e=>{qr("New configuration to be validated: ",e),eu(e,Zr(Qr(e)),"must be an object."),qr(`Calling pre-processing listeners (${Yr.length})`),Yr.forEach((t=>t(e))),qr("Configuration pre-processing finished."),qr(`Calling configuration listeners (${Xr.length})`),Xr.forEach((t=>t(e))),qr("Configuration finished.")},addListener:e=>{Xr.push(e),qr(`Added listener, now ${Xr.length} listeners`)},addPreProcessingListener:e=>{Yr.push(e),qr(`Added pre-processing listener, now ${Yr.length} listeners`)},throwExceptionIf:eu,anObject:Qr,anInteger:e=>e&&"number"==typeof e&&Number.isInteger(e),validIdentifier:e=>/^[A-Za-z][A-Za-z0-9_]*$/g.test(e),not:Zr},nu={exports:{}};!function(e){function t(e,t){for(var n=e.toString();n.length-1?s:c,l=n(u.getHours()),f=n(u.getMinutes()),d=n(u.getSeconds()),D=t(u.getMilliseconds(),3),p=function(e){var t=Math.abs(e),n=String(Math.floor(t/60)),r=String(t%60);return n=("0"+n).slice(-2),r=("0"+r).slice(-2),0===e?"Z":(e<0?"+":"-")+n+":"+r}(u.getTimezoneOffset());return r.replace(/dd/g,o).replace(/MM/g,i).replace(/y{1,4}/g,a).replace(/hh/g,l).replace(/mm/g,f).replace(/ss/g,d).replace(/SSS/g,D).replace(/O/g,p)}function u(e,t,n,r){e["set"+(r?"":"UTC")+t](n)}e.exports=r,e.exports.asString=r,e.exports.parse=function(t,n,r){if(!t)throw new Error("pattern must be supplied");return function(t,n,r){var o=t.indexOf("O")<0,i=!1,s=[{pattern:/y{1,4}/,regexp:"\\d{1,4}",fn:function(e,t){u(e,"FullYear",t,o)}},{pattern:/MM/,regexp:"\\d{1,2}",fn:function(e,t){u(e,"Month",t-1,o),e.getMonth()!==t-1&&(i=!0)}},{pattern:/dd/,regexp:"\\d{1,2}",fn:function(e,t){i&&u(e,"Month",e.getMonth()-1,o),u(e,"Date",t,o)}},{pattern:/hh/,regexp:"\\d{1,2}",fn:function(e,t){u(e,"Hours",t,o)}},{pattern:/mm/,regexp:"\\d\\d",fn:function(e,t){u(e,"Minutes",t,o)}},{pattern:/ss/,regexp:"\\d\\d",fn:function(e,t){u(e,"Seconds",t,o)}},{pattern:/SSS/,regexp:"\\d\\d\\d",fn:function(e,t){u(e,"Milliseconds",t,o)}},{pattern:/O/,regexp:"[+-]\\d{1,2}:?\\d{2}?|Z",fn:function(e,t){t="Z"===t?0:t.replace(":","");var n=Math.abs(t),r=(t>0?-1:1)*(n%100+60*Math.floor(n/100));e.setUTCMinutes(e.getUTCMinutes()+r)}}],c=s.reduce((function(e,t){return t.pattern.test(e.regexp)?(t.index=e.regexp.match(t.pattern).index,e.regexp=e.regexp.replace(t.pattern,"("+t.regexp+")")):t.index=-1,e}),{regexp:t,index:[]}),a=s.filter((function(e){return e.index>-1}));a.sort((function(e,t){return e.index-t.index}));var l=new RegExp(c.regexp).exec(n);if(l){var f=r||e.exports.now();return a.forEach((function(e,t){e.fn(f,l[t+1])})),f}throw new Error("String '"+n+"' could not be parsed as '"+t+"'")}(t,n,r)},e.exports.now=function(){return new Date},e.exports.ISO8601_FORMAT="yyyy-MM-ddThh:mm:ss.SSS",e.exports.ISO8601_WITH_TZ_OFFSET_FORMAT="yyyy-MM-ddThh:mm:ss.SSSO",e.exports.DATETIME_FORMAT="dd MM yyyy hh:mm:ss.SSS",e.exports.ABSOLUTETIME_FORMAT="hh:mm:ss.SSS"}(nu);const ru=nu.exports,uu=E.default,ou=F.default,iu=p.default,su={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[90,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[91,39],yellow:[33,39]};function cu(e){return e?`[${su[e][0]}m`:""}function au(e){return e?`[${su[e][1]}m`:""}function lu(e,t){return n=ou.format("[%s] [%s] %s - ",ru.asString(e.startTime),e.level.toString(),e.categoryName),cu(r=t)+n+au(r);var n,r}function fu(e){return lu(e)+ou.format(...e.data)}function du(e){return lu(e,e.level.colour)+ou.format(...e.data)}function Du(e){return ou.format(...e.data)}function pu(e){return e.data[0]}function Eu(e,t){const n=/%(-?[0-9]+)?(\.?-?[0-9]+)?([[\]cdhmnprzxXyflos%])(\{([^}]+)\})?|([^%]+)/;function r(e){return e&&e.pid?e.pid.toString():process.pid.toString()}e=e||"%r %p %c - %m%n";const u={c:function(e,t){let n=e.categoryName;if(t){const e=parseInt(t,10),r=n.split(".");ee&&(n=r.slice(-e).join(iu.sep))}return n},l:function(e){return e.lineNumber?`${e.lineNumber}`:""},o:function(e){return e.columnNumber?`${e.columnNumber}`:""},s:function(e){return e.callStack||""}};function o(e,t,n){return u[e](t,n)}function i(e,t,n){let r=e;return r=function(e,t){let n;return e?(n=parseInt(e.substr(1),10),n>0?t.slice(0,n):t.slice(n)):t}(t,r),r=function(e,t){let n;if(e)if("-"===e.charAt(0))for(n=parseInt(e.substr(1),10);t.lengthDu,basic:()=>fu,colored:()=>du,coloured:()=>du,pattern:e=>Eu(e&&e.pattern,e&&e.tokens),dummy:()=>pu};var hu={basicLayout:fu,messagePassThroughLayout:Du,patternLayout:Eu,colouredLayout:du,coloredLayout:du,dummyLayout:pu,addLayout(e,t){mu[e]=t},layout:(e,t)=>mu[e]&&mu[e](t)};const yu=tu,Cu=["white","grey","black","blue","cyan","green","magenta","red","yellow"];class Fu{constructor(e,t,n){this.level=e,this.levelStr=t,this.colour=n}toString(){return this.levelStr}static getLevel(e,t){return e?e instanceof Fu?e:(e instanceof Object&&e.levelStr&&(e=e.levelStr),Fu[e.toString().toUpperCase()]||t):t}static addLevels(e){if(e){Object.keys(e).forEach((t=>{const n=t.toUpperCase();Fu[n]=new Fu(e[t].value,n,e[t].colour);const r=Fu.levels.findIndex((e=>e.levelStr===n));r>-1?Fu.levels[r]=Fu[n]:Fu.levels.push(Fu[n])})),Fu.levels.sort(((e,t)=>e.level-t.level))}}isLessThanOrEqualTo(e){return"string"==typeof e&&(e=Fu.getLevel(e)),this.level<=e.level}isGreaterThanOrEqualTo(e){return"string"==typeof e&&(e=Fu.getLevel(e)),this.level>=e.level}isEqualTo(e){return"string"==typeof e&&(e=Fu.getLevel(e)),this.level===e.level}}Fu.levels=[],Fu.addLevels({ALL:{value:Number.MIN_VALUE,colour:"grey"},TRACE:{value:5e3,colour:"blue"},DEBUG:{value:1e4,colour:"cyan"},INFO:{value:2e4,colour:"green"},WARN:{value:3e4,colour:"yellow"},ERROR:{value:4e4,colour:"red"},FATAL:{value:5e4,colour:"magenta"},MARK:{value:9007199254740992,colour:"grey"},OFF:{value:Number.MAX_VALUE,colour:"grey"}}),yu.addListener((e=>{const t=e.levels;if(t){yu.throwExceptionIf(e,yu.not(yu.anObject(t)),"levels must be an object");Object.keys(t).forEach((n=>{yu.throwExceptionIf(e,yu.not(yu.validIdentifier(n)),`level name "${n}" is not a valid identifier (must start with a letter, only contain A-Z,a-z,0-9,_)`),yu.throwExceptionIf(e,yu.not(yu.anObject(t[n])),`level "${n}" must be an object`),yu.throwExceptionIf(e,yu.not(t[n].value),`level "${n}" must have a 'value' property`),yu.throwExceptionIf(e,yu.not(yu.anInteger(t[n].value)),`level "${n}".value must have an integer value`),yu.throwExceptionIf(e,yu.not(t[n].colour),`level "${n}" must have a 'colour' property`),yu.throwExceptionIf(e,yu.not(Cu.indexOf(t[n].colour)>-1),`level "${n}".colour must be one of ${Cu.join(", ")}`)}))}})),yu.addListener((e=>{Fu.addLevels(e.levels)}));var gu=Fu,Au={exports:{}},vu={};/*! (c) 2020 Andrea Giammarchi */ +const{parse:Su,stringify:wu}=JSON,{keys:Ou}=Object,bu=String,_u="string",Bu={},Pu="object",ku=(e,t)=>t,xu=e=>e instanceof bu?bu(e):e,Nu=(e,t)=>typeof t===_u?new bu(t):t,Iu=(e,t,n,r)=>{const u=[];for(let o=Ou(n),{length:i}=o,s=0;s{const r=bu(t.push(n)-1);return e.set(n,r),r},Ru=(e,t)=>{const n=Su(e,Nu).map(xu),r=n[0],u=t||ku,o=typeof r===Pu&&r?Iu(n,new Set,r,u):r;return u.call({"":o},"",o)};vu.parse=Ru;const Mu=(e,t,n)=>{const r=t&&typeof t===Pu?(e,n)=>""===e||-1Su(Mu(e));vu.fromJSON=e=>Ru(wu(e));const Lu=vu,ju=gu;class $u{constructor(e,t,n,r,u){this.startTime=new Date,this.categoryName=e,this.data=n,this.level=t,this.context=Object.assign({},r),this.pid=process.pid,u&&(this.functionName=u.functionName,this.fileName=u.fileName,this.lineNumber=u.lineNumber,this.columnNumber=u.columnNumber,this.callStack=u.callStack)}serialise(){const e=this.data.map((e=>(e&&e.message&&e.stack&&(e=Object.assign({message:e.message,stack:e.stack},e)),e)));return this.data=e,Lu.stringify(this)}static deserialise(e){let t;try{const n=Lu.parse(e);n.data=n.data.map((e=>{if(e&&e.message&&e.stack){const t=new Error(e);Object.keys(e).forEach((n=>{t[n]=e[n]})),e=t}return e})),t=new $u(n.categoryName,ju.getLevel(n.level.levelStr),n.data,n.context),t.startTime=new Date(n.startTime),t.pid=n.pid,t.cluster=n.cluster}catch(n){t=new $u("log4js",ju.ERROR,["Unable to parse log:",e,"because: ",n])}return t}}var Hu=$u;const Ju=Nr.exports("log4js:clustering"),Gu=Hu,Vu=tu;let Uu=!1,Wu=null;try{Wu=require("cluster")}catch(e){Ju("cluster module not present"),Uu=!0}const zu=[];let Ku=!1,qu="NODE_APP_INSTANCE";const Yu=()=>Ku&&"0"===process.env[qu],Xu=()=>Uu||Wu.isMaster||Yu(),Zu=e=>{zu.forEach((t=>t(e)))},Qu=(e,t)=>{if(Ju("cluster message received from worker ",e,": ",t),e.topic&&e.data&&(t=e,e=void 0),t&&t.topic&&"log4js:message"===t.topic){Ju("received message: ",t.data);const e=Gu.deserialise(t.data);Zu(e)}};Uu||Vu.addListener((e=>{zu.length=0,({pm2:Ku,disableClustering:Uu,pm2InstanceVar:qu="NODE_APP_INSTANCE"}=e),Ju(`clustering disabled ? ${Uu}`),Ju(`cluster.isMaster ? ${Wu&&Wu.isMaster}`),Ju(`pm2 enabled ? ${Ku}`),Ju(`pm2InstanceVar = ${qu}`),Ju(`process.env[${qu}] = ${process.env[qu]}`),Ku&&process.removeListener("message",Qu),Wu&&Wu.removeListener&&Wu.removeListener("message",Qu),Uu||e.disableClustering?Ju("Not listening for cluster messages, because clustering disabled."):Yu()?(Ju("listening for PM2 broadcast messages"),process.on("message",Qu)):Wu.isMaster?(Ju("listening for cluster messages"),Wu.on("message",Qu)):Ju("not listening for messages, because we are not a master process")}));var eo={onlyOnMaster:(e,t)=>Xu()?e():t,isMaster:Xu,send:e=>{Xu()?Zu(e):(Ku||(e.cluster={workerId:Wu.worker.id,worker:process.pid}),process.send({topic:"log4js:message",data:e.serialise()}))},onMessage:e=>{zu.push(e)}},to={};function no(e){if("number"==typeof e&&Number.isInteger(e))return e;const t={K:1024,M:1048576,G:1073741824},n=Object.keys(t),r=e.substr(e.length-1).toLocaleUpperCase(),u=e.substring(0,e.length-1).trim();if(n.indexOf(r)<0||!Number.isInteger(Number(u)))throw Error(`maxLogSize: "${e}" is invalid`);return u*t[r]}function ro(e){return function(e,t){const n=Object.assign({},t);return Object.keys(e).forEach((r=>{n[r]&&(n[r]=e[r](t[r]))})),n}({maxLogSize:no},e)}const uo={file:ro,fileSync:ro};to.modifyConfig=e=>uo[e.type]?uo[e.type](e):e;var oo={};const io=console.log.bind(console);oo.configure=function(e,t){let n=t.colouredLayout;return e.layout&&(n=t.layout(e.layout.type,e.layout)),function(e,t){return n=>{io(e(n,t))}}(n,e.timezoneOffset)};var so={};so.configure=function(e,t){let n=t.colouredLayout;return e.layout&&(n=t.layout(e.layout.type,e.layout)),function(e,t){return n=>{process.stdout.write(`${e(n,t)}\n`)}}(n,e.timezoneOffset)};var co={};co.configure=function(e,t){let n=t.colouredLayout;return e.layout&&(n=t.layout(e.layout.type,e.layout)),function(e,t){return n=>{process.stderr.write(`${e(n,t)}\n`)}}(n,e.timezoneOffset)};var ao={};ao.configure=function(e,t,n,r){const u=n(e.appender);return function(e,t,n,r){const u=r.getLevel(e),o=r.getLevel(t,r.FATAL);return e=>{const t=e.level;t.isGreaterThanOrEqualTo(u)&&t.isLessThanOrEqualTo(o)&&n(e)}}(e.level,e.maxLevel,u,r)};var lo={};const fo=Nr.exports("log4js:categoryFilter");lo.configure=function(e,t,n){const r=n(e.appender);return function(e,t){return"string"==typeof e&&(e=[e]),n=>{fo(`Checking ${n.categoryName} against ${e}`),-1===e.indexOf(n.categoryName)&&(fo("Not excluded, sending to appender"),t(n))}}(e.exclude,r)};var Do={};const po=Nr.exports("log4js:noLogFilter");Do.configure=function(e,t,n){const r=n(e.appender);return function(e,t){return n=>{po(`Checking data: ${n.data} against filters: ${e}`),"string"==typeof e&&(e=[e]),e=e.filter((e=>null!=e&&""!==e));const r=new RegExp(e.join("|"),"i");(0===e.length||n.data.findIndex((e=>r.test(e)))<0)&&(po("Not excluded, sending to appender"),t(n))}}(e.exclude,r)};var Eo={},mo={exports:{}},ho={},yo={fromCallback:function(e){return Object.defineProperty((function(){if("function"!=typeof arguments[arguments.length-1])return new Promise(((t,n)=>{arguments[arguments.length]=(e,r)=>{if(e)return n(e);t(r)},arguments.length++,e.apply(this,arguments)}));e.apply(this,arguments)}),"name",{value:e.name})},fromPromise:function(e){return Object.defineProperty((function(){const t=arguments[arguments.length-1];if("function"!=typeof t)return e.apply(this,arguments);e.apply(this,arguments).then((e=>t(null,e)),t)}),"name",{value:e.name})}};!function(e){const t=yo.fromCallback,n=we,r=["access","appendFile","chmod","chown","close","copyFile","fchmod","fchown","fdatasync","fstat","fsync","ftruncate","futimes","lchown","lchmod","link","lstat","mkdir","mkdtemp","open","readFile","readdir","readlink","realpath","rename","rmdir","stat","symlink","truncate","unlink","utimes","writeFile"].filter((e=>"function"==typeof n[e]));Object.keys(n).forEach((t=>{"promises"!==t&&(e[t]=n[t])})),r.forEach((r=>{e[r]=t(n[r])})),e.exists=function(e,t){return"function"==typeof t?n.exists(e,t):new Promise((t=>n.exists(e,t)))},e.read=function(e,t,r,u,o,i){return"function"==typeof i?n.read(e,t,r,u,o,i):new Promise(((i,s)=>{n.read(e,t,r,u,o,((e,t,n)=>{if(e)return s(e);i({bytesRead:t,buffer:n})}))}))},e.write=function(e,t,...r){return"function"==typeof r[r.length-1]?n.write(e,t,...r):new Promise(((u,o)=>{n.write(e,t,...r,((e,t,n)=>{if(e)return o(e);u({bytesWritten:t,buffer:n})}))}))},"function"==typeof n.realpath.native&&(e.realpath.native=t(n.realpath.native))}(ho);const Co=p.default;function Fo(e){return(e=Co.normalize(Co.resolve(e)).split(Co.sep)).length>0?e[0]:null}const go=/[<>:"|?*]/;var Ao=function(e){const t=Fo(e);return e=e.replace(t,""),go.test(e)};const vo=we,So=p.default,wo=Ao,Oo=parseInt("0777",8);var bo=function e(t,n,r,u){if("function"==typeof n?(r=n,n={}):n&&"object"==typeof n||(n={mode:n}),"win32"===process.platform&&wo(t)){const e=new Error(t+" contains invalid WIN32 path characters.");return e.code="EINVAL",r(e)}let o=n.mode;const i=n.fs||vo;void 0===o&&(o=Oo&~process.umask()),u||(u=null),r=r||function(){},t=So.resolve(t),i.mkdir(t,o,(o=>{if(!o)return r(null,u=u||t);if("ENOENT"===o.code){if(So.dirname(t)===t)return r(o);e(So.dirname(t),n,((u,o)=>{u?r(u,o):e(t,n,r,o)}))}else i.stat(t,((e,t)=>{e||!t.isDirectory()?r(o,u):r(null,u)}))}))};const _o=we,Bo=p.default,Po=Ao,ko=parseInt("0777",8);var xo=function e(t,n,r){n&&"object"==typeof n||(n={mode:n});let u=n.mode;const o=n.fs||_o;if("win32"===process.platform&&Po(t)){const e=new Error(t+" contains invalid WIN32 path characters.");throw e.code="EINVAL",e}void 0===u&&(u=ko&~process.umask()),r||(r=null),t=Bo.resolve(t);try{o.mkdirSync(t,u),r=r||t}catch(u){if("ENOENT"===u.code){if(Bo.dirname(t)===t)throw u;r=e(Bo.dirname(t),n,r),e(t,n,r)}else{let e;try{e=o.statSync(t)}catch(e){throw u}if(!e.isDirectory())throw u}}return r};const No=(0,yo.fromCallback)(bo);var Io={mkdirs:No,mkdirsSync:xo,mkdirp:No,mkdirpSync:xo,ensureDir:No,ensureDirSync:xo};const To=we;E.default,p.default;var Ro=function(e,t,n,r){To.open(e,"r+",((e,u)=>{if(e)return r(e);To.futimes(u,t,n,(e=>{To.close(u,(t=>{r&&r(e||t)}))}))}))},Mo=function(e,t,n){const r=To.openSync(e,"r+");return To.futimesSync(r,t,n),To.closeSync(r)};const Lo=we,jo=p.default,$o=10,Ho=5,Jo=0,Go=process.versions.node.split("."),Vo=Number.parseInt(Go[0],10),Uo=Number.parseInt(Go[1],10),Wo=Number.parseInt(Go[2],10);function zo(){if(Vo>$o)return!0;if(Vo===$o){if(Uo>Ho)return!0;if(Uo===Ho&&Wo>=Jo)return!0}return!1}function Ko(e,t){const n=jo.resolve(e).split(jo.sep).filter((e=>e)),r=jo.resolve(t).split(jo.sep).filter((e=>e));return n.reduce(((e,t,n)=>e&&r[n]===t),!0)}function qo(e,t,n){return`Cannot ${n} '${e}' to a subdirectory of itself, '${t}'.`}var Yo,Xo,Zo={checkPaths:function(e,t,n,r){!function(e,t,n){zo()?Lo.stat(e,{bigint:!0},((e,r)=>{if(e)return n(e);Lo.stat(t,{bigint:!0},((e,t)=>e?"ENOENT"===e.code?n(null,{srcStat:r,destStat:null}):n(e):n(null,{srcStat:r,destStat:t})))})):Lo.stat(e,((e,r)=>{if(e)return n(e);Lo.stat(t,((e,t)=>e?"ENOENT"===e.code?n(null,{srcStat:r,destStat:null}):n(e):n(null,{srcStat:r,destStat:t})))}))}(e,t,((u,o)=>{if(u)return r(u);const{srcStat:i,destStat:s}=o;return s&&s.ino&&s.dev&&s.ino===i.ino&&s.dev===i.dev?r(new Error("Source and destination must not be the same.")):i.isDirectory()&&Ko(e,t)?r(new Error(qo(e,t,n))):r(null,{srcStat:i,destStat:s})}))},checkPathsSync:function(e,t,n){const{srcStat:r,destStat:u}=function(e,t){let n,r;n=zo()?Lo.statSync(e,{bigint:!0}):Lo.statSync(e);try{r=zo()?Lo.statSync(t,{bigint:!0}):Lo.statSync(t)}catch(e){if("ENOENT"===e.code)return{srcStat:n,destStat:null};throw e}return{srcStat:n,destStat:r}}(e,t);if(u&&u.ino&&u.dev&&u.ino===r.ino&&u.dev===r.dev)throw new Error("Source and destination must not be the same.");if(r.isDirectory()&&Ko(e,t))throw new Error(qo(e,t,n));return{srcStat:r,destStat:u}},checkParentPaths:function e(t,n,r,u,o){const i=jo.resolve(jo.dirname(t)),s=jo.resolve(jo.dirname(r));if(s===i||s===jo.parse(s).root)return o();zo()?Lo.stat(s,{bigint:!0},((i,c)=>i?"ENOENT"===i.code?o():o(i):c.ino&&c.dev&&c.ino===n.ino&&c.dev===n.dev?o(new Error(qo(t,r,u))):e(t,n,s,u,o))):Lo.stat(s,((i,c)=>i?"ENOENT"===i.code?o():o(i):c.ino&&c.dev&&c.ino===n.ino&&c.dev===n.dev?o(new Error(qo(t,r,u))):e(t,n,s,u,o)))},checkParentPathsSync:function e(t,n,r,u){const o=jo.resolve(jo.dirname(t)),i=jo.resolve(jo.dirname(r));if(i===o||i===jo.parse(i).root)return;let s;try{s=zo()?Lo.statSync(i,{bigint:!0}):Lo.statSync(i)}catch(e){if("ENOENT"===e.code)return;throw e}if(s.ino&&s.dev&&s.ino===n.ino&&s.dev===n.dev)throw new Error(qo(t,r,u));return e(t,n,i,u)},isSrcSubdir:Ko};const Qo=we,ei=p.default,ti=Io.mkdirsSync,ni=Mo,ri=Zo;function ui(e,t,n,r){if(!r.filter||r.filter(t,n))return function(e,t,n,r){const u=r.dereference?Qo.statSync:Qo.lstatSync,o=u(t);if(o.isDirectory())return function(e,t,n,r,u){if(!t)return function(e,t,n,r){return Qo.mkdirSync(n),ii(t,n,r),Qo.chmodSync(n,e.mode)}(e,n,r,u);if(t&&!t.isDirectory())throw new Error(`Cannot overwrite non-directory '${r}' with directory '${n}'.`);return ii(n,r,u)}(o,e,t,n,r);if(o.isFile()||o.isCharacterDevice()||o.isBlockDevice())return function(e,t,n,r,u){return t?function(e,t,n,r){if(r.overwrite)return Qo.unlinkSync(n),oi(e,t,n,r);if(r.errorOnExist)throw new Error(`'${n}' already exists`)}(e,n,r,u):oi(e,n,r,u)}(o,e,t,n,r);if(o.isSymbolicLink())return function(e,t,n,r){let u=Qo.readlinkSync(t);r.dereference&&(u=ei.resolve(process.cwd(),u));if(e){let e;try{e=Qo.readlinkSync(n)}catch(e){if("EINVAL"===e.code||"UNKNOWN"===e.code)return Qo.symlinkSync(u,n);throw e}if(r.dereference&&(e=ei.resolve(process.cwd(),e)),ri.isSrcSubdir(u,e))throw new Error(`Cannot copy '${u}' to a subdirectory of itself, '${e}'.`);if(Qo.statSync(n).isDirectory()&&ri.isSrcSubdir(e,u))throw new Error(`Cannot overwrite '${e}' with '${u}'.`);return function(e,t){return Qo.unlinkSync(t),Qo.symlinkSync(e,t)}(u,n)}return Qo.symlinkSync(u,n)}(e,t,n,r)}(e,t,n,r)}function oi(e,t,n,r){return"function"==typeof Qo.copyFileSync?(Qo.copyFileSync(t,n),Qo.chmodSync(n,e.mode),r.preserveTimestamps?ni(n,e.atime,e.mtime):void 0):function(e,t,n,r){const u=65536,o=(Xo?Yo:(Xo=1,Yo=function(e){if("function"==typeof Buffer.allocUnsafe)try{return Buffer.allocUnsafe(e)}catch(t){return new Buffer(e)}return new Buffer(e)}))(u),i=Qo.openSync(t,"r"),s=Qo.openSync(n,"w",e.mode);let c=0;for(;cfunction(e,t,n,r){const u=ei.join(t,e),o=ei.join(n,e),{destStat:i}=ri.checkPathsSync(u,o,"copy");return ui(i,u,o,r)}(r,e,t,n)))}var si=function(e,t,n){"function"==typeof n&&(n={filter:n}),(n=n||{}).clobber=!("clobber"in n)||!!n.clobber,n.overwrite="overwrite"in n?!!n.overwrite:n.clobber,n.preserveTimestamps&&"ia32"===process.arch&&console.warn("fs-extra: Using the preserveTimestamps option in 32-bit node is not recommended;\n\n see https://github.com/jprichardson/node-fs-extra/issues/269");const{srcStat:r,destStat:u}=ri.checkPathsSync(e,t,"copy");return ri.checkParentPathsSync(e,r,t,"copy"),function(e,t,n,r){if(r.filter&&!r.filter(t,n))return;const u=ei.dirname(n);Qo.existsSync(u)||ti(u);return ui(e,t,n,r)}(u,e,t,n)},ci={copySync:si};const ai=yo.fromPromise,li=ho;var fi={pathExists:ai((function(e){return li.access(e).then((()=>!0)).catch((()=>!1))})),pathExistsSync:li.existsSync};const di=we,Di=p.default,pi=Io.mkdirs,Ei=fi.pathExists,mi=Ro,hi=Zo;function yi(e,t,n,r,u){const o=Di.dirname(n);Ei(o,((i,s)=>i?u(i):s?Fi(e,t,n,r,u):void pi(o,(o=>o?u(o):Fi(e,t,n,r,u)))))}function Ci(e,t,n,r,u,o){Promise.resolve(u.filter(n,r)).then((i=>i?e(t,n,r,u,o):o()),(e=>o(e)))}function Fi(e,t,n,r,u){return r.filter?Ci(gi,e,t,n,r,u):gi(e,t,n,r,u)}function gi(e,t,n,r,u){(r.dereference?di.stat:di.lstat)(t,((o,i)=>o?u(o):i.isDirectory()?function(e,t,n,r,u,o){if(!t)return function(e,t,n,r,u){di.mkdir(n,(o=>{if(o)return u(o);Si(t,n,r,(t=>t?u(t):di.chmod(n,e.mode,u)))}))}(e,n,r,u,o);if(t&&!t.isDirectory())return o(new Error(`Cannot overwrite non-directory '${r}' with directory '${n}'.`));return Si(n,r,u,o)}(i,e,t,n,r,u):i.isFile()||i.isCharacterDevice()||i.isBlockDevice()?function(e,t,n,r,u,o){return t?function(e,t,n,r,u){if(!r.overwrite)return r.errorOnExist?u(new Error(`'${n}' already exists`)):u();di.unlink(n,(o=>o?u(o):Ai(e,t,n,r,u)))}(e,n,r,u,o):Ai(e,n,r,u,o)}(i,e,t,n,r,u):i.isSymbolicLink()?function(e,t,n,r,u){di.readlink(t,((t,o)=>t?u(t):(r.dereference&&(o=Di.resolve(process.cwd(),o)),e?void di.readlink(n,((t,i)=>t?"EINVAL"===t.code||"UNKNOWN"===t.code?di.symlink(o,n,u):u(t):(r.dereference&&(i=Di.resolve(process.cwd(),i)),hi.isSrcSubdir(o,i)?u(new Error(`Cannot copy '${o}' to a subdirectory of itself, '${i}'.`)):e.isDirectory()&&hi.isSrcSubdir(i,o)?u(new Error(`Cannot overwrite '${i}' with '${o}'.`)):function(e,t,n){di.unlink(t,(r=>r?n(r):di.symlink(e,t,n)))}(o,n,u)))):di.symlink(o,n,u))))}(e,t,n,r,u):void 0))}function Ai(e,t,n,r,u){return"function"==typeof di.copyFile?di.copyFile(t,n,(t=>t?u(t):vi(e,n,r,u))):function(e,t,n,r,u){const o=di.createReadStream(t);o.on("error",(e=>u(e))).once("open",(()=>{const t=di.createWriteStream(n,{mode:e.mode});t.on("error",(e=>u(e))).on("open",(()=>o.pipe(t))).once("close",(()=>vi(e,n,r,u)))}))}(e,t,n,r,u)}function vi(e,t,n,r){di.chmod(t,e.mode,(u=>u?r(u):n.preserveTimestamps?mi(t,e.atime,e.mtime,r):r()))}function Si(e,t,n,r){di.readdir(e,((u,o)=>u?r(u):wi(o,e,t,n,r)))}function wi(e,t,n,r,u){const o=e.pop();return o?function(e,t,n,r,u,o){const i=Di.join(n,t),s=Di.join(r,t);hi.checkPaths(i,s,"copy",((t,c)=>{if(t)return o(t);const{destStat:a}=c;Fi(a,i,s,u,(t=>t?o(t):wi(e,n,r,u,o)))}))}(e,o,t,n,r,u):u()}var Oi=function(e,t,n,r){"function"!=typeof n||r?"function"==typeof n&&(n={filter:n}):(r=n,n={}),r=r||function(){},(n=n||{}).clobber=!("clobber"in n)||!!n.clobber,n.overwrite="overwrite"in n?!!n.overwrite:n.clobber,n.preserveTimestamps&&"ia32"===process.arch&&console.warn("fs-extra: Using the preserveTimestamps option in 32-bit node is not recommended;\n\n see https://github.com/jprichardson/node-fs-extra/issues/269"),hi.checkPaths(e,t,"copy",((u,o)=>{if(u)return r(u);const{srcStat:i,destStat:s}=o;hi.checkParentPaths(e,i,t,"copy",(u=>u?r(u):n.filter?Ci(yi,s,e,t,n,r):yi(s,e,t,n,r)))}))};var bi={copy:(0,yo.fromCallback)(Oi)};const _i=we,Bi=p.default,Pi=g.default,ki="win32"===process.platform;function xi(e){["unlink","chmod","stat","lstat","rmdir","readdir"].forEach((t=>{e[t]=e[t]||_i[t],e[t+="Sync"]=e[t]||_i[t]})),e.maxBusyTries=e.maxBusyTries||3}function Ni(e,t,n){let r=0;"function"==typeof t&&(n=t,t={}),Pi(e,"rimraf: missing path"),Pi.strictEqual(typeof e,"string","rimraf: path should be a string"),Pi.strictEqual(typeof n,"function","rimraf: callback function required"),Pi(t,"rimraf: invalid options argument provided"),Pi.strictEqual(typeof t,"object","rimraf: options should be object"),xi(t),Ii(e,t,(function u(o){if(o){if(("EBUSY"===o.code||"ENOTEMPTY"===o.code||"EPERM"===o.code)&&rIi(e,t,u)),100*r)}"ENOENT"===o.code&&(o=null)}n(o)}))}function Ii(e,t,n){Pi(e),Pi(t),Pi("function"==typeof n),t.lstat(e,((r,u)=>r&&"ENOENT"===r.code?n(null):r&&"EPERM"===r.code&&ki?Ti(e,t,r,n):u&&u.isDirectory()?Mi(e,t,r,n):void t.unlink(e,(r=>{if(r){if("ENOENT"===r.code)return n(null);if("EPERM"===r.code)return ki?Ti(e,t,r,n):Mi(e,t,r,n);if("EISDIR"===r.code)return Mi(e,t,r,n)}return n(r)}))))}function Ti(e,t,n,r){Pi(e),Pi(t),Pi("function"==typeof r),n&&Pi(n instanceof Error),t.chmod(e,438,(u=>{u?r("ENOENT"===u.code?null:n):t.stat(e,((u,o)=>{u?r("ENOENT"===u.code?null:n):o.isDirectory()?Mi(e,t,n,r):t.unlink(e,r)}))}))}function Ri(e,t,n){let r;Pi(e),Pi(t),n&&Pi(n instanceof Error);try{t.chmodSync(e,438)}catch(e){if("ENOENT"===e.code)return;throw n}try{r=t.statSync(e)}catch(e){if("ENOENT"===e.code)return;throw n}r.isDirectory()?ji(e,t,n):t.unlinkSync(e)}function Mi(e,t,n,r){Pi(e),Pi(t),n&&Pi(n instanceof Error),Pi("function"==typeof r),t.rmdir(e,(u=>{!u||"ENOTEMPTY"!==u.code&&"EEXIST"!==u.code&&"EPERM"!==u.code?u&&"ENOTDIR"===u.code?r(n):r(u):function(e,t,n){Pi(e),Pi(t),Pi("function"==typeof n),t.readdir(e,((r,u)=>{if(r)return n(r);let o,i=u.length;if(0===i)return t.rmdir(e,n);u.forEach((r=>{Ni(Bi.join(e,r),t,(r=>{if(!o)return r?n(o=r):void(0==--i&&t.rmdir(e,n))}))}))}))}(e,t,r)}))}function Li(e,t){let n;xi(t=t||{}),Pi(e,"rimraf: missing path"),Pi.strictEqual(typeof e,"string","rimraf: path should be a string"),Pi(t,"rimraf: missing options"),Pi.strictEqual(typeof t,"object","rimraf: options should be object");try{n=t.lstatSync(e)}catch(n){if("ENOENT"===n.code)return;"EPERM"===n.code&&ki&&Ri(e,t,n)}try{n&&n.isDirectory()?ji(e,t,null):t.unlinkSync(e)}catch(n){if("ENOENT"===n.code)return;if("EPERM"===n.code)return ki?Ri(e,t,n):ji(e,t,n);if("EISDIR"!==n.code)throw n;ji(e,t,n)}}function ji(e,t,n){Pi(e),Pi(t),n&&Pi(n instanceof Error);try{t.rmdirSync(e)}catch(r){if("ENOTDIR"===r.code)throw n;if("ENOTEMPTY"===r.code||"EEXIST"===r.code||"EPERM"===r.code)!function(e,t){if(Pi(e),Pi(t),t.readdirSync(e).forEach((n=>Li(Bi.join(e,n),t))),!ki){return t.rmdirSync(e,t)}{const n=Date.now();do{try{return t.rmdirSync(e,t)}catch(e){}}while(Date.now()-n<500)}}(e,t);else if("ENOENT"!==r.code)throw r}}var $i=Ni;Ni.sync=Li;const Hi=$i;var Ji={remove:(0,yo.fromCallback)(Hi),removeSync:Hi.sync};const Gi=yo.fromCallback,Vi=we,Ui=p.default,Wi=Io,zi=Ji,Ki=Gi((function(e,t){t=t||function(){},Vi.readdir(e,((n,r)=>{if(n)return Wi.mkdirs(e,t);r=r.map((t=>Ui.join(e,t))),function e(){const n=r.pop();if(!n)return t();zi.remove(n,(n=>{if(n)return t(n);e()}))}()}))}));function qi(e){let t;try{t=Vi.readdirSync(e)}catch(t){return Wi.mkdirsSync(e)}t.forEach((t=>{t=Ui.join(e,t),zi.removeSync(t)}))}var Yi={emptyDirSync:qi,emptydirSync:qi,emptyDir:Ki,emptydir:Ki};const Xi=yo.fromCallback,Zi=p.default,Qi=we,es=Io,ts=fi.pathExists;var ns={createFile:Xi((function(e,t){function n(){Qi.writeFile(e,"",(e=>{if(e)return t(e);t()}))}Qi.stat(e,((r,u)=>{if(!r&&u.isFile())return t();const o=Zi.dirname(e);ts(o,((e,r)=>e?t(e):r?n():void es.mkdirs(o,(e=>{if(e)return t(e);n()}))))}))})),createFileSync:function(e){let t;try{t=Qi.statSync(e)}catch(e){}if(t&&t.isFile())return;const n=Zi.dirname(e);Qi.existsSync(n)||es.mkdirsSync(n),Qi.writeFileSync(e,"")}};const rs=yo.fromCallback,us=p.default,os=we,is=Io,ss=fi.pathExists;var cs={createLink:rs((function(e,t,n){function r(e,t){os.link(e,t,(e=>{if(e)return n(e);n(null)}))}ss(t,((u,o)=>u?n(u):o?n(null):void os.lstat(e,(u=>{if(u)return u.message=u.message.replace("lstat","ensureLink"),n(u);const o=us.dirname(t);ss(o,((u,i)=>u?n(u):i?r(e,t):void is.mkdirs(o,(u=>{if(u)return n(u);r(e,t)}))))}))))})),createLinkSync:function(e,t){if(os.existsSync(t))return;try{os.lstatSync(e)}catch(e){throw e.message=e.message.replace("lstat","ensureLink"),e}const n=us.dirname(t);return os.existsSync(n)||is.mkdirsSync(n),os.linkSync(e,t)}};const as=p.default,ls=we,fs=fi.pathExists;var ds={symlinkPaths:function(e,t,n){if(as.isAbsolute(e))return ls.lstat(e,(t=>t?(t.message=t.message.replace("lstat","ensureSymlink"),n(t)):n(null,{toCwd:e,toDst:e})));{const r=as.dirname(t),u=as.join(r,e);return fs(u,((t,o)=>t?n(t):o?n(null,{toCwd:u,toDst:e}):ls.lstat(e,(t=>t?(t.message=t.message.replace("lstat","ensureSymlink"),n(t)):n(null,{toCwd:e,toDst:as.relative(r,e)})))))}},symlinkPathsSync:function(e,t){let n;if(as.isAbsolute(e)){if(n=ls.existsSync(e),!n)throw new Error("absolute srcpath does not exist");return{toCwd:e,toDst:e}}{const r=as.dirname(t),u=as.join(r,e);if(n=ls.existsSync(u),n)return{toCwd:u,toDst:e};if(n=ls.existsSync(e),!n)throw new Error("relative srcpath does not exist");return{toCwd:e,toDst:as.relative(r,e)}}}};const Ds=we;var ps={symlinkType:function(e,t,n){if(n="function"==typeof t?t:n,t="function"!=typeof t&&t)return n(null,t);Ds.lstat(e,((e,r)=>{if(e)return n(null,"file");t=r&&r.isDirectory()?"dir":"file",n(null,t)}))},symlinkTypeSync:function(e,t){let n;if(t)return t;try{n=Ds.lstatSync(e)}catch(e){return"file"}return n&&n.isDirectory()?"dir":"file"}};const Es=yo.fromCallback,ms=p.default,hs=we,ys=Io.mkdirs,Cs=Io.mkdirsSync,Fs=ds.symlinkPaths,gs=ds.symlinkPathsSync,As=ps.symlinkType,vs=ps.symlinkTypeSync,Ss=fi.pathExists;var ws={createSymlink:Es((function(e,t,n,r){r="function"==typeof n?n:r,n="function"!=typeof n&&n,Ss(t,((u,o)=>u?r(u):o?r(null):void Fs(e,t,((u,o)=>{if(u)return r(u);e=o.toDst,As(o.toCwd,n,((n,u)=>{if(n)return r(n);const o=ms.dirname(t);Ss(o,((n,i)=>n?r(n):i?hs.symlink(e,t,u,r):void ys(o,(n=>{if(n)return r(n);hs.symlink(e,t,u,r)}))))}))}))))})),createSymlinkSync:function(e,t,n){if(hs.existsSync(t))return;const r=gs(e,t);e=r.toDst,n=vs(r.toCwd,n);const u=ms.dirname(t);return hs.existsSync(u)||Cs(u),hs.symlinkSync(e,t,n)}};var Os,bs={createFile:ns.createFile,createFileSync:ns.createFileSync,ensureFile:ns.createFile,ensureFileSync:ns.createFileSync,createLink:cs.createLink,createLinkSync:cs.createLinkSync,ensureLink:cs.createLink,ensureLinkSync:cs.createLinkSync,createSymlink:ws.createSymlink,createSymlinkSync:ws.createSymlinkSync,ensureSymlink:ws.createSymlink,ensureSymlinkSync:ws.createSymlinkSync};try{Os=we}catch(e){Os=D.default}function _s(e,t){var n,r="\n";return"object"==typeof t&&null!==t&&(t.spaces&&(n=t.spaces),t.EOL&&(r=t.EOL)),JSON.stringify(e,t?t.replacer:null,n).replace(/\n/g,r)+r}function Bs(e){return Buffer.isBuffer(e)&&(e=e.toString("utf8")),e=e.replace(/^\uFEFF/,"")}var Ps={readFile:function(e,t,n){null==n&&(n=t,t={}),"string"==typeof t&&(t={encoding:t});var r=(t=t||{}).fs||Os,u=!0;"throws"in t&&(u=t.throws),r.readFile(e,t,(function(r,o){if(r)return n(r);var i;o=Bs(o);try{i=JSON.parse(o,t?t.reviver:null)}catch(t){return u?(t.message=e+": "+t.message,n(t)):n(null,null)}n(null,i)}))},readFileSync:function(e,t){"string"==typeof(t=t||{})&&(t={encoding:t});var n=t.fs||Os,r=!0;"throws"in t&&(r=t.throws);try{var u=n.readFileSync(e,t);return u=Bs(u),JSON.parse(u,t.reviver)}catch(t){if(r)throw t.message=e+": "+t.message,t;return null}},writeFile:function(e,t,n,r){null==r&&(r=n,n={});var u=(n=n||{}).fs||Os,o="";try{o=_s(t,n)}catch(e){return void(r&&r(e,null))}u.writeFile(e,o,n,r)},writeFileSync:function(e,t,n){var r=(n=n||{}).fs||Os,u=_s(t,n);return r.writeFileSync(e,u,n)}},ks=Ps;const xs=yo.fromCallback,Ns=ks;var Is={readJson:xs(Ns.readFile),readJsonSync:Ns.readFileSync,writeJson:xs(Ns.writeFile),writeJsonSync:Ns.writeFileSync};const Ts=p.default,Rs=Io,Ms=fi.pathExists,Ls=Is;var js=function(e,t,n,r){"function"==typeof n&&(r=n,n={});const u=Ts.dirname(e);Ms(u,((o,i)=>o?r(o):i?Ls.writeJson(e,t,n,r):void Rs.mkdirs(u,(u=>{if(u)return r(u);Ls.writeJson(e,t,n,r)}))))};const $s=we,Hs=p.default,Js=Io,Gs=Is;var Vs=function(e,t,n){const r=Hs.dirname(e);$s.existsSync(r)||Js.mkdirsSync(r),Gs.writeJsonSync(e,t,n)};const Us=yo.fromCallback,Ws=Is;Ws.outputJson=Us(js),Ws.outputJsonSync=Vs,Ws.outputJSON=Ws.outputJson,Ws.outputJSONSync=Ws.outputJsonSync,Ws.writeJSON=Ws.writeJson,Ws.writeJSONSync=Ws.writeJsonSync,Ws.readJSON=Ws.readJson,Ws.readJSONSync=Ws.readJsonSync;var zs=Ws;const Ks=we,qs=p.default,Ys=ci.copySync,Xs=Ji.removeSync,Zs=Io.mkdirpSync,Qs=Zo;function ec(e,t,n){try{Ks.renameSync(e,t)}catch(r){if("EXDEV"!==r.code)throw r;return function(e,t,n){const r={overwrite:n,errorOnExist:!0};return Ys(e,t,r),Xs(e)}(e,t,n)}}var tc=function(e,t,n){const r=(n=n||{}).overwrite||n.clobber||!1,{srcStat:u}=Qs.checkPathsSync(e,t,"move");return Qs.checkParentPathsSync(e,u,t,"move"),Zs(qs.dirname(t)),function(e,t,n){if(n)return Xs(t),ec(e,t,n);if(Ks.existsSync(t))throw new Error("dest already exists.");return ec(e,t,n)}(e,t,r)},nc={moveSync:tc};const rc=we,uc=p.default,oc=bi.copy,ic=Ji.remove,sc=Io.mkdirp,cc=fi.pathExists,ac=Zo;function lc(e,t,n,r){rc.rename(e,t,(u=>u?"EXDEV"!==u.code?r(u):function(e,t,n,r){const u={overwrite:n,errorOnExist:!0};oc(e,t,u,(t=>t?r(t):ic(e,r)))}(e,t,n,r):r()))}var fc=function(e,t,n,r){"function"==typeof n&&(r=n,n={});const u=n.overwrite||n.clobber||!1;ac.checkPaths(e,t,"move",((n,o)=>{if(n)return r(n);const{srcStat:i}=o;ac.checkParentPaths(e,i,t,"move",(n=>{if(n)return r(n);sc(uc.dirname(t),(n=>n?r(n):function(e,t,n,r){if(n)return ic(t,(u=>u?r(u):lc(e,t,n,r)));cc(t,((u,o)=>u?r(u):o?r(new Error("dest already exists.")):lc(e,t,n,r)))}(e,t,u,r)))}))}))};var dc={move:(0,yo.fromCallback)(fc)};const Dc=yo.fromCallback,pc=we,Ec=p.default,mc=Io,hc=fi.pathExists;var yc={outputFile:Dc((function(e,t,n,r){"function"==typeof n&&(r=n,n="utf8");const u=Ec.dirname(e);hc(u,((o,i)=>o?r(o):i?pc.writeFile(e,t,n,r):void mc.mkdirs(u,(u=>{if(u)return r(u);pc.writeFile(e,t,n,r)}))))})),outputFileSync:function(e,...t){const n=Ec.dirname(e);if(pc.existsSync(n))return pc.writeFileSync(e,...t);mc.mkdirsSync(n),pc.writeFileSync(e,...t)}};!function(e){e.exports=Object.assign({},ho,ci,bi,Yi,bs,zs,Io,nc,dc,yc,fi,Ji);const t=D.default;Object.getOwnPropertyDescriptor(t,"promises")&&Object.defineProperty(e.exports,"promises",{get:()=>t.promises})}(mo);const Cc=Nr.exports("streamroller:fileNameFormatter"),Fc=p.default;const gc=Nr.exports("streamroller:fileNameParser"),Ac=nu.exports;const vc=Nr.exports("streamroller:moveAndMaybeCompressFile"),Sc=mo.exports,wc=v.default;var Oc=async(e,t,n)=>{if(n=function(e){const t={mode:parseInt("0600",8),compress:!1},n=Object.assign({},t,e);return vc(`_parseOption: moveAndMaybeCompressFile called with option=${JSON.stringify(n)}`),n}(n),e!==t){if(await Sc.pathExists(e))if(vc(`moveAndMaybeCompressFile: moving file from ${e} to ${t} ${n.compress?"with":"without"} compress`),n.compress)await new Promise(((r,u)=>{let o=!1;const i=Sc.createWriteStream(t,{mode:n.mode,flags:"wx"}).on("open",(()=>{o=!0;const t=Sc.createReadStream(e).on("open",(()=>{t.pipe(wc.createGzip()).pipe(i)})).on("error",(t=>{vc(`moveAndMaybeCompressFile: error reading ${e}`,t),i.destroy(t)}))})).on("finish",(()=>{vc(`moveAndMaybeCompressFile: finished compressing ${t}, deleting ${e}`),Sc.unlink(e).then(r).catch((t=>{vc(`moveAndMaybeCompressFile: error deleting ${e}, truncating instead`,t),Sc.truncate(e).then(r).catch((t=>{vc(`moveAndMaybeCompressFile: error truncating ${e}`,t),u(t)}))}))})).on("error",(e=>{o?(vc(`moveAndMaybeCompressFile: error writing ${t}, deleting`,e),Sc.unlink(t).then((()=>{u(e)})).catch((e=>{vc(`moveAndMaybeCompressFile: error deleting ${t}`,e),u(e)}))):(vc(`moveAndMaybeCompressFile: error creating ${t}`,e),u(e))}))})).catch((()=>{}));else{vc(`moveAndMaybeCompressFile: renaming ${e} to ${t}`);try{await Sc.move(e,t,{overwrite:!0})}catch(n){if(vc(`moveAndMaybeCompressFile: error renaming ${e} to ${t}`,n),"ENOENT"!==n.code){vc("moveAndMaybeCompressFile: trying copy+truncate instead");try{await Sc.copy(e,t,{overwrite:!0}),await Sc.truncate(e)}catch(e){vc("moveAndMaybeCompressFile: error copy+truncate",e)}}}}}else vc("moveAndMaybeCompressFile: source and target are the same, not doing anything")};const bc=Nr.exports("streamroller:RollingFileWriteStream"),_c=mo.exports,Bc=p.default,Pc=E.default,kc=()=>new Date,xc=nu.exports,{Writable:Nc}=C.default,Ic=({file:e,keepFileExt:t,needsIndex:n,alwaysIncludeDate:r,compress:u,fileNameSep:o})=>{let i=o||".";const s=Fc.join(e.dir,e.name),c=t=>t+e.ext,a=(e,t,r)=>!n&&r||!t?e:e+i+t,l=(e,t,n)=>(t>0||r)&&n?e+i+n:e,f=(e,t)=>t&&u?e+".gz":e,d=t?[l,a,c,f]:[c,l,a,f];return({date:e,index:t})=>(Cc(`_formatFileName: date=${e}, index=${t}`),d.reduce(((n,r)=>r(n,t,e)),s))},Tc=({file:e,keepFileExt:t,pattern:n,fileNameSep:r})=>{let u=r||".";const o="__NOT_MATCHING__";let i=[(e,t)=>e.endsWith(".gz")?(gc("it is gzipped"),t.isCompressed=!0,e.slice(0,-1*".gz".length)):e,t?t=>t.startsWith(e.name)&&t.endsWith(e.ext)?(gc("it starts and ends with the right things"),t.slice(e.name.length+1,-1*e.ext.length)):o:t=>t.startsWith(e.base)?(gc("it starts with the right things"),t.slice(e.base.length+1)):o,n?(e,t)=>{const r=e.split(u);let o=r[r.length-1];gc("items: ",r,", indexStr: ",o);let i=e;void 0!==o&&o.match(/^\d+$/)?(i=e.slice(0,-1*(o.length+1)),gc(`dateStr is ${i}`),n&&!i&&(i=o,o="0")):o="0";try{const r=Ac.parse(n,i,new Date(0,0));return Ac.asString(n,r)!==i?e:(t.index=parseInt(o,10),t.date=i,t.timestamp=r.getTime(),"")}catch(t){return gc(`Problem parsing ${i} as ${n}, error was: `,t),e}}:(e,t)=>e.match(/^\d+$/)?(gc("it has an index"),t.index=parseInt(e,10),""):e];return e=>{let t={filename:e,index:0,isCompressed:!1};return i.reduce(((e,n)=>n(e,t)),e)?null:t}},Rc=Oc;var Mc=class extends Nc{constructor(e,t){if(bc(`constructor: creating RollingFileWriteStream. path=${e}`),"string"!=typeof e||0===e.length)throw new Error(`Invalid filename: ${e}`);if(e.endsWith(Bc.sep))throw new Error(`Filename is a directory: ${e}`);0===e.indexOf(`~${Bc.sep}`)&&(e=e.replace("~",Pc.homedir())),super(t),this.options=this._parseOption(t),this.fileObject=Bc.parse(e),""===this.fileObject.dir&&(this.fileObject=Bc.parse(Bc.join(process.cwd(),e))),this.fileFormatter=Ic({file:this.fileObject,alwaysIncludeDate:this.options.alwaysIncludePattern,needsIndex:this.options.maxSize 0`)}else delete n.maxSize;if(n.numBackups||0===n.numBackups){if(n.numBackups<0)throw new Error(`options.numBackups (${n.numBackups}) should be >= 0`);if(n.numBackups>=Number.MAX_SAFE_INTEGER)throw new Error(`options.numBackups (${n.numBackups}) should be < Number.MAX_SAFE_INTEGER`);n.numToKeep=n.numBackups+1}else if(n.numToKeep<=0)throw new Error(`options.numToKeep (${n.numToKeep}) should be > 0`);return bc(`_parseOption: creating stream with option=${JSON.stringify(n)}`),n}_final(e){this.currentFileStream.end("",this.options.encoding,e)}_write(e,t,n){this._shouldRoll().then((()=>{bc(`_write: writing chunk. file=${this.currentFileStream.path} state=${JSON.stringify(this.state)} chunk=${e}`),this.currentFileStream.write(e,t,(t=>{this.state.currentSize+=e.length,n(t)}))}))}async _shouldRoll(){(this._dateChanged()||this._tooBig())&&(bc(`_shouldRoll: rolling because dateChanged? ${this._dateChanged()} or tooBig? ${this._tooBig()}`),await this._roll())}_dateChanged(){return this.state.currentDate&&this.state.currentDate!==xc(this.options.pattern,kc())}_tooBig(){return this.state.currentSize>=this.options.maxSize}_roll(){return bc("_roll: closing the current stream"),new Promise(((e,t)=>{this.currentFileStream.end("",this.options.encoding,(()=>{this._moveOldFiles().then(e).catch(t)}))}))}async _moveOldFiles(){const e=await this._getExistingFiles();for(let t=(this.state.currentDate?e.filter((e=>e.date===this.state.currentDate)):e).length;t>=0;t--){bc(`_moveOldFiles: i = ${t}`);const e=this.fileFormatter({date:this.state.currentDate,index:t}),n=this.fileFormatter({date:this.state.currentDate,index:t+1}),r={compress:this.options.compress&&0===t,mode:this.options.mode};await Rc(e,n,r)}this.state.currentSize=0,this.state.currentDate=this.state.currentDate?xc(this.options.pattern,kc()):null,bc(`_moveOldFiles: finished rolling files. state=${JSON.stringify(this.state)}`),this._renewWriteStream(),await new Promise(((e,t)=>{this.currentFileStream.write("","utf8",(()=>{this._clean().then(e).catch(t)}))}))}async _getExistingFiles(){const e=await _c.readdir(this.fileObject.dir).catch((()=>[]));bc(`_getExistingFiles: files=${e}`);const t=e.map((e=>this.fileNameParser(e))).filter((e=>e)),n=e=>(e.timestamp?e.timestamp:kc().getTime())-e.index;return t.sort(((e,t)=>n(e)-n(t))),t}_renewWriteStream(){const e=this.fileFormatter({date:this.state.currentDate,index:0}),t=e=>{try{return _c.mkdirSync(e,{recursive:!0})}catch(n){if("ENOENT"===n.code)return t(Bc.dirname(e)),t(e);if("EEXIST"!==n.code&&"EROFS"!==n.code)throw n;try{if(_c.statSync(e).isDirectory())return e;throw n}catch(e){throw n}}};t(this.fileObject.dir);const n={flags:this.options.flags,encoding:this.options.encoding,mode:this.options.mode};var r,u;_c.appendFileSync(e,"",(r={...n},u="flags",r["flag"]=r[u],delete r[u],r)),this.currentFileStream=_c.createWriteStream(e,n),this.currentFileStream.on("error",(e=>{this.emit("error",e)}))}async _clean(){const e=await this._getExistingFiles();if(bc(`_clean: numToKeep = ${this.options.numToKeep}, existingFiles = ${e.length}`),bc("_clean: existing files are: ",e),this._tooManyFiles(e.length)){const n=e.slice(0,e.length-this.options.numToKeep).map((e=>Bc.format({dir:this.fileObject.dir,base:e.filename})));await(t=n,bc(`deleteFiles: files to delete: ${t}`),Promise.all(t.map((e=>_c.unlink(e).catch((t=>{bc(`deleteFiles: error when unlinking ${e}, ignoring. Error was ${t}`)}))))))}var t}_tooManyFiles(e){return this.options.numToKeep>0&&e>this.options.numToKeep}};const Lc=Mc;var jc=class extends Lc{constructor(e,t,n,r){r||(r={}),t&&(r.maxSize=t),r.numBackups||0===r.numBackups||(n||0===n||(n=1),r.numBackups=n),super(e,r),this.backups=r.numBackups,this.size=this.options.maxSize}get theStream(){return this.currentFileStream}};const $c=Mc;var Hc={RollingFileWriteStream:Mc,RollingFileStream:jc,DateRollingFileStream:class extends $c{constructor(e,t,n){t&&"object"==typeof t&&(n=t,t=null),n||(n={}),t||(t="yyyy-MM-dd"),n.pattern=t,n.numBackups||0===n.numBackups?n.daysToKeep=n.numBackups:(n.daysToKeep||0===n.daysToKeep?process.emitWarning("options.daysToKeep is deprecated due to the confusion it causes when used together with file size rolling. Please use options.numBackups instead.","DeprecationWarning","streamroller-DEP0001"):n.daysToKeep=1,n.numBackups=n.daysToKeep),super(e,n),this.mode=this.options.mode}get theStream(){return this.currentFileStream}}};const Jc=Nr.exports("log4js:file"),Gc=p.default,Vc=Hc,Uc=E.default.EOL;let Wc=!1;const zc=new Set;function Kc(){zc.forEach((e=>{e.sighupHandler()}))}function qc(e,t,n,r){const u=new Vc.RollingFileStream(e,t,n,r);return u.on("error",(t=>{console.error("log4js.fileAppender - Writing to file %s, error happened ",e,t)})),u.on("drain",(()=>{process.emit("log4js:pause",!1)})),u}Eo.configure=function(e,t){let n=t.basicLayout;return e.layout&&(n=t.layout(e.layout.type,e.layout)),e.mode=e.mode||384,function(e,t,n,r,u,o){e=Gc.normalize(e),Jc("Creating file appender (",e,", ",n,", ",r=r||0===r?r:5,", ",u,", ",o,")");let i=qc(e,n,r,u);const s=function(e){if(i.writable){if(!0===u.removeColor){const t=/\x1b[[0-9;]*m/g;e.data=e.data.map((e=>"string"==typeof e?e.replace(t,""):e))}i.write(t(e,o)+Uc,"utf8")||process.emit("log4js:pause",!0)}};return s.reopen=function(){i.end((()=>{i=qc(e,n,r,u)}))},s.sighupHandler=function(){Jc("SIGHUP handler called."),s.reopen()},s.shutdown=function(e){zc.delete(s),0===zc.size&&Wc&&(process.removeListener("SIGHUP",Kc),Wc=!1),i.end("","utf-8",e)},zc.add(s),Wc||(process.on("SIGHUP",Kc),Wc=!0),s}(e.filename,n,e.maxLogSize,e.backups,e,e.timezoneOffset)};var Yc={};const Xc=Hc,Zc=E.default.EOL;function Qc(e,t,n,r,u){r.maxSize=r.maxLogSize;const o=function(e,t,n){const r=new Xc.DateRollingFileStream(e,t,n);return r.on("error",(t=>{console.error("log4js.dateFileAppender - Writing to file %s, error happened ",e,t)})),r.on("drain",(()=>{process.emit("log4js:pause",!1)})),r}(e,t,r),i=function(e){o.writable&&(o.write(n(e,u)+Zc,"utf8")||process.emit("log4js:pause",!0))};return i.shutdown=function(e){o.end("","utf-8",e)},i}Yc.configure=function(e,t){let n=t.basicLayout;return e.layout&&(n=t.layout(e.layout.type,e.layout)),e.alwaysIncludePattern||(e.alwaysIncludePattern=!1),e.mode=e.mode||384,Qc(e.filename,e.pattern,n,e,e.timezoneOffset)};var ea={};const ta=Nr.exports("log4js:fileSync"),na=p.default,ra=D.default,ua=E.default.EOL||"\n";function oa(e,t){if(ra.existsSync(e))return;const n=ra.openSync(e,t.flags,t.mode);ra.closeSync(n)}class ia{constructor(e,t,n,r){ta("In RollingFileStream"),function(){if(!e||!t||t<=0)throw new Error("You must specify a filename and file size")}(),this.filename=e,this.size=t,this.backups=n,this.options=r,this.currentSize=0,this.currentSize=function(e){let t=0;try{t=ra.statSync(e).size}catch(t){oa(e,r)}return t}(this.filename)}shouldRoll(){return ta("should roll with current size %d, and max size %d",this.currentSize,this.size),this.currentSize>=this.size}roll(e){const t=this,n=new RegExp(`^${na.basename(e)}`);function r(e){return n.test(e)}function u(t){return parseInt(t.substring(`${na.basename(e)}.`.length),10)||0}function o(e,t){return u(e)>u(t)?1:u(e) ${e}.${r+1}`),ra.renameSync(na.join(na.dirname(e),n),`${e}.${r+1}`)}}ta("Rolling, rolling, rolling"),ta("Renaming the old files"),ra.readdirSync(na.dirname(e)).filter(r).sort(o).reverse().forEach(i)}write(e,t){const n=this;ta("in write"),this.shouldRoll()&&(this.currentSize=0,this.roll(this.filename)),ta("writing the chunk to the file"),n.currentSize+=e.length,ra.appendFileSync(n.filename,e)}}ea.configure=function(e,t){let n=t.basicLayout;e.layout&&(n=t.layout(e.layout.type,e.layout));const r={flags:e.flags||"a",encoding:e.encoding||"utf8",mode:e.mode||384};return function(e,t,n,r,u,o){ta("fileSync appender created");const i=function(e,t,n){let r;var u;return t?r=new ia(e,t,n,o):(oa(u=e,o),r={write(e){ra.appendFileSync(u,e)}}),r}(e=na.normalize(e),n,r=r||0===r?r:5);return e=>{i.write(t(e,u)+ua)}}(e.filename,n,e.maxLogSize,e.backups,e.timezoneOffset,r)};var sa={};const ca=Nr.exports("log4js:tcp"),aa=S.default;sa.configure=function(e,t){ca(`configure with config = ${e}`);let n=function(e){return e.serialise()};return e.layout&&(n=t.layout(e.layout.type,e.layout)),function(e,t){let n=!1;const r=[];let u,o=3,i="__LOG4JS__";function s(e){ca("Writing log event to socket"),n=u.write(`${t(e)}${i}`,"utf8")}function c(){let e;for(ca("emptying buffer");e=r.shift();)s(e)}function a(e){n?s(e):(ca("buffering log event because it cannot write at the moment"),r.push(e))}return function t(){ca(`appender creating socket to ${e.host||"localhost"}:${e.port||5e3}`),i=`${e.endMsg||"__LOG4JS__"}`,u=aa.createConnection(e.port||5e3,e.host||"localhost"),u.on("connect",(()=>{ca("socket connected"),c(),n=!0})),u.on("drain",(()=>{ca("drain event received, emptying buffer"),n=!0,c()})),u.on("timeout",u.end.bind(u)),u.on("error",(e=>{ca("connection error",e),n=!1,c()})),u.on("close",t)}(),a.shutdown=function(e){ca("shutdown called"),r.length&&o?(ca("buffer has items, waiting 100ms to empty"),o-=1,setTimeout((()=>{a.shutdown(e)}),100)):(u.removeAllListeners("close"),u.end(e))},a}(e,n)};const la=p.default,fa=Nr.exports("log4js:appenders"),da=tu,Da=eo,pa=gu,Ea=hu,ma=to,ha=new Map;ha.set("console",oo),ha.set("stdout",so),ha.set("stderr",co),ha.set("logLevelFilter",ao),ha.set("categoryFilter",lo),ha.set("noLogFilter",Do),ha.set("file",Eo),ha.set("dateFile",Yc),ha.set("fileSync",ea),ha.set("tcp",sa);const ya=new Map,Ca=(e,t)=>{fa("Loading module from ",e);try{return require(e)}catch(n){return void da.throwExceptionIf(t,"MODULE_NOT_FOUND"!==n.code,`appender "${e}" could not be loaded (error was: ${n})`)}},Fa=new Set,ga=(e,t)=>{if(ya.has(e))return ya.get(e);if(!t.appenders[e])return!1;if(Fa.has(e))throw new Error(`Dependency loop detected for appender ${e}.`);Fa.add(e),fa(`Creating appender ${e}`);const n=Aa(e,t);return Fa.delete(e),ya.set(e,n),n},Aa=(e,t)=>{const n=t.appenders[e],r=n.type.configure?n.type:((e,t)=>ha.get(e)||Ca(`./${e}`,t)||Ca(e,t)||require.main&&Ca(la.join(la.dirname(require.main.filename),e),t)||Ca(la.join(process.cwd(),e),t))(n.type,t);return da.throwExceptionIf(t,da.not(r),`appender "${e}" is not valid (type "${n.type}" could not be found)`),r.appender&&fa(`DEPRECATION: Appender ${n.type} exports an appender function.`),r.shutdown&&fa(`DEPRECATION: Appender ${n.type} exports a shutdown function.`),fa(`${e}: clustering.isMaster ? ${Da.isMaster()}`),fa(`${e}: appenderModule is ${F.default.inspect(r)}`),Da.onlyOnMaster((()=>(fa(`calling appenderModule.configure for ${e} / ${n.type}`),r.configure(ma.modifyConfig(n),Ea,(e=>ga(e,t)),pa))),(()=>{}))},va=e=>{ya.clear(),Fa.clear();const t=[];Object.values(e.categories).forEach((e=>{t.push(...e.appenders)})),Object.keys(e.appenders).forEach((n=>{(t.includes(n)||"tcp-server"===e.appenders[n].type)&&ga(n,e)}))},Sa=()=>{va({appenders:{out:{type:"stdout"}},categories:{default:{appenders:["out"],level:"trace"}}})};Sa(),da.addListener((e=>{da.throwExceptionIf(e,da.not(da.anObject(e.appenders)),'must have a property "appenders" of type object.');const t=Object.keys(e.appenders);da.throwExceptionIf(e,da.not(t.length),"must define at least one appender."),t.forEach((t=>{da.throwExceptionIf(e,da.not(e.appenders[t].type),`appender "${t}" is not valid (must be an object with property "type")`)}))})),da.addListener(va),Au.exports=ya,Au.exports.init=Sa;var wa={exports:{}};!function(e){const t=Nr.exports("log4js:categories"),n=tu,r=gu,u=Au.exports,o=new Map;function i(e,t,n){if(!1===t.inherit)return;const r=n.lastIndexOf(".");if(r<0)return;const u=n.substring(0,r);let o=e.categories[u];o||(o={inherit:!0,appenders:[]}),i(e,o,u),!e.categories[u]&&o.appenders&&o.appenders.length&&o.level&&(e.categories[u]=o),t.appenders=t.appenders||[],t.level=t.level||o.level,o.appenders.forEach((e=>{t.appenders.includes(e)||t.appenders.push(e)})),t.parent=o}function s(e){if(!e.categories)return;Object.keys(e.categories).forEach((t=>{const n=e.categories[t];i(e,n,t)}))}n.addPreProcessingListener((e=>s(e))),n.addListener((e=>{n.throwExceptionIf(e,n.not(n.anObject(e.categories)),'must have a property "categories" of type object.');const t=Object.keys(e.categories);n.throwExceptionIf(e,n.not(t.length),"must define at least one category."),t.forEach((t=>{const o=e.categories[t];n.throwExceptionIf(e,[n.not(o.appenders),n.not(o.level)],`category "${t}" is not valid (must be an object with properties "appenders" and "level")`),n.throwExceptionIf(e,n.not(Array.isArray(o.appenders)),`category "${t}" is not valid (appenders must be an array of appender names)`),n.throwExceptionIf(e,n.not(o.appenders.length),`category "${t}" is not valid (appenders must contain at least one appender name)`),Object.prototype.hasOwnProperty.call(o,"enableCallStack")&&n.throwExceptionIf(e,"boolean"!=typeof o.enableCallStack,`category "${t}" is not valid (enableCallStack must be boolean type)`),o.appenders.forEach((r=>{n.throwExceptionIf(e,n.not(u.get(r)),`category "${t}" is not valid (appender "${r}" is not defined)`)})),n.throwExceptionIf(e,n.not(r.getLevel(o.level)),`category "${t}" is not valid (level "${o.level}" not recognised; valid levels are ${r.levels.join(", ")})`)})),n.throwExceptionIf(e,n.not(e.categories.default),'must define a "default" category.')}));const c=e=>{o.clear();Object.keys(e.categories).forEach((n=>{const i=e.categories[n],s=[];i.appenders.forEach((e=>{s.push(u.get(e)),t(`Creating category ${n}`),o.set(n,{appenders:s,level:r.getLevel(i.level),enableCallStack:i.enableCallStack||!1})}))}))},a=()=>{c({categories:{default:{appenders:["out"],level:"OFF"}}})};a(),n.addListener(c);const l=e=>(t(`configForCategory: searching for config for ${e}`),o.has(e)?(t(`configForCategory: ${e} exists in config, returning it`),o.get(e)):e.indexOf(".")>0?(t(`configForCategory: ${e} has hierarchy, searching for parents`),l(e.substring(0,e.lastIndexOf(".")))):(t("configForCategory: returning config for default category"),l("default")));e.exports=o,e.exports=Object.assign(e.exports,{appendersForCategory:e=>l(e).appenders,getLevelForCategory:e=>l(e).level,setLevelForCategory:(e,n)=>{let r=o.get(e);if(t(`setLevelForCategory: found ${r} for ${e}`),!r){const n=l(e);t(`setLevelForCategory: no config found for category, found ${n} for parents of ${e}`),r={appenders:n.appenders}}r.level=n,o.set(e,r)},getEnableCallStackForCategory:e=>!0===l(e).enableCallStack,setEnableCallStackForCategory:(e,t)=>{l(e).enableCallStack=t},init:a})}(wa);const Oa=Nr.exports("log4js:logger"),ba=Hu,_a=gu,Ba=eo,Pa=wa.exports,ka=tu,xa=/at (?:(.+)\s+\()?(?:(.+?):(\d+)(?::(\d+))?|([^)]+))\)?/;function Na(e,t=4){const n=e.stack.split("\n").slice(t),r=xa.exec(n[0]);return r&&6===r.length?{functionName:r[1],fileName:r[2],lineNumber:parseInt(r[3],10),columnNumber:parseInt(r[4],10),callStack:n.join("\n")}:null}class Ia{constructor(e){if(!e)throw new Error("No category provided.");this.category=e,this.context={},this.parseCallStack=Na,Oa(`Logger created (${this.category}, ${this.level})`)}get level(){return _a.getLevel(Pa.getLevelForCategory(this.category),_a.TRACE)}set level(e){Pa.setLevelForCategory(this.category,_a.getLevel(e,this.level))}get useCallStack(){return Pa.getEnableCallStackForCategory(this.category)}set useCallStack(e){Pa.setEnableCallStackForCategory(this.category,!0===e)}log(e,...t){let n=_a.getLevel(e);n||(this._log(_a.WARN,"log4js:logger.log: invalid value for log-level as first parameter given: ",e),n=_a.INFO),this.isLevelEnabled(n)&&this._log(n,t)}isLevelEnabled(e){return this.level.isLessThanOrEqualTo(e)}_log(e,t){Oa(`sending log data (${e}) to appenders`);const n=new ba(this.category,e,t,this.context,this.useCallStack&&this.parseCallStack(new Error));Ba.send(n)}addContext(e,t){this.context[e]=t}removeContext(e){delete this.context[e]}clearContext(){this.context={}}setParseCallStackFunction(e){this.parseCallStack=e}}function Ta(e){const t=_a.getLevel(e),n=t.toString().toLowerCase().replace(/_([a-z])/g,(e=>e[1].toUpperCase())),r=n[0].toUpperCase()+n.slice(1);Ia.prototype[`is${r}Enabled`]=function(){return this.isLevelEnabled(t)},Ia.prototype[n]=function(...e){this.log(t,...e)}}_a.levels.forEach(Ta),ka.addListener((()=>{_a.levels.forEach(Ta)}));var Ra=Ia;const Ma=gu;function La(e){return e.originalUrl||e.url}function ja(e,t){for(let n=0;ne.source?e.source:e));t=new RegExp(n.join("|"))}return t}(t.nolog);return(e,i,s)=>{if(e._logging)return s();if(o&&o.test(e.originalUrl))return s();if(n.isLevelEnabled(r)||"auto"===t.level){const o=new Date,{writeHead:s}=i;e._logging=!0,i.writeHead=(e,t)=>{i.writeHead=s,i.writeHead(e,t),i.__statusCode=e,i.__headers=t||{}},i.on("finish",(()=>{i.responseTime=new Date-o,i.statusCode&&"auto"===t.level&&(r=Ma.INFO,i.statusCode>=300&&(r=Ma.WARN),i.statusCode>=400&&(r=Ma.ERROR)),r=function(e,t,n){let r=t;if(n){const t=n.find((t=>{let n=!1;return n=t.from&&t.to?e>=t.from&&e<=t.to:-1!==t.codes.indexOf(e),n}));t&&(r=Ma.getLevel(t.level,r))}return r}(i.statusCode,r,t.statusRules);const s=function(e,t,n){const r=[];return r.push({token:":url",replacement:La(e)}),r.push({token:":protocol",replacement:e.protocol}),r.push({token:":hostname",replacement:e.hostname}),r.push({token:":method",replacement:e.method}),r.push({token:":status",replacement:t.__statusCode||t.statusCode}),r.push({token:":response-time",replacement:t.responseTime}),r.push({token:":date",replacement:(new Date).toUTCString()}),r.push({token:":referrer",replacement:e.headers.referer||e.headers.referrer||""}),r.push({token:":http-version",replacement:`${e.httpVersionMajor}.${e.httpVersionMinor}`}),r.push({token:":remote-addr",replacement:e.headers["x-forwarded-for"]||e.ip||e._remoteAddress||e.socket&&(e.socket.remoteAddress||e.socket.socket&&e.socket.socket.remoteAddress)}),r.push({token:":user-agent",replacement:e.headers["user-agent"]}),r.push({token:":content-length",replacement:t.getHeader("content-length")||t.__headers&&t.__headers["Content-Length"]||"-"}),r.push({token:/:req\[([^\]]+)]/g,replacement:(t,n)=>e.headers[n.toLowerCase()]}),r.push({token:/:res\[([^\]]+)]/g,replacement:(e,n)=>t.getHeader(n.toLowerCase())||t.__headers&&t.__headers[n]}),(e=>{const t=e.concat();for(let e=0;eja(e,s)));t&&n.log(r,t)}else n.log(r,ja(u,s));t.context&&n.removeContext("res")}))}return s()}},nl=Va;let rl=!1;function ul(e){if(!rl)return;Ua("Received log event ",e);Za.appendersForCategory(e.categoryName).forEach((t=>{t(e)}))}function ol(e){rl&&il();let t=e;return"string"==typeof t&&(t=function(e){Ua(`Loading configuration from ${e}`);try{return JSON.parse(Wa.readFileSync(e,"utf8"))}catch(t){throw new Error(`Problem reading config from file "${e}". Error was ${t.message}`,t)}}(e)),Ua(`Configuration is ${t}`),Ka.configure(za(t)),el.onMessage(ul),rl=!0,sl}function il(e){Ua("Shutdown called. Disabling all log writing."),rl=!1;const t=Array.from(Xa.values());Xa.init(),Za.init();const n=t.reduceRight(((e,t)=>t.shutdown?e+1:e),0);if(0===n)return Ua("No appenders with shutdown functions found."),void 0!==e&&e();let r,u=0;function o(t){r=r||t,u+=1,Ua(`Appender shutdowns complete: ${u} / ${n}`),u>=n&&(Ua("All shutdown functions completed."),e&&e(r))}return Ua(`Found ${n} appenders with shutdown functions.`),t.filter((e=>e.shutdown)).forEach((e=>e.shutdown(o))),null}const sl={getLogger:function(e){return rl||ol(process.env.LOG4JS_CONFIG||{appenders:{out:{type:"stdout"}},categories:{default:{appenders:["out"],level:"OFF"}}}),new Qa(e||"default")},configure:ol,shutdown:il,connectLogger:tl,levels:Ya,addLayout:qa.addLayout,recording:function(){return nl}};var cl=sl,al={};Object.defineProperty(al,"__esModule",{value:!0}),al.levelMap=al.getLevel=al.setCategoriesLevel=al.getConfiguration=al.setConfiguration=void 0;const ll=cl;let fl={appenders:{debug:{type:"stdout",layout:{type:"pattern",pattern:"[%d] > hvigor %p %c %[%m%]"}},info:{type:"stdout",layout:{type:"pattern",pattern:"[%d] > hvigor %[%m%]"}},"no-pattern-info":{type:"stdout",layout:{type:"pattern",pattern:"%m"}},wrong:{type:"stderr",layout:{type:"pattern",pattern:"[%d] > hvigor %[%p: %m%]"}},"just-debug":{type:"logLevelFilter",appender:"debug",level:"debug",maxLevel:"debug"},"just-info":{type:"logLevelFilter",appender:"info",level:"info",maxLevel:"info"},"just-wrong":{type:"logLevelFilter",appender:"wrong",level:"warn",maxLevel:"error"}},categories:{default:{appenders:["just-debug","just-info","just-wrong"],level:"debug"},"no-pattern-info":{appenders:["no-pattern-info"],level:"info"}}};al.setConfiguration=e=>{fl=e};al.getConfiguration=()=>fl;let dl=ll.levels.DEBUG;al.setCategoriesLevel=(e,t)=>{dl=e;const n=fl.categories;for(const r in n)(null==t?void 0:t.includes(r))||Object.prototype.hasOwnProperty.call(n,r)&&(n[r].level=e.levelStr)};al.getLevel=()=>dl,al.levelMap=new Map([["ALL",ll.levels.ALL],["MARK",ll.levels.MARK],["TRACE",ll.levels.TRACE],["DEBUG",ll.levels.DEBUG],["INFO",ll.levels.INFO],["WARN",ll.levels.WARN],["ERROR",ll.levels.ERROR],["FATAL",ll.levels.FATAL],["OFF",ll.levels.OFF]]);var Dl=w&&w.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n);var u=Object.getOwnPropertyDescriptor(t,n);u&&!("get"in u?!t.__esModule:u.writable||u.configurable)||(u={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,r,u)}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),pl=w&&w.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),El=w&&w.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.prototype.hasOwnProperty.call(e,n)&&Dl(t,e,n);return pl(t,e),t};Object.defineProperty(xr,"__esModule",{value:!0}),xr.evaluateLogLevel=xr.HvigorLogger=void 0;const ml=El(cl),hl=cl,yl=El(F.default),Cl=al;class Fl{constructor(e){ml.configure((0,Cl.getConfiguration)()),this._logger=ml.getLogger(e),this._logger.level=(0,Cl.getLevel)()}static getLogger(e){return new Fl(e)}log(e,...t){this._logger.log(e,...t)}debug(e,...t){this._logger.debug(e,...t)}info(e,...t){this._logger.info(e,...t)}warn(e,...t){void 0!==e&&""!==e&&this._logger.warn(e,...t)}error(e,...t){this._logger.error(e,...t)}_printTaskExecuteInfo(e,t){this.info(`Finished :${e}... after ${t}`)}_printFailedTaskInfo(e){this.error(`Failed :${e}... `)}_printDisabledTaskInfo(e){this.info(`Disabled :${e}... `)}_printUpToDateTaskInfo(e){this.info(`UP-TO-DATE :${e}... `)}errorMessageExit(e,...t){throw new Error(yl.format(e,...t))}errorExit(e,t,...n){t&&this._logger.error(t,n),this._logger.error(e.stack)}setLevel(e,t){(0,Cl.setCategoriesLevel)(e,t),ml.shutdown(),ml.configure((0,Cl.getConfiguration)())}getLevel(){return this._logger.level}configure(e){const t=(0,Cl.getConfiguration)(),n={appenders:{...t.appenders,...e.appenders},categories:{...t.categories,...e.categories}};(0,Cl.setConfiguration)(n),ml.shutdown(),ml.configure(n)}}xr.HvigorLogger=Fl,xr.evaluateLogLevel=function(e,t){t.debug?e.setLevel(hl.levels.DEBUG):t.warn?e.setLevel(hl.levels.WARN):t.error?e.setLevel(hl.levels.ERROR):e.setLevel(hl.levels.INFO)};var gl=w&&w.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(X,"__esModule",{value:!0}),X.parseJsonText=X.parseJsonFile=void 0;const Al=Z,vl=gl(kr),Sl=gl(p.default),wl=gl(E.default),Ol=xr.HvigorLogger.getLogger("parse-json-util");var bl;!function(e){e[e.Char=0]="Char",e[e.EOF=1]="EOF",e[e.Identifier=2]="Identifier"}(bl||(bl={}));let _l,Bl,Pl,kl,xl,Nl,Il="start",Tl=[],Rl=0,Ml=1,Ll=0,jl=!1,$l="default",Hl="'",Jl=1;function Gl(e,t=!1){Bl=String(e),Il="start",Tl=[],Rl=0,Ml=1,Ll=0,kl=void 0,jl=t;do{_l=Vl(),Xl[Il]()}while("eof"!==_l.type);return kl}function Vl(){for($l="default",xl="",Hl="'",Jl=1;;){Nl=Ul();const e=zl[$l]();if(e)return e}}function Ul(){if(Bl[Rl])return String.fromCodePoint(Bl.codePointAt(Rl))}function Wl(){const e=Ul();return"\n"===e?(Ml++,Ll=0):e?Ll+=e.length:Ll++,e&&(Rl+=e.length),e}X.parseJsonFile=function(e,t=!1,n="utf-8"){const r=vl.default.readFileSync(Sl.default.resolve(e),{encoding:n});try{return Gl(r,t)}catch(t){if(t instanceof SyntaxError){const n=t.message.split("at");2===n.length&&Ol.errorMessageExit(`${n[0].trim()}${wl.default.EOL}\t at ${e}:${n[1].trim()}`)}Ol.errorMessageExit(`${e} is not in valid JSON/JSON5 format.`)}},X.parseJsonText=Gl;const zl={default(){switch(Nl){case"/":return Wl(),void($l="comment");case void 0:return Wl(),Kl("eof")}if(!Al.JudgeUtil.isIgnoreChar(Nl)&&!Al.JudgeUtil.isSpaceSeparator(Nl))return zl[Il]();Wl()},start(){$l="value"},beforePropertyName(){switch(Nl){case"$":case"_":return xl=Wl(),void($l="identifierName");case"\\":return Wl(),void($l="identifierNameStartEscape");case"}":return Kl("punctuator",Wl());case'"':case"'":return Hl=Nl,Wl(),void($l="string")}if(Al.JudgeUtil.isIdStartChar(Nl))return xl+=Wl(),void($l="identifierName");throw tf(bl.Char,Wl())},afterPropertyName(){if(":"===Nl)return Kl("punctuator",Wl());throw tf(bl.Char,Wl())},beforePropertyValue(){$l="value"},afterPropertyValue(){switch(Nl){case",":case"}":return Kl("punctuator",Wl())}throw tf(bl.Char,Wl())},beforeArrayValue(){if("]"===Nl)return Kl("punctuator",Wl());$l="value"},afterArrayValue(){switch(Nl){case",":case"]":return Kl("punctuator",Wl())}throw tf(bl.Char,Wl())},end(){throw tf(bl.Char,Wl())},comment(){switch(Nl){case"*":return Wl(),void($l="multiLineComment");case"/":return Wl(),void($l="singleLineComment")}throw tf(bl.Char,Wl())},multiLineComment(){switch(Nl){case"*":return Wl(),void($l="multiLineCommentAsterisk");case void 0:throw tf(bl.Char,Wl())}Wl()},multiLineCommentAsterisk(){switch(Nl){case"*":return void Wl();case"/":return Wl(),void($l="default");case void 0:throw tf(bl.Char,Wl())}Wl(),$l="multiLineComment"},singleLineComment(){switch(Nl){case"\n":case"\r":case"\u2028":case"\u2029":return Wl(),void($l="default");case void 0:return Wl(),Kl("eof")}Wl()},value(){switch(Nl){case"{":case"[":return Kl("punctuator",Wl());case"n":return Wl(),ql("ull"),Kl("null",null);case"t":return Wl(),ql("rue"),Kl("boolean",!0);case"f":return Wl(),ql("alse"),Kl("boolean",!1);case"-":case"+":return"-"===Wl()&&(Jl=-1),void($l="numerical");case".":case"0":case"I":case"N":return void($l="numerical");case'"':case"'":return Hl=Nl,Wl(),xl="",void($l="string")}if(void 0===Nl||!Al.JudgeUtil.isDigitWithoutZero(Nl))throw tf(bl.Char,Wl());$l="numerical"},numerical(){switch(Nl){case".":return xl=Wl(),void($l="decimalPointLeading");case"0":return xl=Wl(),void($l="zero");case"I":return Wl(),ql("nfinity"),Kl("numeric",Jl*(1/0));case"N":return Wl(),ql("aN"),Kl("numeric",NaN)}if(void 0!==Nl&&Al.JudgeUtil.isDigitWithoutZero(Nl))return xl=Wl(),void($l="decimalInteger");throw tf(bl.Char,Wl())},zero(){switch(Nl){case".":case"e":case"E":return void($l="decimal");case"x":case"X":return xl+=Wl(),void($l="hexadecimal")}return Kl("numeric",0)},decimalInteger(){switch(Nl){case".":case"e":case"E":return void($l="decimal")}if(!Al.JudgeUtil.isDigit(Nl))return Kl("numeric",Jl*Number(xl));xl+=Wl()},decimal(){switch(Nl){case".":xl+=Wl(),$l="decimalFraction";break;case"e":case"E":xl+=Wl(),$l="decimalExponent"}},decimalPointLeading(){if(Al.JudgeUtil.isDigit(Nl))return xl+=Wl(),void($l="decimalFraction");throw tf(bl.Char,Wl())},decimalFraction(){switch(Nl){case"e":case"E":return xl+=Wl(),void($l="decimalExponent")}if(!Al.JudgeUtil.isDigit(Nl))return Kl("numeric",Jl*Number(xl));xl+=Wl()},decimalExponent(){switch(Nl){case"+":case"-":return xl+=Wl(),void($l="decimalExponentSign")}if(Al.JudgeUtil.isDigit(Nl))return xl+=Wl(),void($l="decimalExponentInteger");throw tf(bl.Char,Wl())},decimalExponentSign(){if(Al.JudgeUtil.isDigit(Nl))return xl+=Wl(),void($l="decimalExponentInteger");throw tf(bl.Char,Wl())},decimalExponentInteger(){if(!Al.JudgeUtil.isDigit(Nl))return Kl("numeric",Jl*Number(xl));xl+=Wl()},hexadecimal(){if(Al.JudgeUtil.isHexDigit(Nl))return xl+=Wl(),void($l="hexadecimalInteger");throw tf(bl.Char,Wl())},hexadecimalInteger(){if(!Al.JudgeUtil.isHexDigit(Nl))return Kl("numeric",Jl*Number(xl));xl+=Wl()},identifierNameStartEscape(){if("u"!==Nl)throw tf(bl.Char,Wl());Wl();const e=Yl();switch(e){case"$":case"_":break;default:if(!Al.JudgeUtil.isIdStartChar(e))throw tf(bl.Identifier)}xl+=e,$l="identifierName"},identifierName(){switch(Nl){case"$":case"_":case"‌":case"‍":return void(xl+=Wl());case"\\":return Wl(),void($l="identifierNameEscape")}if(!Al.JudgeUtil.isIdContinueChar(Nl))return Kl("identifier",xl);xl+=Wl()},identifierNameEscape(){if("u"!==Nl)throw tf(bl.Char,Wl());Wl();const e=Yl();switch(e){case"$":case"_":case"‌":case"‍":break;default:if(!Al.JudgeUtil.isIdContinueChar(e))throw tf(bl.Identifier)}xl+=e,$l="identifierName"},string(){switch(Nl){case"\\":return Wl(),void(xl+=function(){const e=Ul(),t=function(){switch(Ul()){case"b":return Wl(),"\b";case"f":return Wl(),"\f";case"n":return Wl(),"\n";case"r":return Wl(),"\r";case"t":return Wl(),"\t";case"v":return Wl(),"\v"}return}();if(t)return t;switch(e){case"0":if(Wl(),Al.JudgeUtil.isDigit(Ul()))throw tf(bl.Char,Wl());return"\0";case"x":return Wl(),function(){let e="",t=Ul();if(!Al.JudgeUtil.isHexDigit(t))throw tf(bl.Char,Wl());if(e+=Wl(),t=Ul(),!Al.JudgeUtil.isHexDigit(t))throw tf(bl.Char,Wl());return e+=Wl(),String.fromCodePoint(parseInt(e,16))}();case"u":return Wl(),Yl();case"\n":case"\u2028":case"\u2029":return Wl(),"";case"\r":return Wl(),"\n"===Ul()&&Wl(),""}if(void 0===e||Al.JudgeUtil.isDigitWithoutZero(e))throw tf(bl.Char,Wl());return Wl()}());case'"':case"'":if(Nl===Hl){const e=Kl("string",xl);return Wl(),e}return void(xl+=Wl());case"\n":case"\r":case void 0:throw tf(bl.Char,Wl());case"\u2028":case"\u2029":!function(e){Ol.warn(`JSON5: '${ef(e)}' in strings is not valid ECMAScript; consider escaping.`)}(Nl)}xl+=Wl()}};function Kl(e,t){return{type:e,value:t,line:Ml,column:Ll}}function ql(e){for(const t of e){if(Ul()!==t)throw tf(bl.Char,Wl());Wl()}}function Yl(){let e="",t=4;for(;t-- >0;){const t=Ul();if(!Al.JudgeUtil.isHexDigit(t))throw tf(bl.Char,Wl());e+=Wl()}return String.fromCodePoint(parseInt(e,16))}const Xl={start(){if("eof"===_l.type)throw tf(bl.EOF);Zl()},beforePropertyName(){switch(_l.type){case"identifier":case"string":return Pl=_l.value,void(Il="afterPropertyName");case"punctuator":return void Ql();case"eof":throw tf(bl.EOF)}},afterPropertyName(){if("eof"===_l.type)throw tf(bl.EOF);Il="beforePropertyValue"},beforePropertyValue(){if("eof"===_l.type)throw tf(bl.EOF);Zl()},afterPropertyValue(){if("eof"===_l.type)throw tf(bl.EOF);switch(_l.value){case",":return void(Il="beforePropertyName");case"}":Ql()}},beforeArrayValue(){if("eof"===_l.type)throw tf(bl.EOF);"punctuator"!==_l.type||"]"!==_l.value?Zl():Ql()},afterArrayValue(){if("eof"===_l.type)throw tf(bl.EOF);switch(_l.value){case",":return void(Il="beforeArrayValue");case"]":Ql()}},end(){}};function Zl(){const e=function(){let e;switch(_l.type){case"punctuator":switch(_l.value){case"{":e={};break;case"[":e=[]}break;case"null":case"boolean":case"numeric":case"string":e=_l.value}return e}();if(jl&&"object"==typeof e&&(e._line=Ml,e._column=Ll),void 0===kl)kl=e;else{const t=Tl[Tl.length-1];Array.isArray(t)?jl&&"object"!=typeof e?t.push({value:e,_line:Ml,_column:Ll}):t.push(e):t[Pl]=jl&&"object"!=typeof e?{value:e,_line:Ml,_column:Ll}:e}!function(e){if(e&&"object"==typeof e)Tl.push(e),Il=Array.isArray(e)?"beforeArrayValue":"beforePropertyName";else{const e=Tl[Tl.length-1];Il=e?Array.isArray(e)?"afterArrayValue":"afterPropertyValue":"end"}}(e)}function Ql(){Tl.pop();const e=Tl[Tl.length-1];Il=e?Array.isArray(e)?"afterArrayValue":"afterPropertyValue":"end"}function ef(e){const t={"'":"\\'",'"':'\\"',"\\":"\\\\","\b":"\\b","\f":"\\f","\n":"\\n","\r":"\\r","\t":"\\t","\v":"\\v","\0":"\\0","\u2028":"\\u2028","\u2029":"\\u2029"};if(t[e])return t[e];if(e<" "){const t=e.charCodeAt(0).toString(16);return`\\x${`00${t}`.substring(t.length)}`}return e}function tf(e,t){let n="";switch(e){case bl.Char:n=void 0===t?`JSON5: invalid end of input at ${Ml}:${Ll}`:`JSON5: invalid character '${ef(t)}' at ${Ml}:${Ll}`;break;case bl.EOF:n=`JSON5: invalid end of input at ${Ml}:${Ll}`;break;case bl.Identifier:Ll-=5,n=`JSON5: invalid identifier character at ${Ml}:${Ll}`}const r=new nf(n);return r.lineNumber=Ml,r.columnNumber=Ll,r}class nf extends SyntaxError{}var rf=w&&w.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n);var u=Object.getOwnPropertyDescriptor(t,n);u&&!("get"in u?!t.__esModule:u.writable||u.configurable)||(u={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,r,u)}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),uf=w&&w.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),of=w&&w.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.prototype.hasOwnProperty.call(e,n)&&rf(t,e,n);return uf(t,e),t};Object.defineProperty(Y,"__esModule",{value:!0});var sf=Y.cleanWorkSpace=Ff=Y.executeInstallHvigor=yf=Y.isHvigorInstalled=mf=Y.isAllDependenciesInstalled=void 0;const cf=of(D.default),af=of(p.default),lf=b,ff=j,df=$,Df=X;let pf,Ef;var mf=Y.isAllDependenciesInstalled=function(){function e(e){const t=null==e?void 0:e.dependencies;return void 0===t?0:Object.getOwnPropertyNames(t).length}if(pf=gf(),Ef=Af(),e(pf)+1!==e(Ef))return!1;for(const e in null==pf?void 0:pf.dependencies)if(!(0,ff.hasNpmPackInPaths)(e,[lf.HVIGOR_PROJECT_DEPENDENCIES_HOME])||!hf(e,pf,Ef))return!1;return!0};function hf(e,t,n){return void 0!==n.dependencies&&(0,ff.offlinePluginConversion)(lf.HVIGOR_PROJECT_ROOT_DIR,t.dependencies[e])===n.dependencies[e]}var yf=Y.isHvigorInstalled=function(){return pf=gf(),Ef=Af(),(0,ff.hasNpmPackInPaths)(lf.HVIGOR_ENGINE_PACKAGE_NAME,[lf.HVIGOR_PROJECT_DEPENDENCIES_HOME])&&(0,ff.offlinePluginConversion)(lf.HVIGOR_PROJECT_ROOT_DIR,pf.hvigorVersion)===Ef.dependencies[lf.HVIGOR_ENGINE_PACKAGE_NAME]};const Cf={cwd:lf.HVIGOR_PROJECT_DEPENDENCIES_HOME,stdio:["inherit","inherit","inherit"]};var Ff=Y.executeInstallHvigor=function(){(0,df.logInfoPrintConsole)("Hvigor installing...");const e={dependencies:{}};e.dependencies[lf.HVIGOR_ENGINE_PACKAGE_NAME]=(0,ff.offlinePluginConversion)(lf.HVIGOR_PROJECT_ROOT_DIR,pf.hvigorVersion);try{cf.mkdirSync(lf.HVIGOR_PROJECT_DEPENDENCIES_HOME,{recursive:!0});const t=af.resolve(lf.HVIGOR_PROJECT_DEPENDENCIES_HOME,lf.DEFAULT_PACKAGE_JSON);cf.writeFileSync(t,JSON.stringify(e))}catch(e){(0,df.logErrorAndExit)(e)}!function(){const e=["config","set","store-dir",lf.HVIGOR_PNPM_STORE_PATH];(0,ff.executeCommand)(lf.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH,e,Cf)}(),(0,ff.executeCommand)(lf.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH,["install"],Cf)};function gf(){const e=af.resolve(lf.HVIGOR_PROJECT_WRAPPER_HOME,lf.DEFAULT_HVIGOR_CONFIG_JSON_FILE_NAME);return cf.existsSync(e)||(0,df.logErrorAndExit)(`Error: Hvigor config file ${e} does not exist.`),(0,Df.parseJsonFile)(e)}function Af(){return cf.existsSync(lf.HVIGOR_PROJECT_DEPENDENCY_PACKAGE_JSON_PATH)?(0,Df.parseJsonFile)(lf.HVIGOR_PROJECT_DEPENDENCY_PACKAGE_JSON_PATH):{dependencies:{}}}sf=Y.cleanWorkSpace=function(){if((0,df.logInfoPrintConsole)("Hvigor cleaning..."),!cf.existsSync(lf.HVIGOR_PROJECT_DEPENDENCIES_HOME))return;const e=cf.readdirSync(lf.HVIGOR_PROJECT_DEPENDENCIES_HOME);if(e&&0!==e.length){cf.existsSync(lf.HVIGOR_BOOT_JS_FILE_PATH)&&(0,ff.executeCommand)(process.argv[0],[lf.HVIGOR_BOOT_JS_FILE_PATH,"--stop-daemon"],{});try{e.forEach((e=>{cf.rmSync(af.resolve(lf.HVIGOR_PROJECT_DEPENDENCIES_HOME,e),{recursive:!0})}))}catch(e){(0,df.logErrorAndExit)(`The hvigor build tool cannot be installed. Please manually clear the workspace directory and synchronize the project again.\n\n Workspace Path: ${lf.HVIGOR_PROJECT_DEPENDENCIES_HOME}.`)}}};var vf={},Sf=w&&w.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n);var u=Object.getOwnPropertyDescriptor(t,n);u&&!("get"in u?!t.__esModule:u.writable||u.configurable)||(u={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,r,u)}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),wf=w&&w.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),Of=w&&w.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.prototype.hasOwnProperty.call(e,n)&&Sf(t,e,n);return wf(t,e),t};Object.defineProperty(vf,"__esModule",{value:!0});var bf=vf.executeBuild=void 0;const _f=b,Bf=Of(D.default),Pf=Of(p.default),kf=$;bf=vf.executeBuild=function(){const e=Pf.resolve(_f.HVIGOR_PROJECT_DEPENDENCIES_HOME,"node_modules","@ohos","hvigor","bin","hvigor.js");try{const t=Bf.realpathSync(e);require(t)}catch(t){(0,kf.logErrorAndExit)(`Error: ENOENT: no such file ${e},delete ${_f.HVIGOR_PROJECT_DEPENDENCIES_HOME} and retry.`)}},function(){if(O.checkNpmConifg(),O.environmentHandler(),O.isPnpmAvailable()||O.executeInstallPnpm(),yf()&&mf())bf();else{sf();try{Ff()}catch(e){return void sf()}bf()}}(); \ No newline at end of file diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/hvigorfile.ts.tmpl b/packages/flutter_tools/templates/app_shared/ohos.tmpl/hvigorfile.ts.tmpl new file mode 100644 index 0000000000000000000000000000000000000000..5a172b770e3b15f67c12152d00f38f2084d3915b --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/hvigorfile.ts.tmpl @@ -0,0 +1,17 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +export { appTasks } from '@ohos/hvigor-ohos-plugin'; \ No newline at end of file diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/hvigorw.bat.tmpl b/packages/flutter_tools/templates/app_shared/ohos.tmpl/hvigorw.bat.tmpl new file mode 100644 index 0000000000000000000000000000000000000000..6861293e47dfd0186da380321b73be9033507e24 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/hvigorw.bat.tmpl @@ -0,0 +1,64 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Hvigor startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +set WRAPPER_MODULE_PATH=%APP_HOME%\hvigor\hvigor-wrapper.js +set NODE_EXE=node.exe + +goto start + +:start +@rem Find node.exe +if defined NODE_HOME goto findNodeFromNodeHome + +%NODE_EXE% --version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: NODE_HOME is not set and no 'node' command could be found in your PATH. +echo. +echo Please set the NODE_HOME variable in your environment to match the +echo location of your NodeJs installation. + +goto fail + +:findNodeFromNodeHome +set NODE_HOME=%NODE_HOME:"=% +set NODE_EXE_PATH=%NODE_HOME%/%NODE_EXE% + +if exist "%NODE_EXE_PATH%" goto execute +echo. +echo ERROR: NODE_HOME is not set and no 'node' command could be found in your PATH. +echo. +echo Please set the NODE_HOME variable in your environment to match the +echo location of your NodeJs installation. + +goto fail + +:execute +@rem Execute hvigor +"%NODE_EXE%" %WRAPPER_MODULE_PATH% %* + +if "%ERRORLEVEL%" == "0" goto hvigorwEnd + +:fail +exit /b 1 + +:hvigorwEnd +if "%OS%" == "Windows_NT" endlocal + +:end diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/hvigorw.tmpl b/packages/flutter_tools/templates/app_shared/ohos.tmpl/hvigorw.tmpl new file mode 100644 index 0000000000000000000000000000000000000000..5efd8343d3232bdd1d9b7f67a3326034054c5396 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/hvigorw.tmpl @@ -0,0 +1,61 @@ +#!/bin/bash + +# Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# ---------------------------------------------------------------------------- +# Hvigor startup script, version 1.0.0 +# +# Required ENV vars: +# ------------------ +# NODE_HOME - location of a Node home dir +# or +# Add /usr/local/nodejs/bin to the PATH environment variable +# ---------------------------------------------------------------------------- + +HVIGOR_APP_HOME=$(dirname $(readlink -f $0)) +HVIGOR_WRAPPER_SCRIPT=${HVIGOR_APP_HOME}/hvigor/hvigor-wrapper.js +warn() { + echo "" + echo -e "\033[1;33m`date '+[%Y-%m-%d %H:%M:%S]'`$@\033[0m" +} + +error() { + echo "" + echo -e "\033[1;31m`date '+[%Y-%m-%d %H:%M:%S]'`$@\033[0m" +} + +fail() { + error "$@" + exit 1 +} + +# Determine node to start hvigor wrapper script +if [ -n "${NODE_HOME}" ];then + EXECUTABLE_NODE="${NODE_HOME}/bin/node" + if [ ! -x "$EXECUTABLE_NODE" ];then + fail "ERROR: NODE_HOME is set to an invalid directory,check $NODE_HOME\n\nPlease set NODE_HOME in your environment to the location where your nodejs installed" + fi +else + EXECUTABLE_NODE="node" + which ${EXECUTABLE_NODE} > /dev/null 2>&1 || fail "ERROR: NODE_HOME is not set and not 'node' command found in your path" +fi + +# Check hvigor wrapper script +if [ ! -r "$HVIGOR_WRAPPER_SCRIPT" ];then + fail "ERROR: Couldn't find hvigor/hvigor-wrapper.js in ${HVIGOR_APP_HOME}" +fi + +# start hvigor-wrapper script +exec "${EXECUTABLE_NODE}" \ + "${HVIGOR_WRAPPER_SCRIPT}" "$@" diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/local.properties.tmpl b/packages/flutter_tools/templates/app_shared/ohos.tmpl/local.properties.tmpl new file mode 100644 index 0000000000000000000000000000000000000000..ad6307bb8ff8a70f57782f3c0e80ccfd9f9e8259 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/local.properties.tmpl @@ -0,0 +1,25 @@ +# Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# This file is automatically generated by DevEco Studio. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file should *NOT* be checked into Version Control Systems, +# as it contains information specific to your local configuration. +# +# For customization when using a Version Control System, please read the header note. + +#hwsdk.dir={{hosSdkHome}} +sdk.dir={{ohosSdkHome}} +nodejs.dir={{nodeHome}} \ No newline at end of file diff --git a/packages/flutter_tools/templates/app_shared/ohos.tmpl/oh-package.json5 b/packages/flutter_tools/templates/app_shared/ohos.tmpl/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..a2408ea9cb7b309e6ad95e27a4c8b88985ae57c6 --- /dev/null +++ b/packages/flutter_tools/templates/app_shared/ohos.tmpl/oh-package.json5 @@ -0,0 +1,28 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +{ + "name": "apptemplate", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.6" + } +} diff --git a/packages/flutter_tools/templates/template_manifest.json b/packages/flutter_tools/templates/template_manifest.json index c452abec1b01b32c0e2f8b50c0d1a52277965be4..2c67626f30ea3def1555ea271f33f3e87515eeee 100644 --- a/packages/flutter_tools/templates/template_manifest.json +++ b/packages/flutter_tools/templates/template_manifest.json @@ -139,6 +139,47 @@ "templates/app_shared/windows.tmpl/runner/win32_window.cpp", "templates/app_shared/windows.tmpl/runner/win32_window.h", + "templates/app_shared/ohos.tmpl/.gitignore", + "templates/app_shared/ohos.tmpl/build-profile.json5.tmpl", + "templates/app_shared/ohos.tmpl/hvigorfile.ts.tmpl", + "templates/app_shared/ohos.tmpl/hvigorw.bat.tmpl", + "templates/app_shared/ohos.tmpl/hvigorw.tmpl", + "templates/app_shared/ohos.tmpl/local.properties", + "templates/app_shared/ohos.tmpl/oh-package.json5", + "templates/app_shared/ohos.tmpl/AppScope/app.json5.tmpl", + "templates/app_shared/ohos.tmpl/AppScope/resources/base/element/string.json.tmpl", + "templates/app_shared/ohos.tmpl/AppScope/resources/base/media/app_icon.png", + "templates/app_shared/ohos.tmpl/entry/.gitignore", + "templates/app_shared/ohos.tmpl/entry/build-profile.json5.tmpl", + "templates/app_shared/ohos.tmpl/entry/hvigorfile.ts.tmpl", + "templates/app_shared/ohos.tmpl/entry/oh-package.json5.tmpl", + "templates/app_shared/ohos.tmpl/entry/src/main/module.json5", + "templates/app_shared/ohos.tmpl/entry/src/main/ets/entryability/EntryAbility.ts.tmpl", + "templates/app_shared/ohos.tmpl/entry/src/main/ets/pages/Index.ets.tmpl", + "templates/app_shared/ohos.tmpl/entry/src/main/resources/base/element/color.json", + "templates/app_shared/ohos.tmpl/entry/src/main/resources/base/element/string.json", + "templates/app_shared/ohos.tmpl/entry/src/main/resources/base/media/icon.png", + "templates/app_shared/ohos.tmpl/entry/src/main/resources/base/profile/main_pages.json", + "templates/app_shared/ohos.tmpl/entry/src/main/resources/en_US/element/string.json", + "templates/app_shared/ohos.tmpl/entry/src/main/resources/zh_CN/element/string.json", + "templates/app_shared/ohos.tmpl/entry/src/ohosTest/module.json5.tmpl", + "templates/app_shared/ohos.tmpl/entry/src/ohosTest/ets/test/Ability.test.ets", + "templates/app_shared/ohos.tmpl/entry/src/ohosTest/ets/test/List.test.ets", + "templates/app_shared/ohos.tmpl/entry/src/ohosTest/ets/testability/TestAbility.ets", + "templates/app_shared/ohos.tmpl/entry/src/ohosTest/ets/testability/pages/Index.ets", + "templates/app_shared/ohos.tmpl/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts", + "templates/app_shared/ohos.tmpl/entry/src/ohosTest/resources/base/element/color.json", + "templates/app_shared/ohos.tmpl/entry/src/ohosTest/resources/base/element/string.json", + "templates/app_shared/ohos.tmpl/entry/src/ohosTest/resources/base/media/icon.png", + "templates/app_shared/ohos.tmpl/entry/src/ohosTest/resources/base/profile/test_pages.json.tmpl", + "templates/app_shared/ohos.tmpl/hvigor/hvigor-config.json5.tmpl", + "templates/app_shared/ohos.tmpl/hvigor/hvigor-wrapper.js.tmpl", + "templates/app_shared/ohos.tmpl/har/flutter_embedding.har.debug", + "templates/app_shared/ohos.tmpl/har/flutter_embedding.har.release", + "templates/app_shared/ohos.tmpl/local.properties.tmpl", + "templates/app_shared/ohos.tmpl/dta/icudtl.dat", + "templates/app_shared/ohos.tmpl/entry/libs/arm64-v8a/libc++_shared.so", + "templates/app_test_widget/test/widget_test.dart.tmpl", "templates/cocoapods/Podfile-ios-objc", diff --git a/packages/flutter_tools/test/src/fakes.dart b/packages/flutter_tools/test/src/fakes.dart index 386f56babe58003eeb549feff5a9ce52fa008dd6..2c1ceaf724cd527b5ef2acba8e00e3958b5933eb 100644 --- a/packages/flutter_tools/test/src/fakes.dart +++ b/packages/flutter_tools/test/src/fakes.dart @@ -24,8 +24,8 @@ class FakeDyldEnvironmentArtifact extends ArtifactSet { FakeDyldEnvironmentArtifact() : super(DevelopmentArtifact.iOS); @override Map get environment => { - 'DYLD_LIBRARY_PATH': '/path/to/libraries', - }; + 'DYLD_LIBRARY_PATH': '/path/to/libraries', + }; @override Future isUpToDate(FileSystem fileSystem) => Future.value(true); @@ -34,8 +34,9 @@ class FakeDyldEnvironmentArtifact extends ArtifactSet { String get name => 'fake'; @override - Future update(ArtifactUpdater artifactUpdater, Logger logger, FileSystem fileSystem, OperatingSystemUtils operatingSystemUtils, {bool offline = false}) async { - } + Future update(ArtifactUpdater artifactUpdater, Logger logger, + FileSystem fileSystem, OperatingSystemUtils operatingSystemUtils, + {bool offline = false}) async {} } /// A fake process implementation which can be provided all necessary values. @@ -46,8 +47,8 @@ class FakeProcess implements Process { IOSink? stdin, this.stdout = const Stream>.empty(), this.stderr = const Stream>.empty(), - }) : exitCode = exitCode ?? Future.value(0), - stdin = stdin ?? MemoryIOSink(); + }) : exitCode = exitCode ?? Future.value(0), + stdin = stdin ?? MemoryIOSink(); @override final int pid; @@ -116,8 +117,9 @@ class MemoryIOSink implements IOSink { (List data) { try { add(data); - // Catches all exceptions to propagate them to the completer. - } catch (err, stack) { // ignore: avoid_catches_without_on_clauses + // Catches all exceptions to propagate them to the completer. + } catch (err, stack) { + // ignore: avoid_catches_without_on_clauses sub.cancel(); completer.completeError(err, stack); } @@ -140,12 +142,12 @@ class MemoryIOSink implements IOSink { } @override - void writeln([ Object? obj = '' ]) { + void writeln([Object? obj = '']) { add(encoding.encode('$obj\n')); } @override - void writeAll(Iterable objects, [ String separator = '' ]) { + void writeAll(Iterable objects, [String separator = '']) { bool addSeparator = false; for (final dynamic object in objects) { if (addSeparator) { @@ -157,7 +159,7 @@ class MemoryIOSink implements IOSink { } @override - void addError(dynamic error, [ StackTrace? stackTrace ]) { + void addError(dynamic error, [StackTrace? stackTrace]) { throw UnimplementedError(); } @@ -165,17 +167,18 @@ class MemoryIOSink implements IOSink { Future get done => close(); @override - Future close() async { } + Future close() async {} @override - Future flush() async { } + Future flush() async {} void clear() { writes.clear(); } String getAndClear() { - final String result = utf8.decode(writes.expand((List l) => l).toList()); + final String result = + utf8.decode(writes.expand((List l) => l).toList()); clear(); return result; } @@ -188,6 +191,7 @@ class MemoryStdout extends MemoryIOSink implements io.Stdout { assert(value != null); _hasTerminal = value; } + bool _hasTerminal = true; @override @@ -199,6 +203,7 @@ class MemoryStdout extends MemoryIOSink implements io.Stdout { assert(value != null); _supportsAnsiEscapes = value; } + bool _supportsAnsiEscapes = true; @override @@ -208,6 +213,7 @@ class MemoryStdout extends MemoryIOSink implements io.Stdout { } throw const io.StdoutException('unspecified mock value'); } + set terminalColumns(int value) => _terminalColumns = value; int? _terminalColumns; @@ -218,6 +224,7 @@ class MemoryStdout extends MemoryIOSink implements io.Stdout { } throw const io.StdoutException('unspecified mock value'); } + set terminalLines(int value) => _terminalLines = value; int? _terminalLines; } @@ -244,8 +251,10 @@ class FakeStdio extends Stdio { @override bool hasTerminal = true; - List get writtenToStdout => _stdout.writes.map(_stdout.encoding.decode).toList(); - List get writtenToStderr => _stderr.writes.map(_stderr.encoding.decode).toList(); + List get writtenToStdout => + _stdout.writes.map(_stdout.encoding.decode).toList(); + List get writtenToStderr => + _stderr.writes.map(_stderr.encoding.decode).toList(); } class FakeStdin extends Fake implements Stdin { @@ -279,8 +288,8 @@ class FakeStdin extends Fake implements Stdin { } class FakePlistParser implements PlistParser { - FakePlistParser([Map? underlyingValues]): - _underlyingValues = underlyingValues ?? {}; + FakePlistParser([Map? underlyingValues]) + : _underlyingValues = underlyingValues ?? {}; final Map _underlyingValues; @@ -303,8 +312,7 @@ class FakePlistParser implements PlistParser { } class FakeBotDetector implements BotDetector { - const FakeBotDetector(bool isRunningOnBot) - : _isRunningOnBot = isRunningOnBot; + const FakeBotDetector(bool isRunningOnBot) : _isRunningOnBot = isRunningOnBot; @override Future get isRunningOnBot async => _isRunningOnBot; @@ -384,7 +392,7 @@ class FakeFlutterVersion implements FlutterVersion { } @override - Future ensureVersionFile() async { } + Future ensureVersionFile() async {} @override String getBranchName({bool redactUnknownBranches = false}) { @@ -406,6 +414,7 @@ class FakeFlutterVersion implements FlutterVersion { // config. If not otherwise specified, all values default to false. class TestFeatureFlags implements FeatureFlags { TestFeatureFlags({ + this.isOhosEnabled = false, this.isLinuxEnabled = false, this.isMacOSEnabled = false, this.isWebEnabled = false, @@ -417,6 +426,9 @@ class TestFeatureFlags implements FeatureFlags { this.areCustomDevicesEnabled = false, }); + @override + final bool isOhosEnabled; + @override final bool isLinuxEnabled; @@ -447,6 +459,8 @@ class TestFeatureFlags implements FeatureFlags { @override bool isEnabled(Feature feature) { switch (feature) { + case flutterOhosFeature: + return isOhosEnabled; case flutterWebFeature: return isWebEnabled; case flutterLinuxDesktopFeature: @@ -476,7 +490,7 @@ class FakeOperatingSystemUtils extends Fake implements OperatingSystemUtils { final List> chmods = >[]; @override - void makeExecutable(File file) { } + void makeExecutable(File file) {} @override HostPlatform hostPlatform = HostPlatform.linux_x64; @@ -493,10 +507,10 @@ class FakeOperatingSystemUtils extends Fake implements OperatingSystemUtils { List whichAll(String execName) => []; @override - void unzip(File file, Directory targetDirectory) { } + void unzip(File file, Directory targetDirectory) {} @override - void unpack(File gzippedTarFile, Directory targetDirectory) { } + void unpack(File gzippedTarFile, Directory targetDirectory) {} @override Stream> gzipLevel1Stream(Stream> stream) => stream; @@ -548,13 +562,12 @@ class FakeStopwatch implements Stopwatch { } class FakeStopwatchFactory implements StopwatchFactory { - FakeStopwatchFactory({ - Stopwatch? stopwatch, - Map? stopwatches - }) : stopwatches = { - if (stopwatches != null) ...stopwatches, - if (stopwatch != null) '': stopwatch, - }; + FakeStopwatchFactory( + {Stopwatch? stopwatch, Map? stopwatches}) + : stopwatches = { + if (stopwatches != null) ...stopwatches, + if (stopwatch != null) '': stopwatch, + }; Map stopwatches;