diff --git a/OpenHarmony/.eslintignore b/OpenHarmony/.eslintignore new file mode 100644 index 0000000..d4dc2e5 --- /dev/null +++ b/OpenHarmony/.eslintignore @@ -0,0 +1 @@ +hvigor/hvigor-wrapper.js \ No newline at end of file diff --git a/OpenHarmony/.gitignore b/OpenHarmony/.gitignore new file mode 100644 index 0000000..e1df0e4 --- /dev/null +++ b/OpenHarmony/.gitignore @@ -0,0 +1,12 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +/oh-package-lock.json5 diff --git a/OpenHarmony/AppScope/app.json5 b/OpenHarmony/AppScope/app.json5 new file mode 100644 index 0000000..01a926b --- /dev/null +++ b/OpenHarmony/AppScope/app.json5 @@ -0,0 +1,10 @@ +{ + "app": { + "bundleName": "cn.openharmony.jwks_rsa", + "vendor": "example", + "versionCode": 1000000, + "versionName": "2.0.1", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/OpenHarmony/AppScope/resources/base/element/string.json b/OpenHarmony/AppScope/resources/base/element/string.json new file mode 100644 index 0000000..1531ce6 --- /dev/null +++ b/OpenHarmony/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "jwks_rsa" + } + ] +} diff --git a/OpenHarmony/AppScope/resources/base/media/app_icon.png b/OpenHarmony/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000..ce307a8 Binary files /dev/null and b/OpenHarmony/AppScope/resources/base/media/app_icon.png differ diff --git a/OpenHarmony/CHANGELOG.md b/OpenHarmony/CHANGELOG.md new file mode 100644 index 0000000..b4855f7 --- /dev/null +++ b/OpenHarmony/CHANGELOG.md @@ -0,0 +1,23 @@ +## 2.0.1 + +- Release 2.0.1 + +## 2.0.1-rc.0 +- Code obfuscation +- Modified the compilation and build warning prompt + +## 2.0.0 +- DevEco Studio 版本: 4.1 Canary(4.1.3.317) +- OpenHarmony SDK:API11 (4.1.0.36) +- ArkTS新语法适配 + +### v1.0.0 + +- 已实现功能 + 1、支持从URL中获取公钥材料。 + 2、支持对获取密钥的速率设置。 + 3、支持从缓存中获取公钥材料。 + 4、支持生成公钥,获取密钥属性(kid、kty、alg、usage等)。 + +- 支持算法 + 1、RSA2048 \ No newline at end of file diff --git a/OpenHarmony/LICENSE b/OpenHarmony/LICENSE new file mode 100644 index 0000000..006c80b --- /dev/null +++ b/OpenHarmony/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Sandrino Di Mattia + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/OpenHarmony/NOTICE b/OpenHarmony/NOTICE new file mode 100644 index 0000000..94500ea --- /dev/null +++ b/OpenHarmony/NOTICE @@ -0,0 +1,34 @@ +OPEN SOURCE SOFTWARE NOTICE + +Please note we provide an open source software notice for the third party open source software along with this software and/or this software component (in the following just “this SOFTWARE”). The open source software licenses are granted by the respective right holders. + +Warranty Disclaimer +THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS. + +Copyright Notice and License Texts + +Software jwks-rsa 1.0.0 + +Copyright notice: +Copyright (c) 2016 Sandrino Di Mattia + +License: The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/OpenHarmony/OAT.xml b/OpenHarmony/OAT.xml new file mode 100644 index 0000000..b051a7a --- /dev/null +++ b/OpenHarmony/OAT.xml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OpenHarmony/README.OpenSource b/OpenHarmony/README.OpenSource new file mode 100644 index 0000000..aa60e8e --- /dev/null +++ b/OpenHarmony/README.OpenSource @@ -0,0 +1,11 @@ +[ + { + "Name": "jwks-rsa", + "License": "MIT License", + "License File": " LICENSE", + "Version Number": "1.0.0", + "Owner" : "xiafeng@huawei.com", + "Upstream URL": "https://github.com/auth0/node-jwks-rsa", + "Description": "A library to retrieve RSA public keys from a JWKS (JSON Web Key Set) endpoint." + } +] diff --git a/OpenHarmony/README.md b/OpenHarmony/README.md new file mode 100644 index 0000000..efa8643 --- /dev/null +++ b/OpenHarmony/README.md @@ -0,0 +1,145 @@ +# jwks-rsa + +## Introduction + +jwks-rsa is a library that retrieves keys from JSON Web Key Set (JWKS) endpoints to generate public keys. It uses the asymmetric public key encryption algorithm (RSA) and asymmetric elliptic curve encryption algorithm (ECC) for encryption. + +## How to Install + +```shell +ohpm install @ohos/jwks_rsa +``` +For details about the OpenHarmony ohpm environment configuration, see [OpenHarmony HAR](https://gitcode.com/openharmony-tpc/docs/blob/master/OpenHarmony_har_usage.en.md). + +## How to Use +1. Instantiate **JwksClient** and set the corresponding attributes. + + ``` +this.client = new JwksClient({ + jwksUri: 'https://sandrino.auth0.com/.well-known/jwks.json', + requestHeaders: {}, // Optional + timeout: 30000, // Defaults to 30s + cache: false, + rateLimit: true + }); +}, +``` + +2. Obtain **publicKey** and the attribute value. + + Public key encryption is implemented using the encryption framework (@ohos.security.cryptoFramework) of OpenHarmony. For details, see [Encryption and Decryption with an RSA Asymmetric Key Pair (PKCS1_OAEP)](https://gitcode.com/openharmony/docs/blob/master/en/application-dev/security/CryptoArchitectureKit/crypto-rsa-asym-encrypt-decrypt-pkcs1_oaep.md). +``` + function compareRsaPubKeyBySpec(rsaKeySpec, n, e) { + if (typeof n === 'string' || typeof e === 'string') { + console.error('type is string'); + return false; + } + if (typeof n === 'number' || typeof e === 'number') { + console.error('type is number'); + return false; + } + if (rsaKeySpec.params.n != n) { + return false; + } + if (rsaKeySpec.pk != e) { + return false; + } + return true; + } + + let n = buffer.from(key.n,'base64') + let e = buffer.from(key.e,'base64') + let bN = base64ToBigNum(n); + let eN = base64ToBigNum(e); + var commonSpec = { + algName:"RSA", + specType:cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC, + n:BigInt(bN) + } + var rsaSpec = { + algName:"RSA", + specType:cryptoFramework.AsyKeySpecType.PUBLIC_KEY_SPEC, + params : commonSpec, + pk :BigInt(eN), + } + // Generate an RSA key pair based on the RSA key pair parameter. + asyKeyGenerator = cryptoFramework.createAsyKeyGeneratorBySpec(rsaSpec); + // Generate a publicKey instance. + const pubKey = await asyKeyGenerator.generatePubKey() + // Obtain the specified parameters of publicKey. + let nBN = pubKey.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.RSA_N_BN); + let eBN = pubKey.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.RSA_PK_BN); + Compare the RSA public key specifications with the expected value. + if (compareRsaPubKeyBySpec(rsaSpec, nBN, eBN) != true) { + console.error("jwks_rsa error pub key big number") + } else { + console.info("jwks_rsa n, e in the pubKey are same as the spec."); + return pubKey; + } +``` + + Obtain publicKey and the attribute value. +``` + let signingKey = await this.client.getSigningKey(kid) + this.kid = signingKey.kid + this.alg = signingKey.alg + this.kty = signingKey.kty + this.use = signingKey.use + this.publicKey = await signingKey.getPublicKey() +``` + +## Constraints +This project has been verified in the following version: +- DevEco Studio: 4.1 Canary (4.1.3.317) + +- OpenHarmony SDK: API11 (4.1.0.36) + +## Directory Structure + +```` +|---- OHOS_APP_jwks-rsa +| |---- entry # Sample code +| |---- jwks-rsa # OHOS_APP_jwks-rsa library +| |---- src + |----main + |----js + |----components + |----errors + |----ArgumentError.js # Error logs + |----JwksError.js # Error logs + |----JwksRateLimitError.js # Error logs + |----SigningKeyNotFoundError.js # Error logs + |----integrations + |----config.js # Encryption algorithms + |----express.js # Secret provider generation by expressJwtSecret + |----hapi.js # Secret provider generation by hapiJwtSecret + |----koa.js # Secret provider generation by koaJwtSecret + |----passport.js # Secret provider generation by passportJwtSecret + |----wrappers + |----cache.js # Key acquisition from the cache + |----callbackSupport.js # Callbacks + |----interceptor.js # Callbacks + |----rateLimit.js # Key requesting rate + |----request.js # Network requests + |----JwksClient.js # JwksClient constructor + |----utils.js # Encryption algorithms +| |---- README.md # Readme +| |---- README_zh.md # Readme +```` + +## About obfuscation +- Code obfuscation, please see[Code Obfuscation](https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/arkts-utils/source-obfuscation.md) +- If you want the jwks_rsa library not to be obfuscated during code obfuscation, you need to add corresponding exclusion rules in the obfuscation rule configuration file obfuscation-rules.txt: + +``` +-keep +./oh_modules/@ohos/jwks_rsa +``` + +## How to Contribute + +If you find any problem when using jwks-rsa, you can submit an [Issue](https://gitcode.com/openharmony-tpc/openharmony_tpc_samples/issues) or a [PR](https://gitcode.com/openharmony-tpc/openharmony_tpc_samples/pulls) to us. + +## License + +This project is licensed under the terms of the [MIT License](https://gitcode.com/openharmony-tpc/openharmony_tpc_samples/blob/master/jwks-rsa/LICENSE). diff --git a/OpenHarmony/README_zh.md b/OpenHarmony/README_zh.md new file mode 100644 index 0000000..471b7cd --- /dev/null +++ b/OpenHarmony/README_zh.md @@ -0,0 +1,145 @@ +# jwks-rsa + +## 简介 + +从 JWKS(JSON Web 密钥集)端点检索密钥来生成公钥的库,其加密方式采用了非对称公钥加密算法(RSA)和非对称椭圆曲线加密算法(ECC)。 + +## 下载安装 + +```shell +ohpm install @ohos/jwks_rsa +``` +OpenHarmony ohpm环境配置等更多内容,请参考 [如何安装OpenHarmony ohpm包](https://gitcode.com/openharmony-tpc/docs/blob/master/OpenHarmony_har_usage.md) 。 + +## 使用说明 +1. 初始化:实例化JwksClient和设置对应的属性 + + ``` +this.client = new JwksClient({ + jwksUri: 'https://sandrino.auth0.com/.well-known/jwks.json', + requestHeaders: {}, // Optional + timeout: 30000, // Defaults to 30s + cache: false, + rateLimit: true + }); +}, +``` + +2. 获取publicKey和属性值: + + 公钥加密实现是使用OH子系统的加密框架(@ohos.security.cryptoFramework)。具体实现参考(https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/security/CryptoArchitectureKit/crypto-rsa-asym-encrypt-decrypt-pkcs1_oaep.md) 。 +``` + function compareRsaPubKeyBySpec(rsaKeySpec, n, e) { + if (typeof n === 'string' || typeof e === 'string') { + console.error('type is string'); + return false; + } + if (typeof n === 'number' || typeof e === 'number') { + console.error('type is number'); + return false; + } + if (rsaKeySpec.params.n != n) { + return false; + } + if (rsaKeySpec.pk != e) { + return false; + } + return true; + } + + let n = buffer.from(key.n,'base64') + let e = buffer.from(key.e,'base64') + let bN = base64ToBigNum(n); + let eN = base64ToBigNum(e); + var commonSpec = { + algName:"RSA", + specType:cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC, + n:BigInt(bN) + } + var rsaSpec = { + algName:"RSA", + specType:cryptoFramework.AsyKeySpecType.PUBLIC_KEY_SPEC, + params : commonSpec, + pk :BigInt(eN), + } + //根据RSA密钥对参数生成RSA密钥对 + asyKeyGenerator = cryptoFramework.createAsyKeyGeneratorBySpec(rsaSpec); + //生成公钥实例 + const pubKey = await asyKeyGenerator.generatePubKey() + //获取公钥的指定参数 + let nBN = pubKey.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.RSA_N_BN); + let eBN = pubKey.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.RSA_PK_BN); + 将RSA公钥规范与预期值进行比较 + if (compareRsaPubKeyBySpec(rsaSpec, nBN, eBN) != true) { + console.error("jwks_rsa error pub key big number") + } else { + console.info("jwks_rsa n, e in the pubKey are same as the spec."); + return pubKey; + } +``` + + 获取publicKey和属性值 +``` + let signingKey = await this.client.getSigningKey(kid) + this.kid = signingKey.kid + this.alg = signingKey.alg + this.kty = signingKey.kty + this.use = signingKey.use + this.publicKey = await signingKey.getPublicKey() +``` + +## 约束与限制 +在下述版本验证通过: +- DevEco Studio 版本: 4.1 Canary(4.1.3.317) + +- OpenHarmony SDK:API11 (4.1.0.36) + +## 目录结构 + +```` +|---- OHOS_APP_jwks-rsa +| |---- entry # 示例代码文件夹 +| |---- jwks-rsa # OHOS_APP_jwks-rsa库文件夹 +| |---- src + |----main + |----js + |----components + |----errors + |----ArgumentError.js #错误日志 + |----JwksError.js #错误日志 + |----JwksRateLimitError.js #错误日志 + |----SigningKeyNotFoundError.js #错误日志 + |----integrations + |----config.js #支持的加密算法 + |----express.js #expressJwtSecret生成秘密提供者 + |----hapi.js #hapiJwtSecret生成秘密提供者 + |----koa.js #koaJwtSecret生成秘密提供者 + |----passport.js #passportJwtSecret生成秘密提供者 + |----wrappers + |----cache.js #从缓存中获取密钥 + |----callbackSupport.js #回调方法 + |----interceptor.js #回调方法 + |----rateLimit.js #设置请求密钥的速率 + |----request.js #网路请求 + |----JwksClient.js #构造方法 + |----utils.js #加密算法 +| |---- README.md #使用方法 +| |---- README_zh.md #使用方法 +```` + +## 关于混淆 +- 代码混淆,请查看[代码混淆简介](https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/arkts-utils/source-obfuscation.md) +- 如果希望jwks_rsa库在代码混淆过程中不会被混淆,需要在混淆规则配置文件obfuscation-rules.txt中添加相应的排除规则: + +``` +-keep +./oh_modules/@ohos/jwks_rsa +``` + +## 贡献代码 + +使用过程中发现任何问题都可以提 [Issue](https://gitcode.com/openharmony-tpc/openharmony_tpc_samples/issues) 给组件,当然,也非常欢迎发 [PR](https://gitcode.com/openharmony-tpc/openharmony_tpc_samples/pulls)共建 。 + +## 开源协议 + +本项目基于 [MIT License](https://gitcode.com/openharmony-tpc/openharmony_tpc_samples/blob/master/jwks-rsa/LICENSE) ,请自由地享受和参与开源。 \ No newline at end of file diff --git a/OpenHarmony/TEST.md b/OpenHarmony/TEST.md new file mode 100644 index 0000000..f5dc1c4 --- /dev/null +++ b/OpenHarmony/TEST.md @@ -0,0 +1,12 @@ +# jwks-rsa单元测试用例 + +该测试用例基于OpenHarmony系统下,采用[原库测试用例](https://gitcode.com/openharmony-tpc/openharmony_tpc_samples/tree/master/jwks-rsa/entry/src/ohosTest/ets/test) +进行单元测试 + +单元测试用例覆盖情况 + +| 接口名 |是否通过 |备注| +|:--------------------------------------:|:---:|:---:| +| getKeys() | pass | | +| getSigningKeys() |pass | | +| getSigningKey(kid) |pass | | diff --git a/OpenHarmony/build-profile.json5 b/OpenHarmony/build-profile.json5 new file mode 100644 index 0000000..f0668ed --- /dev/null +++ b/OpenHarmony/build-profile.json5 @@ -0,0 +1,41 @@ +{ + "app": { + "signingConfigs": [], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compileSdkVersion": 10, + "compatibleSdkVersion": 10, + "targetSdkVersion": 10, + "runtimeOS": "OpenHarmony" + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + }, + { + "name": "library", + "srcPath": "./library" + } + ] +} \ No newline at end of file diff --git a/OpenHarmony/entry/.gitignore b/OpenHarmony/entry/.gitignore new file mode 100644 index 0000000..db98584 --- /dev/null +++ b/OpenHarmony/entry/.gitignore @@ -0,0 +1,12 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +/.preview \ No newline at end of file diff --git a/OpenHarmony/entry/build-profile.json5 b/OpenHarmony/entry/build-profile.json5 new file mode 100644 index 0000000..037178e --- /dev/null +++ b/OpenHarmony/entry/build-profile.json5 @@ -0,0 +1,27 @@ +{ + "apiType": "stageMode", + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": true, + "files": [ + "./obfuscation-rules.txt" + // 混淆规则文件 + ] + } + } + } + } + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/OpenHarmony/entry/hvigorfile.ts b/OpenHarmony/entry/hvigorfile.ts new file mode 100644 index 0000000..c6edcd9 --- /dev/null +++ b/OpenHarmony/entry/hvigorfile.ts @@ -0,0 +1,6 @@ +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/OpenHarmony/entry/obfuscation-rules.txt b/OpenHarmony/entry/obfuscation-rules.txt new file mode 100644 index 0000000..ee27f89 --- /dev/null +++ b/OpenHarmony/entry/obfuscation-rules.txt @@ -0,0 +1,26 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation + +-keep +./oh_modules/@ohos/jwks_rsa \ No newline at end of file diff --git a/OpenHarmony/entry/oh-package.json5 b/OpenHarmony/entry/oh-package.json5 new file mode 100644 index 0000000..73ca02d --- /dev/null +++ b/OpenHarmony/entry/oh-package.json5 @@ -0,0 +1,12 @@ +{ + "license": "Apache 2.0", + "devDependencies": {}, + "author": "", + "name": "entry", + "description": "Please describe the basic information.", + "main": "", + "version": "2.0.1", + "dependencies": { + "@ohos/jwks_rsa": "file:../library" + } +} \ No newline at end of file diff --git a/OpenHarmony/entry/src/main/ets/entryability/EntryAbility.ts b/OpenHarmony/entry/src/main/ets/entryability/EntryAbility.ts new file mode 100644 index 0000000..beda874 --- /dev/null +++ b/OpenHarmony/entry/src/main/ets/entryability/EntryAbility.ts @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2022 Huawei Device 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 AbilityConstant from '@ohos.app.ability.AbilityConstant'; +import hilog from '@ohos.hilog'; +import UIAbility from '@ohos.app.ability.UIAbility'; +import Want from '@ohos.app.ability.Want'; +import window from '@ohos.window'; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage) { + // Main window is created, set main page for this ability + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/TestPage', (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() { + // Main window is destroyed, release UI related resources + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground() { + // Ability has brought to foreground + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground() { + // Ability has back to background + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +} diff --git a/OpenHarmony/entry/src/main/ets/pages/TestPage.ets b/OpenHarmony/entry/src/main/ets/pages/TestPage.ets new file mode 100644 index 0000000..19b30f6 --- /dev/null +++ b/OpenHarmony/entry/src/main/ets/pages/TestPage.ets @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2022 Huawei Device 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 {JwksClient} from "@ohos/jwks_rsa" +import util from '@ohos.util'; +import cryptoFramework from "@ohos.security.cryptoFramework"; + + +// let that:ESObject; +class Option{ + jwksUri:string; + requestHeaders: null | object; // Optional + timeout:number=5000; // Defaults to 30s + cache:boolean; + rateLimit: boolean + + constructor(jwksUri:string, + requestHeaders: null | object, // Optional + timeout:number, // Defaults to 30s + cache:boolean, + rateLimit: boolean) { + this.jwksUri = jwksUri; + this.requestHeaders = requestHeaders; + this.timeout = timeout; + this.cache = cache; + this.rateLimit = rateLimit; + } +} +@Entry +@Component +struct Index { + @State kid: string = '' + @State alg: string = '' + @State kty: string = '' + @State usage: string = '' + @State publicKey: string = '' + private client: JwksClient|null = null; + + build() { + Column() { + Scroll() { + Column({ space: 5 }) { + Row() { + Button($r('app.string.generate_public_key')).fontSize($r('app.string.button_font_size')).width('70%').height('70%').padding($r('app.string.margin')).onClick(() => { + console.info("===== get publicKey start =====") + const kid = 'RkI5MjI5OUY5ODc1N0Q4QzM0OUYzNkVGMTJDOUEzQkFCOTU3NjE2Rg'; + //根据kid从秘钥集中获取对应的jwk + this.getData(kid) + }) + }.justifyContent(FlexAlign.Center).width('100%').height('100vp') + + Text("kid: " + this.kid) + .fontSize($r('app.string.font_size')) + Text("alg: " + this.alg) + .fontSize($r('app.string.font_size')) + Text("kty: " + this.kty) + .fontSize($r('app.string.font_size')) + Text("usage: " + this.usage) + .fontSize($r('app.string.font_size')) + Text("publicKey: " + this.publicKey) + .fontSize($r('app.string.font_size')) + } + .width('100%').margin($r('app.string.margin')).alignItems(HorizontalAlign.Start).justifyContent(FlexAlign.Start) + } + }.height('100%').justifyContent(FlexAlign.Start).alignItems(HorizontalAlign.Start) + } + + aboutToAppear() { + // that = this; + let option: Option = new Option('https://sandrino.auth0.com/.well-known/jwks.json',null,5000,false,true) + this.client = new JwksClient(option); + } + + async getData(kid:string) { + + + if(this.client != null){ + let signingKey: Single = await this.client.getSigningKey(kid) + console.info("jwks_rsa signingKey:"+JSON.stringify(signingKey)) + this.kid = signingKey.kid + this.alg = signingKey.algorithm + this.kty = signingKey.type + this.usage = signingKey.usage + let pubKey:cryptoFramework.PubKey | undefined = await signingKey.getPublicKey() + let publicData:Uint8Array | undefined = pubKey?.getEncoded().data; + console.info("jwks_rsa public key encode = " + publicData) + let base64:util.Base64Helper = new util.Base64Helper(); + this.publicKey = base64.encodeToStringSync(publicData); + console.info("jwks_rsa publicKey = " + this.publicKey) + } + + } +} + +class Single{ + kid: string = ""; + algorithm: string = ""; + type:string = ""; + usage: string = ""; + x5u: undefined | string | string[] = undefined; + x5c: undefined | string | string[] = undefined; + x5t: undefined | string | string[] = undefined; + getPublicKey():cryptoFramework.PubKey | undefined { + return undefined + } +} \ No newline at end of file diff --git a/OpenHarmony/entry/src/main/module.json5 b/OpenHarmony/entry/src/main/module.json5 new file mode 100644 index 0000000..2d8c2dd --- /dev/null +++ b/OpenHarmony/entry/src/main/module.json5 @@ -0,0 +1,47 @@ +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "requestPermissions": [ + { + "name": "ohos.permission.INTERNET", + "reason": "$string:internet_permission" + }, + { + "name": "ohos.permission.GET_WIFI_INFO", + "reason": "$string:internet_permission" + } + ], + "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" + ] + } + ] + } + ] + } +} \ No newline at end of file diff --git a/OpenHarmony/entry/src/main/resources/base/element/color.json b/OpenHarmony/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000..3c71296 --- /dev/null +++ b/OpenHarmony/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/OpenHarmony/entry/src/main/resources/base/element/string.json b/OpenHarmony/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000..5a83ea1 --- /dev/null +++ b/OpenHarmony/entry/src/main/resources/base/element/string.json @@ -0,0 +1,36 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "jwks_rsa" + }, + { + "name": "button_font_size", + "value": "35fp" + }, + { + "name": "font_size", + "value": "30fp" + }, + { + "name": "margin", + "value": "5vp" + }, + { + "name": "internet_permission", + "value": "obtain internet resource" + }, + { + "name": "generate_public_key", + "value": "Click to generate public key" + } + ] +} \ No newline at end of file diff --git a/OpenHarmony/entry/src/main/resources/base/media/icon.png b/OpenHarmony/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000..ce307a8 Binary files /dev/null and b/OpenHarmony/entry/src/main/resources/base/media/icon.png differ diff --git a/OpenHarmony/entry/src/main/resources/base/profile/main_pages.json b/OpenHarmony/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000..45f2141 --- /dev/null +++ b/OpenHarmony/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/TestPage" + ] +} diff --git a/OpenHarmony/entry/src/main/resources/en_US/element/string.json b/OpenHarmony/entry/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000..5a83ea1 --- /dev/null +++ b/OpenHarmony/entry/src/main/resources/en_US/element/string.json @@ -0,0 +1,36 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "jwks_rsa" + }, + { + "name": "button_font_size", + "value": "35fp" + }, + { + "name": "font_size", + "value": "30fp" + }, + { + "name": "margin", + "value": "5vp" + }, + { + "name": "internet_permission", + "value": "obtain internet resource" + }, + { + "name": "generate_public_key", + "value": "Click to generate public key" + } + ] +} \ No newline at end of file diff --git a/OpenHarmony/entry/src/main/resources/zh_CN/element/string.json b/OpenHarmony/entry/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000..b839f9d --- /dev/null +++ b/OpenHarmony/entry/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,36 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "模块描述" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "jwks_rsa" + }, + { + "name": "button_font_size", + "value": "35fp" + }, + { + "name": "font_size", + "value": "30fp" + }, + { + "name": "margin", + "value": "5vp" + }, + { + "name": "internet_permission", + "value": "obtain internet resource" + }, + { + "name": "generate_public_key", + "value": "点击生成公钥" + } + ] +} \ No newline at end of file diff --git a/OpenHarmony/entry/src/ohosTest/ets/test/Ability.test.ets b/OpenHarmony/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000..72f86a7 --- /dev/null +++ b/OpenHarmony/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2022 Huawei Device 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', ()=>{ + + it('assertContain',0, ()=> { + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc' + let b = 'b' + expect(a).assertContain(b) + expect(a).assertEqual(a) + }) + }) +} \ No newline at end of file diff --git a/OpenHarmony/entry/src/ohosTest/ets/test/JwksClient.test.ets b/OpenHarmony/entry/src/ohosTest/ets/test/JwksClient.test.ets new file mode 100644 index 0000000..df69137 --- /dev/null +++ b/OpenHarmony/entry/src/ohosTest/ets/test/JwksClient.test.ets @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2022 Huawei Device 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' +import {JwksClient} from "@ohos/jwks_rsa" +import Option from './Option' + +let jwksClient: JwksClient; +let signingKey:ESObject; + +export default function JwksClientTest() { + describe('ArtsJwksClientTest', ()=> { + beforeAll(() => { + console.info("===== beforeAll ======") + let option: Option = new Option('https://sandrino.auth0.com/.well-known/jwks.json',null,5000,false,true) + jwksClient = new JwksClient(option); + expect(jwksClient != null).assertTrue() + }) + afterAll(()=>{ + jwksClient == null; + }) + it('JwksClient_Test_getKeys',0, async () => { + expect(await jwksClient.getKeys() != null).assertTrue() + }) + + it('JwksClient_Test_getSigningKeys',0, async () => { + expect(await jwksClient.getSigningKeys() != null).assertTrue() + }) + + it('JwksClient_Test_signingKey',0, async () => { + const kid = 'RkI5MjI5OUY5ODc1N0Q4QzM0OUYzNkVGMTJDOUEzQkFCOTU3NjE2Rg'; + signingKey = await jwksClient.getSigningKey(kid); + expect(signingKey != null).assertTrue() + }) + + it('JwksClient_Test_kid',0, async () =>{ + expect(signingKey.kid != null).assertTrue() + }) + + it('JwksClient_Test_algorithm',0, () => { + expect(signingKey.algorithm != null).assertTrue() + }) + + it('JwksClient_Test_type',0, () => { + expect(signingKey.type != null).assertTrue() + }) + + it('JwksClient_Test_usage',0, () => { + expect(signingKey.usage != null).assertTrue() + }) + + it('JwksClient_Test_getPublicKey',0, async () => { + let publicKey:ESObject = await signingKey.getPublicKey() + expect(publicKey != null).assertTrue() + }) + }) +} \ No newline at end of file diff --git a/OpenHarmony/entry/src/ohosTest/ets/test/List.test.ets b/OpenHarmony/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000..475d764 --- /dev/null +++ b/OpenHarmony/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2022 Huawei Device 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' +import JwksClientTest from './JwksClient.test' +export default function testsuite() { + abilityTest(); + JwksClientTest() +} \ No newline at end of file diff --git a/OpenHarmony/entry/src/ohosTest/ets/test/Option.ets b/OpenHarmony/entry/src/ohosTest/ets/test/Option.ets new file mode 100644 index 0000000..ecd0c12 --- /dev/null +++ b/OpenHarmony/entry/src/ohosTest/ets/test/Option.ets @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2022 Huawei Device 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. + */ + +export default class Option{ + jwksUri:string; + requestHeaders: ESObject; // Optional + timeout:number=5000; // Defaults to 30s + cache:boolean; + rateLimit: boolean + + constructor(jwksUri:string, + requestHeaders: ESObject, // Optional + timeout:number, // Defaults to 30s + cache:boolean, + rateLimit: boolean) { + this.jwksUri = jwksUri; + this.requestHeaders = requestHeaders; + this.timeout = timeout; + this.cache = cache; + this.rateLimit = rateLimit; + } +} \ No newline at end of file diff --git a/OpenHarmony/entry/src/ohosTest/ets/testability/TestAbility.ets b/OpenHarmony/entry/src/ohosTest/ets/testability/TestAbility.ets new file mode 100644 index 0000000..1176b43 --- /dev/null +++ b/OpenHarmony/entry/src/ohosTest/ets/testability/TestAbility.ets @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2022 Huawei Device 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'; +import Want from '@ohos.app.ability.Want'; +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; + +export default class TestAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.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) ?? ''); + let abilityDelegator:ESObject + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + let abilityDelegatorArguments:ESObject + 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/OpenHarmony/entry/src/ohosTest/ets/testability/pages/index.ets b/OpenHarmony/entry/src/ohosTest/ets/testability/pages/index.ets new file mode 100644 index 0000000..c002de7 --- /dev/null +++ b/OpenHarmony/entry/src/ohosTest/ets/testability/pages/index.ets @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2022 Huawei Device 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/OpenHarmony/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts b/OpenHarmony/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts new file mode 100644 index 0000000..6413cd8 --- /dev/null +++ b/OpenHarmony/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ts @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2022 Huawei Device 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() + const bundleName = abilityDelegatorArguments.bundleName; + const testAbilityName = 'TestAbility'; + let lMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + const want = { + bundleName: bundleName, + abilityName: testAbilityName + }; + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + abilityDelegator.startAbility(want, (err : any, data : any) => { + hilog.info(0x0000, 'testTag', 'startAbility : err : %{public}s', JSON.stringify(err) ?? ''); + hilog.info(0x0000, 'testTag', 'startAbility : data : %{public}s',JSON.stringify(data) ?? ''); + }) + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end'); + } +} \ No newline at end of file diff --git a/OpenHarmony/entry/src/ohosTest/module.json5 b/OpenHarmony/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000..4fc9701 --- /dev/null +++ b/OpenHarmony/entry/src/ohosTest/module.json5 @@ -0,0 +1,37 @@ +{ + "module": { + "name": "entry_test", + "type": "feature", + "description": "$string:module_test_desc", + "mainElement": "TestAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "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/OpenHarmony/entry/src/ohosTest/resources/base/element/color.json b/OpenHarmony/entry/src/ohosTest/resources/base/element/color.json new file mode 100644 index 0000000..3c71296 --- /dev/null +++ b/OpenHarmony/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/OpenHarmony/entry/src/ohosTest/resources/base/element/string.json b/OpenHarmony/entry/src/ohosTest/resources/base/element/string.json new file mode 100644 index 0000000..65d8fa5 --- /dev/null +++ b/OpenHarmony/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/OpenHarmony/entry/src/ohosTest/resources/base/media/icon.png b/OpenHarmony/entry/src/ohosTest/resources/base/media/icon.png new file mode 100644 index 0000000..ce307a8 Binary files /dev/null and b/OpenHarmony/entry/src/ohosTest/resources/base/media/icon.png differ diff --git a/OpenHarmony/entry/src/ohosTest/resources/base/profile/test_pages.json b/OpenHarmony/entry/src/ohosTest/resources/base/profile/test_pages.json new file mode 100644 index 0000000..b7e7343 --- /dev/null +++ b/OpenHarmony/entry/src/ohosTest/resources/base/profile/test_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "testability/pages/Index" + ] +} diff --git a/OpenHarmony/hvigor/hvigor-config.json5 b/OpenHarmony/hvigor/hvigor-config.json5 new file mode 100644 index 0000000..1a47490 --- /dev/null +++ b/OpenHarmony/hvigor/hvigor-config.json5 @@ -0,0 +1,18 @@ +{ + "hvigorVersion": "3.0.9", + "dependencies": { + "@ohos/hvigor-ohos-plugin": "3.0.9" + }, + "execution": { + // "daemon": true, /* Enable daemon compilation. Default: true */ + // "incremental": true, /* Enable incremental compilation. Default: true */ + // "parallel": true, /* Enable parallel compilation. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Default: false */ + } +} diff --git a/OpenHarmony/hvigor/hvigor-wrapper.js b/OpenHarmony/hvigor/hvigor-wrapper.js new file mode 100644 index 0000000..199ce97 --- /dev/null +++ b/OpenHarmony/hvigor/hvigor-wrapper.js @@ -0,0 +1 @@ +"use strict";var u=require("path"),D=require("os"),e=require("fs"),t=require("crypto"),r=require("child_process"),n="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},i={},C={},F=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(C,"__esModule",{value:!0}),C.maxPathLength=C.isMac=C.isLinux=C.isWindows=void 0;const E=F(D),A="Windows_NT",o="Darwin";function a(){return E.default.type()===A}function c(){return E.default.type()===o}C.isWindows=a,C.isLinux=function(){return"Linux"===E.default.type()},C.isMac=c,C.maxPathLength=function(){return c()?1016:a()?259:4095},function(e){var t=n&&n.__createBinding||(Object.create?function(u,D,e,t){void 0===t&&(t=e);var r=Object.getOwnPropertyDescriptor(D,e);r&&!("get"in r?!D.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return D[e]}}),Object.defineProperty(u,t,r)}:function(u,D,e,t){void 0===t&&(t=e),u[t]=D[e]}),r=n&&n.__setModuleDefault||(Object.create?function(u,D){Object.defineProperty(u,"default",{enumerable:!0,value:D})}:function(u,D){u.default=D}),i=n&&n.__importStar||function(u){if(u&&u.__esModule)return u;var D={};if(null!=u)for(var e in u)"default"!==e&&Object.prototype.hasOwnProperty.call(u,e)&&t(D,u,e);return r(D,u),D};Object.defineProperty(e,"__esModule",{value:!0}),e.WORK_SPACE=e.HVIGOR_PROJECT_WRAPPER_HOME=e.HVIGOR_PROJECT_ROOT_DIR=e.HVIGOR_PROJECT_CACHES_HOME=e.HVIGOR_PNPM_STORE_PATH=e.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH=e.PROJECT_CACHES=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 F=i(D),E=i(u),A=C;e.HVIGOR_ENGINE_PACKAGE_NAME="@ohos/hvigor",e.PNPM_TOOL=(0,A.isWindows)()?"pnpm.cmd":"pnpm",e.NPM_TOOL=(0,A.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=E.resolve(F.homedir(),".hvigor"),e.HVIGOR_WRAPPER_TOOLS_HOME=E.resolve(e.HVIGOR_USER_HOME,"wrapper","tools"),e.PROJECT_CACHES="project_caches",e.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH=E.resolve(e.HVIGOR_WRAPPER_TOOLS_HOME,"node_modules",".bin",e.PNPM_TOOL),e.HVIGOR_PNPM_STORE_PATH=E.resolve(e.HVIGOR_USER_HOME,"caches"),e.HVIGOR_PROJECT_CACHES_HOME=E.resolve(e.HVIGOR_USER_HOME,e.PROJECT_CACHES),e.HVIGOR_PROJECT_ROOT_DIR=process.cwd(),e.HVIGOR_PROJECT_WRAPPER_HOME=E.resolve(e.HVIGOR_PROJECT_ROOT_DIR,e.HVIGOR),e.WORK_SPACE="workspace"}(i);var s={},l={};Object.defineProperty(l,"__esModule",{value:!0}),l.logInfoPrintConsole=l.logErrorAndExit=void 0,l.logErrorAndExit=function(u){u instanceof Error?console.error(u.message):console.error(u),process.exit(-1)},l.logInfoPrintConsole=function(u){console.log(u)};var B=n&&n.__createBinding||(Object.create?function(u,D,e,t){void 0===t&&(t=e);var r=Object.getOwnPropertyDescriptor(D,e);r&&!("get"in r?!D.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return D[e]}}),Object.defineProperty(u,t,r)}:function(u,D,e,t){void 0===t&&(t=e),u[t]=D[e]}),d=n&&n.__setModuleDefault||(Object.create?function(u,D){Object.defineProperty(u,"default",{enumerable:!0,value:D})}:function(u,D){u.default=D}),f=n&&n.__importStar||function(u){if(u&&u.__esModule)return u;var D={};if(null!=u)for(var e in u)"default"!==e&&Object.prototype.hasOwnProperty.call(u,e)&&B(D,u,e);return d(D,u),D};Object.defineProperty(s,"__esModule",{value:!0});var _=s.executeBuild=void 0;const p=f(e),O=f(u),h=l;_=s.executeBuild=function(u){const D=O.resolve(u,"node_modules","@ohos","hvigor","bin","hvigor.js");try{const u=p.realpathSync(D);require(u)}catch(e){(0,h.logErrorAndExit)(`Error: ENOENT: no such file ${D},delete ${u} and retry.`)}};var P={},v={};!function(u){var D=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(u,"__esModule",{value:!0}),u.hashFile=u.hash=u.createHash=void 0;const r=D(t),i=D(e);u.createHash=(u="MD5")=>r.default.createHash(u);u.hash=(D,e)=>(0,u.createHash)(e).update(D).digest("hex");u.hashFile=(D,e)=>{if(i.default.existsSync(D))return(0,u.hash)(i.default.readFileSync(D,"utf-8"),e)}}(v);var g={},m={},R={};Object.defineProperty(R,"__esModule",{value:!0}),R.Unicode=void 0;class y{}R.Unicode=y,y.SPACE_SEPARATOR=/[\u1680\u2000-\u200A\u202F\u205F\u3000]/,y.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]/,y.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(m,"__esModule",{value:!0}),m.JudgeUtil=void 0;const I=R;m.JudgeUtil=class{static isIgnoreChar(u){return"string"==typeof u&&("\t"===u||"\v"===u||"\f"===u||" "===u||" "===u||"\ufeff"===u||"\n"===u||"\r"===u||"\u2028"===u||"\u2029"===u)}static isSpaceSeparator(u){return"string"==typeof u&&I.Unicode.SPACE_SEPARATOR.test(u)}static isIdStartChar(u){return"string"==typeof u&&(u>="a"&&u<="z"||u>="A"&&u<="Z"||"$"===u||"_"===u||I.Unicode.ID_START.test(u))}static isIdContinueChar(u){return"string"==typeof u&&(u>="a"&&u<="z"||u>="A"&&u<="Z"||u>="0"&&u<="9"||"$"===u||"_"===u||"‌"===u||"‍"===u||I.Unicode.ID_CONTINUE.test(u))}static isDigitWithoutZero(u){return/[1-9]/.test(u)}static isDigit(u){return"string"==typeof u&&/[0-9]/.test(u)}static isHexDigit(u){return"string"==typeof u&&/[0-9A-Fa-f]/.test(u)}};var N=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(g,"__esModule",{value:!0}),g.parseJsonText=g.parseJsonFile=void 0;const b=N(e),S=N(D),w=N(u),H=m;var x;!function(u){u[u.Char=0]="Char",u[u.EOF=1]="EOF",u[u.Identifier=2]="Identifier"}(x||(x={}));let M,T,V,G,j,J,W="start",U=[],L=0,$=1,k=0,K=!1,z="default",q="'",Z=1;function X(u,D=!1){T=String(u),W="start",U=[],L=0,$=1,k=0,G=void 0,K=D;do{M=Q(),nu[W]()}while("eof"!==M.type);return G}function Q(){for(z="default",j="",q="'",Z=1;;){J=Y();const u=Du[z]();if(u)return u}}function Y(){if(T[L])return String.fromCodePoint(T.codePointAt(L))}function uu(){const u=Y();return"\n"===u?($++,k=0):u?k+=u.length:k++,u&&(L+=u.length),u}g.parseJsonFile=function(u,D=!1,e="utf-8"){const t=b.default.readFileSync(w.default.resolve(u),{encoding:e});try{return X(t,D)}catch(D){if(D instanceof SyntaxError){const e=D.message.split("at");if(2===e.length)throw new Error(`${e[0].trim()}${S.default.EOL}\t at ${u}:${e[1].trim()}`)}throw new Error(`${u} is not in valid JSON/JSON5 format.`)}},g.parseJsonText=X;const Du={default(){switch(J){case"/":return uu(),void(z="comment");case void 0:return uu(),eu("eof")}if(!H.JudgeUtil.isIgnoreChar(J)&&!H.JudgeUtil.isSpaceSeparator(J))return Du[W]();uu()},start(){z="value"},beforePropertyName(){switch(J){case"$":case"_":return j=uu(),void(z="identifierName");case"\\":return uu(),void(z="identifierNameStartEscape");case"}":return eu("punctuator",uu());case'"':case"'":return q=J,uu(),void(z="string")}if(H.JudgeUtil.isIdStartChar(J))return j+=uu(),void(z="identifierName");throw Eu(x.Char,uu())},afterPropertyName(){if(":"===J)return eu("punctuator",uu());throw Eu(x.Char,uu())},beforePropertyValue(){z="value"},afterPropertyValue(){switch(J){case",":case"}":return eu("punctuator",uu())}throw Eu(x.Char,uu())},beforeArrayValue(){if("]"===J)return eu("punctuator",uu());z="value"},afterArrayValue(){switch(J){case",":case"]":return eu("punctuator",uu())}throw Eu(x.Char,uu())},end(){throw Eu(x.Char,uu())},comment(){switch(J){case"*":return uu(),void(z="multiLineComment");case"/":return uu(),void(z="singleLineComment")}throw Eu(x.Char,uu())},multiLineComment(){switch(J){case"*":return uu(),void(z="multiLineCommentAsterisk");case void 0:throw Eu(x.Char,uu())}uu()},multiLineCommentAsterisk(){switch(J){case"*":return void uu();case"/":return uu(),void(z="default");case void 0:throw Eu(x.Char,uu())}uu(),z="multiLineComment"},singleLineComment(){switch(J){case"\n":case"\r":case"\u2028":case"\u2029":return uu(),void(z="default");case void 0:return uu(),eu("eof")}uu()},value(){switch(J){case"{":case"[":return eu("punctuator",uu());case"n":return uu(),tu("ull"),eu("null",null);case"t":return uu(),tu("rue"),eu("boolean",!0);case"f":return uu(),tu("alse"),eu("boolean",!1);case"-":case"+":return"-"===uu()&&(Z=-1),void(z="numerical");case".":case"0":case"I":case"N":return void(z="numerical");case'"':case"'":return q=J,uu(),j="",void(z="string")}if(void 0===J||!H.JudgeUtil.isDigitWithoutZero(J))throw Eu(x.Char,uu());z="numerical"},numerical(){switch(J){case".":return j=uu(),void(z="decimalPointLeading");case"0":return j=uu(),void(z="zero");case"I":return uu(),tu("nfinity"),eu("numeric",Z*(1/0));case"N":return uu(),tu("aN"),eu("numeric",NaN)}if(void 0!==J&&H.JudgeUtil.isDigitWithoutZero(J))return j=uu(),void(z="decimalInteger");throw Eu(x.Char,uu())},zero(){switch(J){case".":case"e":case"E":return void(z="decimal");case"x":case"X":return j+=uu(),void(z="hexadecimal")}return eu("numeric",0)},decimalInteger(){switch(J){case".":case"e":case"E":return void(z="decimal")}if(!H.JudgeUtil.isDigit(J))return eu("numeric",Z*Number(j));j+=uu()},decimal(){switch(J){case".":j+=uu(),z="decimalFraction";break;case"e":case"E":j+=uu(),z="decimalExponent"}},decimalPointLeading(){if(H.JudgeUtil.isDigit(J))return j+=uu(),void(z="decimalFraction");throw Eu(x.Char,uu())},decimalFraction(){switch(J){case"e":case"E":return j+=uu(),void(z="decimalExponent")}if(!H.JudgeUtil.isDigit(J))return eu("numeric",Z*Number(j));j+=uu()},decimalExponent(){switch(J){case"+":case"-":return j+=uu(),void(z="decimalExponentSign")}if(H.JudgeUtil.isDigit(J))return j+=uu(),void(z="decimalExponentInteger");throw Eu(x.Char,uu())},decimalExponentSign(){if(H.JudgeUtil.isDigit(J))return j+=uu(),void(z="decimalExponentInteger");throw Eu(x.Char,uu())},decimalExponentInteger(){if(!H.JudgeUtil.isDigit(J))return eu("numeric",Z*Number(j));j+=uu()},hexadecimal(){if(H.JudgeUtil.isHexDigit(J))return j+=uu(),void(z="hexadecimalInteger");throw Eu(x.Char,uu())},hexadecimalInteger(){if(!H.JudgeUtil.isHexDigit(J))return eu("numeric",Z*Number(j));j+=uu()},identifierNameStartEscape(){if("u"!==J)throw Eu(x.Char,uu());uu();const u=ru();switch(u){case"$":case"_":break;default:if(!H.JudgeUtil.isIdStartChar(u))throw Eu(x.Identifier)}j+=u,z="identifierName"},identifierName(){switch(J){case"$":case"_":case"‌":case"‍":return void(j+=uu());case"\\":return uu(),void(z="identifierNameEscape")}if(!H.JudgeUtil.isIdContinueChar(J))return eu("identifier",j);j+=uu()},identifierNameEscape(){if("u"!==J)throw Eu(x.Char,uu());uu();const u=ru();switch(u){case"$":case"_":case"‌":case"‍":break;default:if(!H.JudgeUtil.isIdContinueChar(u))throw Eu(x.Identifier)}j+=u,z="identifierName"},string(){switch(J){case"\\":return uu(),void(j+=function(){const u=Y(),D=function(){switch(Y()){case"b":return uu(),"\b";case"f":return uu(),"\f";case"n":return uu(),"\n";case"r":return uu(),"\r";case"t":return uu(),"\t";case"v":return uu(),"\v"}return}();if(D)return D;switch(u){case"0":if(uu(),H.JudgeUtil.isDigit(Y()))throw Eu(x.Char,uu());return"\0";case"x":return uu(),function(){let u="",D=Y();if(!H.JudgeUtil.isHexDigit(D))throw Eu(x.Char,uu());if(u+=uu(),D=Y(),!H.JudgeUtil.isHexDigit(D))throw Eu(x.Char,uu());return u+=uu(),String.fromCodePoint(parseInt(u,16))}();case"u":return uu(),ru();case"\n":case"\u2028":case"\u2029":return uu(),"";case"\r":return uu(),"\n"===Y()&&uu(),""}if(void 0===u||H.JudgeUtil.isDigitWithoutZero(u))throw Eu(x.Char,uu());return uu()}());case'"':case"'":if(J===q){const u=eu("string",j);return uu(),u}return void(j+=uu());case"\n":case"\r":case void 0:throw Eu(x.Char,uu());case"\u2028":case"\u2029":!function(u){console.warn(`JSON5: '${Fu(u)}' in strings is not valid ECMAScript; consider escaping.`)}(J)}j+=uu()}};function eu(u,D){return{type:u,value:D,line:$,column:k}}function tu(u){for(const D of u){if(Y()!==D)throw Eu(x.Char,uu());uu()}}function ru(){let u="",D=4;for(;D-- >0;){const D=Y();if(!H.JudgeUtil.isHexDigit(D))throw Eu(x.Char,uu());u+=uu()}return String.fromCodePoint(parseInt(u,16))}const nu={start(){if("eof"===M.type)throw Eu(x.EOF);iu()},beforePropertyName(){switch(M.type){case"identifier":case"string":return V=M.value,void(W="afterPropertyName");case"punctuator":return void Cu();case"eof":throw Eu(x.EOF)}},afterPropertyName(){if("eof"===M.type)throw Eu(x.EOF);W="beforePropertyValue"},beforePropertyValue(){if("eof"===M.type)throw Eu(x.EOF);iu()},afterPropertyValue(){if("eof"===M.type)throw Eu(x.EOF);switch(M.value){case",":return void(W="beforePropertyName");case"}":Cu()}},beforeArrayValue(){if("eof"===M.type)throw Eu(x.EOF);"punctuator"!==M.type||"]"!==M.value?iu():Cu()},afterArrayValue(){if("eof"===M.type)throw Eu(x.EOF);switch(M.value){case",":return void(W="beforeArrayValue");case"]":Cu()}},end(){}};function iu(){const u=function(){let u;switch(M.type){case"punctuator":switch(M.value){case"{":u={};break;case"[":u=[]}break;case"null":case"boolean":case"numeric":case"string":u=M.value}return u}();if(K&&"object"==typeof u&&(u._line=$,u._column=k),void 0===G)G=u;else{const D=U[U.length-1];Array.isArray(D)?K&&"object"!=typeof u?D.push({value:u,_line:$,_column:k}):D.push(u):D[V]=K&&"object"!=typeof u?{value:u,_line:$,_column:k}:u}!function(u){if(u&&"object"==typeof u)U.push(u),W=Array.isArray(u)?"beforeArrayValue":"beforePropertyName";else{const u=U[U.length-1];W=u?Array.isArray(u)?"afterArrayValue":"afterPropertyValue":"end"}}(u)}function Cu(){U.pop();const u=U[U.length-1];W=u?Array.isArray(u)?"afterArrayValue":"afterPropertyValue":"end"}function Fu(u){const D={"'":"\\'",'"':'\\"',"\\":"\\\\","\b":"\\b","\f":"\\f","\n":"\\n","\r":"\\r","\t":"\\t","\v":"\\v","\0":"\\0","\u2028":"\\u2028","\u2029":"\\u2029"};if(D[u])return D[u];if(u<" "){const D=u.charCodeAt(0).toString(16);return`\\x${`00${D}`.substring(D.length)}`}return u}function Eu(u,D){let e="";switch(u){case x.Char:e=void 0===D?`JSON5: invalid end of input at ${$}:${k}`:`JSON5: invalid character '${Fu(D)}' at ${$}:${k}`;break;case x.EOF:e=`JSON5: invalid end of input at ${$}:${k}`;break;case x.Identifier:k-=5,e=`JSON5: invalid identifier character at ${$}:${k}`}const t=new Au(e);return t.lineNumber=$,t.columnNumber=k,t}class Au extends SyntaxError{}var ou={},au=n&&n.__createBinding||(Object.create?function(u,D,e,t){void 0===t&&(t=e);var r=Object.getOwnPropertyDescriptor(D,e);r&&!("get"in r?!D.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return D[e]}}),Object.defineProperty(u,t,r)}:function(u,D,e,t){void 0===t&&(t=e),u[t]=D[e]}),cu=n&&n.__setModuleDefault||(Object.create?function(u,D){Object.defineProperty(u,"default",{enumerable:!0,value:D})}:function(u,D){u.default=D}),su=n&&n.__importStar||function(u){if(u&&u.__esModule)return u;var D={};if(null!=u)for(var e in u)"default"!==e&&Object.prototype.hasOwnProperty.call(u,e)&&au(D,u,e);return cu(D,u),D},lu=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(ou,"__esModule",{value:!0}),ou.isFileExists=ou.offlinePluginConversion=ou.executeCommand=ou.getNpmPath=ou.hasNpmPackInPaths=void 0;const Bu=r,du=lu(e),fu=su(u),_u=i,pu=l;ou.hasNpmPackInPaths=function(u,D){try{return require.resolve(u,{paths:[...D]}),!0}catch(u){return!1}},ou.getNpmPath=function(){const u=process.execPath;return fu.join(fu.dirname(u),_u.NPM_TOOL)},ou.executeCommand=function(u,D,e){0!==(0,Bu.spawnSync)(u,D,e).status&&(0,pu.logErrorAndExit)(`Error: ${u} ${D} execute failed.See above for details.`)},ou.offlinePluginConversion=function(u,D){return D.startsWith("file:")||D.endsWith(".tgz")?fu.resolve(u,_u.HVIGOR,D.replace("file:","")):D},ou.isFileExists=function(u){return du.default.existsSync(u)&&du.default.statSync(u).isFile()};var Ou=n&&n.__createBinding||(Object.create?function(u,D,e,t){void 0===t&&(t=e);var r=Object.getOwnPropertyDescriptor(D,e);r&&!("get"in r?!D.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return D[e]}}),Object.defineProperty(u,t,r)}:function(u,D,e,t){void 0===t&&(t=e),u[t]=D[e]}),hu=n&&n.__setModuleDefault||(Object.create?function(u,D){Object.defineProperty(u,"default",{enumerable:!0,value:D})}:function(u,D){u.default=D}),Pu=n&&n.__importStar||function(u){if(u&&u.__esModule)return u;var D={};if(null!=u)for(var e in u)"default"!==e&&Object.prototype.hasOwnProperty.call(u,e)&&Ou(D,u,e);return hu(D,u),D},vu=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(P,"__esModule",{value:!0});var gu=P.initProjectWorkSpace=void 0;const mu=Pu(e),Ru=vu(D),yu=Pu(u),Iu=v,Nu=i,bu=g,Su=l,wu=ou;let Hu,xu,Mu;function Tu(u,D,e){return void 0!==e.dependencies&&(0,wu.offlinePluginConversion)(Nu.HVIGOR_PROJECT_ROOT_DIR,D.dependencies[u])===yu.normalize(e.dependencies[u])}function Vu(){const u=yu.join(Mu,Nu.WORK_SPACE);if((0,Su.logInfoPrintConsole)("Hvigor cleaning..."),!mu.existsSync(u))return;const D=mu.readdirSync(u);if(!D||0===D.length)return;const e=yu.resolve(Mu,"node_modules","@ohos","hvigor","bin","hvigor.js");mu.existsSync(e)&&(0,wu.executeCommand)(process.argv[0],[e,"--stop-daemon"],{});try{D.forEach((D=>{mu.rmSync(yu.resolve(u,D),{recursive:!0})}))}catch(D){(0,Su.logErrorAndExit)(`The hvigor build tool cannot be installed. Please manually clear the workspace directory and synchronize the project again.\n\n Workspace Path: ${u}.`)}}gu=P.initProjectWorkSpace=function(){if(Hu=function(){const u=yu.resolve(Nu.HVIGOR_PROJECT_WRAPPER_HOME,Nu.DEFAULT_HVIGOR_CONFIG_JSON_FILE_NAME);mu.existsSync(u)||(0,Su.logErrorAndExit)(`Error: Hvigor config file ${u} does not exist.`);return(0,bu.parseJsonFile)(u)}(),Mu=function(u){let D;D=function(u){let D=u.hvigorVersion;if(D.startsWith("file:")||D.endsWith(".tgz"))return!1;const e=u.dependencies,t=Object.getOwnPropertyNames(e);for(const u of t){const D=e[u];if(D.startsWith("file:")||D.endsWith(".tgz"))return!1}if(1===t.length&&"@ohos/hvigor-ohos-plugin"===t[0])return D>"2.5.0";return!1}(u)?function(u){let D=`${Nu.HVIGOR_ENGINE_PACKAGE_NAME}@${u.hvigorVersion}`;const e=u.dependencies;if(e){Object.getOwnPropertyNames(e).sort().forEach((u=>{D+=`,${u}@${e[u]}`}))}return(0,Iu.hash)(D)}(u):(0,Iu.hash)(process.cwd());return yu.resolve(Ru.default.homedir(),".hvigor","project_caches",D)}(Hu),xu=function(){const u=yu.resolve(Mu,Nu.WORK_SPACE,Nu.DEFAULT_PACKAGE_JSON);return mu.existsSync(u)?(0,bu.parseJsonFile)(u):{dependencies:{}}}(),!(0,wu.hasNpmPackInPaths)(Nu.HVIGOR_ENGINE_PACKAGE_NAME,[yu.join(Mu,Nu.WORK_SPACE)])||(0,wu.offlinePluginConversion)(Nu.HVIGOR_PROJECT_ROOT_DIR,Hu.hvigorVersion)!==xu.dependencies[Nu.HVIGOR_ENGINE_PACKAGE_NAME]||!function(){function u(u){const D=null==u?void 0:u.dependencies;return void 0===D?0:Object.getOwnPropertyNames(D).length}const D=u(Hu),e=u(xu);if(D+1!==e)return!1;for(const u in null==Hu?void 0:Hu.dependencies)if(!(0,wu.hasNpmPackInPaths)(u,[yu.join(Mu,Nu.WORK_SPACE)])||!Tu(u,Hu,xu))return!1;return!0}()){Vu();try{!function(){(0,Su.logInfoPrintConsole)("Hvigor installing...");for(const u in Hu.dependencies)Hu.dependencies[u]&&(Hu.dependencies[u]=(0,wu.offlinePluginConversion)(Nu.HVIGOR_PROJECT_ROOT_DIR,Hu.dependencies[u]));const u={dependencies:{...Hu.dependencies}};u.dependencies[Nu.HVIGOR_ENGINE_PACKAGE_NAME]=(0,wu.offlinePluginConversion)(Nu.HVIGOR_PROJECT_ROOT_DIR,Hu.hvigorVersion);const D=yu.join(Mu,Nu.WORK_SPACE);try{mu.mkdirSync(D,{recursive:!0});const e=yu.resolve(D,Nu.DEFAULT_PACKAGE_JSON);mu.writeFileSync(e,JSON.stringify(u))}catch(u){(0,Su.logErrorAndExit)(u)}(function(){const u=["config","set","store-dir",Nu.HVIGOR_PNPM_STORE_PATH],D={cwd:yu.join(Mu,Nu.WORK_SPACE),stdio:["inherit","inherit","inherit"]};(0,wu.executeCommand)(Nu.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH,u,D)})(),function(){const u=["install"],D={cwd:yu.join(Mu,Nu.WORK_SPACE),stdio:["inherit","inherit","inherit"]};(0,wu.executeCommand)(Nu.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH,u,D)}(),(0,Su.logInfoPrintConsole)("Hvigor install success.")}()}catch(u){Vu()}}return Mu};var Gu={};!function(t){var C=n&&n.__createBinding||(Object.create?function(u,D,e,t){void 0===t&&(t=e);var r=Object.getOwnPropertyDescriptor(D,e);r&&!("get"in r?!D.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return D[e]}}),Object.defineProperty(u,t,r)}:function(u,D,e,t){void 0===t&&(t=e),u[t]=D[e]}),F=n&&n.__setModuleDefault||(Object.create?function(u,D){Object.defineProperty(u,"default",{enumerable:!0,value:D})}:function(u,D){u.default=D}),E=n&&n.__importStar||function(u){if(u&&u.__esModule)return u;var D={};if(null!=u)for(var e in u)"default"!==e&&Object.prototype.hasOwnProperty.call(u,e)&&C(D,u,e);return F(D,u),D},A=n&&n.__importDefault||function(u){return u&&u.__esModule?u:{default:u}};Object.defineProperty(t,"__esModule",{value:!0}),t.executeInstallPnpm=t.isPnpmInstalled=t.environmentHandler=t.checkNpmConifg=t.PNPM_VERSION=void 0;const o=r,a=E(e),c=A(D),s=E(u),B=i,d=l,f=ou;t.PNPM_VERSION="7.30.0",t.checkNpmConifg=function(){const u=s.resolve(B.HVIGOR_PROJECT_ROOT_DIR,".npmrc"),D=s.resolve(c.default.homedir(),".npmrc");if((0,f.isFileExists)(u)||(0,f.isFileExists)(D))return;const e=(0,f.getNpmPath)(),t=(0,o.spawnSync)(e,["config","get","prefix"],{cwd:B.HVIGOR_PROJECT_ROOT_DIR});if(0!==t.status||!t.stdout)return void(0,d.logErrorAndExit)("Error: The hvigor depends on the npmrc file. Configure the npmrc file first.");const r=s.resolve(`${t.stdout}`.replace(/[\r\n]/gi,""),".npmrc");(0,f.isFileExists)(r)||(0,d.logErrorAndExit)("Error: The hvigor depends on the npmrc file. Configure the npmrc file first.")},t.environmentHandler=function(){process.env["npm_config_update-notifier"]="false"},t.isPnpmInstalled=function(){return!!a.existsSync(B.HVIGOR_WRAPPER_PNPM_SCRIPT_PATH)&&(0,f.hasNpmPackInPaths)("pnpm",[B.HVIGOR_WRAPPER_TOOLS_HOME])},t.executeInstallPnpm=function(){(0,d.logInfoPrintConsole)(`Installing pnpm@${t.PNPM_VERSION}...`);const u=(0,f.getNpmPath)();!function(){const u=s.resolve(B.HVIGOR_WRAPPER_TOOLS_HOME,B.DEFAULT_PACKAGE_JSON);try{a.existsSync(B.HVIGOR_WRAPPER_TOOLS_HOME)||a.mkdirSync(B.HVIGOR_WRAPPER_TOOLS_HOME,{recursive:!0});const D={dependencies:{}};D.dependencies[B.PNPM]=t.PNPM_VERSION,a.writeFileSync(u,JSON.stringify(D))}catch(D){(0,d.logErrorAndExit)(`Error: EPERM: operation not permitted,create ${u} failed.`)}}(),(0,f.executeCommand)(u,["install","pnpm"],{cwd:B.HVIGOR_WRAPPER_TOOLS_HOME,stdio:["inherit","inherit","inherit"],env:process.env}),(0,d.logInfoPrintConsole)("Pnpm install success.")}}(Gu),function(){Gu.checkNpmConifg(),Gu.environmentHandler(),Gu.isPnpmInstalled()||Gu.executeInstallPnpm();const D=gu();_(u.join(D,i.WORK_SPACE))}(); diff --git a/OpenHarmony/hvigorfile.ts b/OpenHarmony/hvigorfile.ts new file mode 100644 index 0000000..f3cb9f1 --- /dev/null +++ b/OpenHarmony/hvigorfile.ts @@ -0,0 +1,6 @@ +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/OpenHarmony/hvigorw b/OpenHarmony/hvigorw new file mode 100644 index 0000000..ff6a29a --- /dev/null +++ b/OpenHarmony/hvigorw @@ -0,0 +1,48 @@ +#!/bin/bash + +# ---------------------------------------------------------------------------- +# 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="`pwd -P`" +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/OpenHarmony/hvigorw.bat b/OpenHarmony/hvigorw.bat new file mode 100644 index 0000000..d570007 --- /dev/null +++ b/OpenHarmony/hvigorw.bat @@ -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/OpenHarmony/library/.gitignore b/OpenHarmony/library/.gitignore new file mode 100644 index 0000000..fbabf77 --- /dev/null +++ b/OpenHarmony/library/.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/OpenHarmony/library/.preview/default/intermediates/merge_profile/default/module.json b/OpenHarmony/library/.preview/default/intermediates/merge_profile/default/module.json new file mode 100644 index 0000000..e19b7ae --- /dev/null +++ b/OpenHarmony/library/.preview/default/intermediates/merge_profile/default/module.json @@ -0,0 +1,21 @@ +{ + "app": { + "bundleName": "cn.openharmony.jwks_rsa", + "debug": true, + "versionCode": 1000000, + "versionName": "1.0.0", + "minAPIVersion": 10, + "targetAPIVersion": 10, + "apiReleaseType": "Beta2", + "compileSdkVersion": "4.0.9.6", + "compileSdkType": "OpenHarmony" + }, + "module": { + "name": "jwks_rsa", + "type": "har", + "deviceTypes": [ + "default", + "tablet" + ] + } +} diff --git a/OpenHarmony/library/build-profile.json5 b/OpenHarmony/library/build-profile.json5 new file mode 100644 index 0000000..08f43dc --- /dev/null +++ b/OpenHarmony/library/build-profile.json5 @@ -0,0 +1,28 @@ +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": true, + "files": [ + "./obfuscation-rules.txt" + ] + }, + "consumerFiles": [ + "./consumer-rules.txt" + ] + } + } + }, + ], + "targets": [ + { + "name": "default" + } + ] +} diff --git a/OpenHarmony/library/consumer-rules.txt b/OpenHarmony/library/consumer-rules.txt new file mode 100644 index 0000000..e69de29 diff --git a/OpenHarmony/library/hvigorfile.ts b/OpenHarmony/library/hvigorfile.ts new file mode 100644 index 0000000..4218707 --- /dev/null +++ b/OpenHarmony/library/hvigorfile.ts @@ -0,0 +1,6 @@ +import { harTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: harTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/OpenHarmony/library/index.d.ts b/OpenHarmony/library/index.d.ts new file mode 100644 index 0000000..6f1e930 --- /dev/null +++ b/OpenHarmony/library/index.d.ts @@ -0,0 +1,152 @@ +/* +Copyright (c) 2022 Huawei Device 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 cryptoFramework from '@ohos.security.cryptoFramework'; + +declare namespace Jwks { + + class JwksClient { + constructor(options: Options); + + /** + * get all keys data. + * + * @return all keys data from http. + * @since 9 + */ + getKeys(): Promise; + + /** + * get all SigningKeys. Convert keys data into SigningKey + * + * @return all SigningKeys. + * @since 9 + */ + getSigningKeys(): Promise; + + /** + * Obtain the SigningKey based on the id. + * + * @param The unique id of jwk. + * @return SigningKey. + * @since 9 + */ + getSigningKey(kid: string | null | undefined): Promise; + } + + /** + * HTTP request header. + */ + interface Headers { + [key: string]: string; + } + + /** + * options to create JwksClient. + */ + interface Options { + /** + * URL for initiating an HTTP request. + */ + jwksUri: string; + /** + * whether to use rateLimit. + */ + rateLimit?: boolean; + /** + * whether to use cache. + */ + cache?: boolean; + /** + * Cache size. + */ + cacheMaxEntries?: number; + /** + * Cache time. + */ + cacheMaxAge?: number; + /** + * Number of requests per minute. + */ + jwksRequestsPerMinute?: number; + /** + * HTTP request header. + */ + requestHeaders?: Headers; + /** + * timeout period. The default value is 30,000, in ms. + */ + timeout?: number; + } + + interface SigningKey { + /** + * The unique id of jwk. + */ + kid: string; + /** + * The algorithm id of jwk. + */ + algorithm: string; + /** + * The type id of jwk. + */ + type: string; + /** + * The usage id of jwk. + */ + usage: string; + /** + * Obtain the PublicKey. + * + * @return PublicKey {@link cryptoFramework.PubKey}. + * @since 9 + */ + getPublicKey(): cryptoFramework.PubKey; + } + + /** + * class to handle ArgumentError. + */ + class ArgumentError extends Error { + name: 'ArgumentError'; + constructor(message: string); + } + + /** + * class to handle JwksError. + */ + class JwksError extends Error { + name: 'JwksError'; + constructor(message: string); + } + + /** + * class to handle JwksRateLimitError. + */ + class JwksRateLimitError extends Error { + name: 'JwksRateLimitError'; + constructor(message: string); + } + + /** + * class to handle SigningKeyNotFoundError. + */ + class SigningKeyNotFoundError extends Error { + name: 'SigningKeyNotFoundError'; + constructor(message: string); + } +} + +export default Jwks; \ No newline at end of file diff --git a/OpenHarmony/library/index.ets b/OpenHarmony/library/index.ets new file mode 100644 index 0000000..9d5afec --- /dev/null +++ b/OpenHarmony/library/index.ets @@ -0,0 +1,16 @@ +/* +Copyright (c) 2022 Huawei Device 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. +*/ + +export {JwksClient} from './src/main/ets/common/JwksClient' \ No newline at end of file diff --git a/OpenHarmony/library/obfuscation-rules.txt b/OpenHarmony/library/obfuscation-rules.txt new file mode 100644 index 0000000..69c4d6a --- /dev/null +++ b/OpenHarmony/library/obfuscation-rules.txt @@ -0,0 +1,18 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope \ No newline at end of file diff --git a/OpenHarmony/library/oh-package-lock.json5 b/OpenHarmony/library/oh-package-lock.json5 new file mode 100644 index 0000000..ee0f722 --- /dev/null +++ b/OpenHarmony/library/oh-package-lock.json5 @@ -0,0 +1,13 @@ +{ + "lockfileVersion": 1, + "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", + "specifiers": { + "limiter@^1.1.5": "limiter@1.1.5" + }, + "packages": { + "limiter@1.1.5": { + "resolved": "https://repo.harmonyos.com/ohpm/limiter/-/limiter-1.1.5.tgz", + "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" + } + } +} \ No newline at end of file diff --git a/OpenHarmony/library/oh-package.json5 b/OpenHarmony/library/oh-package.json5 new file mode 100644 index 0000000..70f57b9 --- /dev/null +++ b/OpenHarmony/library/oh-package.json5 @@ -0,0 +1,27 @@ +{ + "keywords": [ + "Tool", + "OpenHarmony", + "rsa", + "jwks" + ], + "author": "ohos_tpc", + "description": "用于从 JWKS(JSON Web 密钥集)端点检索RSA签名密钥的库,支持所有当前注册的 JWK 类型和 JWS 算法", + "ohos": { + "org": "opensource" + }, + "main": "index.ets", + "repository": "https://gitcode.com/openharmony-tpc/openharmony_tpc_samples/tree/master/jwks-rsa", + "type": "module", + "version": "2.0.1", + "dependencies": { + "limiter": "^1.1.5" + }, + "tags": [ + "Tool" + ], + "compileOnlyDependencies": {}, + "license": "MIT License", + "devDependencies": {}, + "name": "@ohos/jwks_rsa" +} diff --git a/OpenHarmony/library/src/main/ets/common/JwksClient.js b/OpenHarmony/library/src/main/ets/common/JwksClient.js new file mode 100644 index 0000000..65c7dca --- /dev/null +++ b/OpenHarmony/library/src/main/ets/common/JwksClient.js @@ -0,0 +1,107 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +import {retrieveSigningKeys } from './utils'; +import {rateLimitWrapper} from "./wrappers/rateLimit" +import {getKeysInterceptor} from "./wrappers/interceptor" +import {cacheWrapper} from "./wrappers/cache" +import {callbackSupport} from "./wrappers/callbackSupport" +import {Request} from "./wrappers/request" + +import JwksError from './errors/JwksError' +import SigningKeyNotFoundError from './errors/SigningKeyNotFoundError' + +let requestInstance = new Request() +//Provide external interfaces +export class JwksClient { + constructor(options) { + this.options = { + rateLimit: false, + cache: true, + timeout: 30000, + ...options + }; + // Initialize wrappers. + if (this.options.getKeysInterceptor) { + this.getSigningKey = getKeysInterceptor(this, options); + } + + if (this.options.rateLimit) { + this.getSigningKey = rateLimitWrapper(this, options); + } + if (this.options.cache) { + this.getSigningKey = cacheWrapper(this, options); + } + + this.getSigningKey = callbackSupport(this); + } + + async getKeys() { + console.info(`Fetching keys from '${this.options.jwksUri}'`); + try { + const res = await requestInstance.request({ + uri: this.options.jwksUri, + headers: this.options.requestHeaders, + agent: this.options.requestAgent, + timeout: this.options.timeout, + fetcher: this.options.fetcher + }); + console.info("http data = " + JSON.stringify(res.keys)) + return res.keys; + } catch (err) { + const { errorMsg } = err; + console.info('Failure:', errorMsg || err); + throw (errorMsg ? new JwksError(errorMsg) : err); + } + } + + async getSigningKeys() { + const keys = await this.getKeys(); + + if (!keys || !keys.length) { + throw new JwksError('The JWKS endpoint did not contain any keys'); + } + + const signingKeys = retrieveSigningKeys(keys); + if (!signingKeys.length) { + throw new JwksError('The JWKS endpoint did not contain any signing keys'); + } + return signingKeys; + } + + async getSigningKey (kid) { + console.info(`Fetching signing key for '${kid}'`); + const keys = await this.getSigningKeys(); + const kidDefined = kid !== undefined && kid !== null; + if (!kidDefined && keys.length > 1) { + throw new SigningKeyNotFoundError('No KID specified and JWKS endpoint returned more than 1 key'); + } + + const key = keys.find(k => !kidDefined || k.kid === kid); + if (key) { + return key; + } else { + throw new SigningKeyNotFoundError('Unable to find a signing key that matches'); + } + } +} diff --git a/OpenHarmony/library/src/main/ets/common/errors/ArgumentError.js b/OpenHarmony/library/src/main/ets/common/errors/ArgumentError.js new file mode 100644 index 0000000..619c032 --- /dev/null +++ b/OpenHarmony/library/src/main/ets/common/errors/ArgumentError.js @@ -0,0 +1,29 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +export default class ArgumentError extends Error { + constructor(message) { + super(message) + this.name = 'ArgumentError' + } +} \ No newline at end of file diff --git a/OpenHarmony/library/src/main/ets/common/errors/JwksError.js b/OpenHarmony/library/src/main/ets/common/errors/JwksError.js new file mode 100644 index 0000000..1cb8178 --- /dev/null +++ b/OpenHarmony/library/src/main/ets/common/errors/JwksError.js @@ -0,0 +1,29 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +export default class JwksError extends Error { + constructor(message) { + super(message) + this.name = 'JwksError' + } +} \ No newline at end of file diff --git a/OpenHarmony/library/src/main/ets/common/errors/JwksRateLimitError.js b/OpenHarmony/library/src/main/ets/common/errors/JwksRateLimitError.js new file mode 100644 index 0000000..2a997e5 --- /dev/null +++ b/OpenHarmony/library/src/main/ets/common/errors/JwksRateLimitError.js @@ -0,0 +1,29 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +export default class JwksRateLimitError extends Error { + constructor(message) { + super(message) + this.name = 'JwksRateLimitError' + } +} diff --git a/OpenHarmony/library/src/main/ets/common/errors/SigningKeyNotFoundError.js b/OpenHarmony/library/src/main/ets/common/errors/SigningKeyNotFoundError.js new file mode 100644 index 0000000..98b4db7 --- /dev/null +++ b/OpenHarmony/library/src/main/ets/common/errors/SigningKeyNotFoundError.js @@ -0,0 +1,29 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +export default class SigningKeyNotFoundError extends Error { + constructor(message) { + super(message) + this.name = 'SigningKeyNotFoundError' + } +} diff --git a/OpenHarmony/library/src/main/ets/common/errors/index.js b/OpenHarmony/library/src/main/ets/common/errors/index.js new file mode 100644 index 0000000..7e0a015 --- /dev/null +++ b/OpenHarmony/library/src/main/ets/common/errors/index.js @@ -0,0 +1,29 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +module.exports = { + ArgumentError: require('./ArgumentError'), + JwksError: require('./JwksError'), + JwksRateLimitError: require('./JwksRateLimitError'), + SigningKeyNotFoundError: require('./SigningKeyNotFoundError') +}; diff --git a/OpenHarmony/library/src/main/ets/common/utils.js b/OpenHarmony/library/src/main/ets/common/utils.js new file mode 100644 index 0000000..2da4dc2 --- /dev/null +++ b/OpenHarmony/library/src/main/ets/common/utils.js @@ -0,0 +1,159 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +import cryptoFramework from '@ohos.security.cryptoFramework'; +import SigningKeyNotFoundError from '../common/errors/SigningKeyNotFoundError' + +import buffer from '@ohos.buffer'; + +const ALGORITHM_RSA = "RSA"; +const ALGORITHM_RSA2048 = "RSA2048"; +const ALGORITHM_ELLIPTIC_CURVE = "EC"; +const ALGORITHM_ECC256 = "ECC256"; +const ALGORITHM_ECC384 = "ECC384"; +const ALGORITHM_ECC512 = "ECC512"; +const ELLIPTIC_CURVE_TYPE_P256 = "P-256"; +const ELLIPTIC_CURVE_TYPE_P384 = "P-384"; +const ELLIPTIC_CURVE_TYPE_P512 = "P-512"; + +export function retrieveSigningKeys(keys) { + + return keys.map((key) => { + return { + kid: key.kid, + algorithm: key.alg, + type: key.kty, + usage: key.use, + x5u: key.x5u, + x5c: key.x5c, + x5t: key.x5t, + async getPublicKey() { + return await convertKey(key); + } + }; + }); + return keys +}; + +function base64ToBigNum(value){ + const buf = buffer.from(value,'base64'); + return "0x"+ buf.toString('hex') +} +// Compare the RSA public key specifications with the expected values. +function compareRsaPubKeyBySpec(rsaKeySpec, n, e) { + if (typeof n === 'string' || typeof e === 'string') { + console.error('type is string'); + return false; + } + if (typeof n === 'number' || typeof e === 'number') { + console.error('type is number'); + return false; + } + if (rsaKeySpec.params.n != n) { + return false; + } + if (rsaKeySpec.pk != e) { + return false; + } + return true; +} +function genEccCommonSpec(p,x,y,a,b,n) { + let fieldFp = { + fieldType: "Fp", + p: BigInt(p) + } + +let G = { + x: BigInt(x), + y: BigInt(y) +} + +let eccCommonSpec= { + algName: "ECC", + specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC, + field: fieldFp, + a: BigInt(a), + b: BigInt(b), + g: G, + n: BigInt(n), + h: 1 +} +return eccCommonSpec; +} + +async function convertKey(key) { + console.info("jwks_rsa converkey:"+JSON.stringify(key)) + var asyKeyGenerator; + switch(key.kty) { + case ALGORITHM_RSA: + let n = buffer.from(key.n,'base64') + let e = buffer.from(key.e,'base64') + let bN = base64ToBigNum(n); + let eN = base64ToBigNum(e); + var commonSpec = { + algName:"RSA", + specType:cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC, + n:BigInt(bN) + } + var rsaSpec = { + algName:"RSA", + specType:cryptoFramework.AsyKeySpecType.PUBLIC_KEY_SPEC, + params : commonSpec, + pk :BigInt(eN), + } + asyKeyGenerator = cryptoFramework.createAsyKeyGeneratorBySpec(rsaSpec); + const pubKey = await asyKeyGenerator.generatePubKey() + let nBN = pubKey.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.RSA_N_BN); + let eBN = pubKey.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.RSA_PK_BN); + if (compareRsaPubKeyBySpec(rsaSpec, nBN, eBN) != true) { + console.error("jwks_rsa error pub key big number") + } else { + console.info("jwks_rsa n, e in the pubKey are same as the spec."); + return pubKey; + } + break; + case ALGORITHM_ELLIPTIC_CURVE: + let x = buffer.from(key.x,'base64'); + let y = buffer.from(key.y,'base64'); + let p = buffer.from(key.p,'base64'); + let a = buffer.from(key.a,'base64'); + let b = buffer.from(key.b,'base64'); + let cn = buffer.from(key.n,'base64'); + + let xN = base64ToBigNum(x); + let yN = base64ToBigNum(y); + let pN = base64ToBigNum(p); + let aN = base64ToBigNum(a); + let cbN = base64ToBigNum(b); + let nN = base64ToBigNum(cn); + var eccSpec = genEccCommonSpec(pN,xN,yN,aN,cbN,nN); + asyKeyGenerator = cryptoFramework.createAsyKeyGeneratorBySpec(eccSpec); + const eccPubKey = await asyKeyGenerator.generatePubKey(); + return eccPubKey; + default: + throw new SigningKeyNotFoundError("The key type of " + key.kty + " is not supported"); + } +} + + + diff --git a/OpenHarmony/library/src/main/ets/common/wrappers/cache.js b/OpenHarmony/library/src/main/ets/common/wrappers/cache.js new file mode 100644 index 0000000..ee257cf --- /dev/null +++ b/OpenHarmony/library/src/main/ets/common/wrappers/cache.js @@ -0,0 +1,94 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +import HashMap from '@ohos.util.HashMap'; + +let hashMap = new HashMap(); +let hashMapInformation = new HashMap(); +export function cacheWrapper(client, { cacheMaxEntries = 5, cacheMaxAge = 600000 }) { + console.info(`Configured caching of signing keys. Max: ${cacheMaxEntries} / Age: ${cacheMaxAge}`) + const getSigningKey = client.getSigningKey.bind(client) + + return async(kid)=>{ + handleHashMapInformation(cacheMaxAge) + if(hashMap.hasKey(kid)) { + hashMapInformation.replace(kid, Date.now()) + return hashMap.get(kid) + } else { + cacheMaxEntriesControl(cacheMaxEntries) + const singingKey = await getSigningKey(kid) + hashMap.set(kid, singingKey) + hashMapInformation.set(kid, Date.now()) + return singingKey + } + } +} + +//Expiration of processing validity + function handleHashMapInformation(cacheMaxAge){ + //cacheMaxEntries + if(hashMapInformation.length > 0) { + let hashMapOverdue = new HashMap(); + let nowTime = Date.now() + let keys = hashMapInformation.keys() + let key = keys.next().value; + while(key != undefined) { + //cacheMaxAge + if((nowTime - hashMapInformation.get(key)) > cacheMaxAge) { + hashMapOverdue.set(key, hashMap.get(key)) + } + key = keys.next().value; + } + let hashMapOverdueKeys = hashMapOverdue.keys() + let hashMapOverdueKey = hashMapOverdueKeys.next().value + while(hashMapOverdueKey != undefined){ + if(hashMap.hasKey(hashMapOverdueKey)) { + hashMap.remove(hashMapOverdueKey) + hashMapInformation.remove(hashMapOverdueKey) + } + hashMapOverdueKey = hashMapOverdueKeys.next().value + } + } +} + +//Exceeds the maximum number +function cacheMaxEntriesControl(cacheMaxEntries){ + if(hashMapInformation.length >= cacheMaxEntries){ + let nowTime = Date.now() + let tempValue = nowTime + let tempKey = "" + let keys = hashMapInformation.keys() + let key = keys.next().value; + while(key != undefined) { + //cacheMaxAge + if(hashMapInformation.get(key) < tempValue) { + tempValue = hashMapInformation.get(key) + tempKey = key + } + key = keys.next().value; + } + hashMapInformation.remove(tempKey) + hashMap.remove(tempKey) + } +} + + diff --git a/OpenHarmony/library/src/main/ets/common/wrappers/callbackSupport.js b/OpenHarmony/library/src/main/ets/common/wrappers/callbackSupport.js new file mode 100644 index 0000000..f070ecc --- /dev/null +++ b/OpenHarmony/library/src/main/ets/common/wrappers/callbackSupport.js @@ -0,0 +1,29 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +export function callbackSupport(client) { + const getSigningKey = client.getSigningKey.bind(client); + return async (kid, cb) => { + return await getSigningKey(kid) + }; +}; + diff --git a/OpenHarmony/library/src/main/ets/common/wrappers/interceptor.js b/OpenHarmony/library/src/main/ets/common/wrappers/interceptor.js new file mode 100644 index 0000000..f99c44d --- /dev/null +++ b/OpenHarmony/library/src/main/ets/common/wrappers/interceptor.js @@ -0,0 +1,49 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +import {retrieveSigningKeys} from '../utils'; + +/** + * Uses getKeysInterceptor to allow users to retrieve keys from a file,external cache, or provided object before falling back to the jwksUri endpoint + */ + +export function getKeysInterceptor(client, { getKeysInterceptor }) { + const getSigningKey = client.getSigningKey.bind(client); + + return async (kid) => { + const keys = await getKeysInterceptor(); + let signingKeys; + if (keys && keys.length) { + signingKeys = retrieveSigningKeys(keys); + } + if (signingKeys && signingKeys.length) { + const key = signingKeys.find(k =>!kid || k.kid === kid); + if (key) { + return key; + } + } + return getSigningKey(kid); + }; +} + + + diff --git a/OpenHarmony/library/src/main/ets/common/wrappers/rateLimit.js b/OpenHarmony/library/src/main/ets/common/wrappers/rateLimit.js new file mode 100644 index 0000000..e537837 --- /dev/null +++ b/OpenHarmony/library/src/main/ets/common/wrappers/rateLimit.js @@ -0,0 +1,43 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +import { RateLimiter } from 'limiter'; + +export function rateLimitWrapper(client, { jwksRequestsPerMinute = 5 }) { + const getSigningKey = client.getSigningKey.bind(client); + const limiter = new RateLimiter({tokensPerInterval:jwksRequestsPerMinute, interval:'minute', fireImmediately:true}); + console.info(`Configured rate limiting to JWKS endpoint at ${jwksRequestsPerMinute}/minute`); + + return async (kid) => { + if (limiter.tryRemoveTokens(1)) { + try { + return await getSigningKey(kid); + } catch (error) { + console.info(error); + } + } else { + console.info(`Too many requests to the JWKS endpoint`); + } + } +} + + diff --git a/OpenHarmony/library/src/main/ets/common/wrappers/request.js b/OpenHarmony/library/src/main/ets/common/wrappers/request.js new file mode 100644 index 0000000..53cdb24 --- /dev/null +++ b/OpenHarmony/library/src/main/ets/common/wrappers/request.js @@ -0,0 +1,59 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import http from '@ohos.net.http'; +import prompt from '@ohos.prompt'; + +export class Request{ + request(options){ + return new Promise((resolve, reject) => { + var keysResult = null + if (options.fetcher) { + return options.fetcher(options.uri); + } + let httpRequest = http.createHttp(); + let promise = httpRequest.request(options.uri, + { + method: http.RequestMethod.GET, // 可选,默认为http.RequestMethod.GET + header: options.requestHeaders, + connectTimeout: options.timeout, // 可选,默认为60000ms + readTimeout: options.timeout, // 可选,默认为60000ms + } + ); + promise.then((data)=> { + // data.result为HTTP响应内容,可根据业务需要进行解析 + keysResult = JSON.parse((String)(data.result)) + resolve(keysResult) + }).catch((err) => { + console.error('http error:' + JSON.stringify(err)); + prompt.showToast({ + message: '网络错误: ' + JSON.stringify(err), + duration: 1000 + }) + }).finally(() => { + httpRequest.destroy(); + }); + }) + } +} + diff --git a/OpenHarmony/library/src/main/module.json5 b/OpenHarmony/library/src/main/module.json5 new file mode 100644 index 0000000..2ccdcbf --- /dev/null +++ b/OpenHarmony/library/src/main/module.json5 @@ -0,0 +1,10 @@ +{ + "module": { + "name": "library", + "type": "har", + "deviceTypes": [ + "default", + "tablet" + ] + } +} diff --git a/OpenHarmony/library/src/main/resources/base/element/string.json b/OpenHarmony/library/src/main/resources/base/element/string.json new file mode 100644 index 0000000..1e76de0 --- /dev/null +++ b/OpenHarmony/library/src/main/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from npm package" + } + ] +} diff --git a/OpenHarmony/library/src/main/resources/en_US/element/string.json b/OpenHarmony/library/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000..1e76de0 --- /dev/null +++ b/OpenHarmony/library/src/main/resources/en_US/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from npm package" + } + ] +} diff --git a/OpenHarmony/library/src/main/resources/zh_CN/element/string.json b/OpenHarmony/library/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000..1e76de0 --- /dev/null +++ b/OpenHarmony/library/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from npm package" + } + ] +} diff --git a/OpenHarmony/oh-package.json5 b/OpenHarmony/oh-package.json5 new file mode 100644 index 0000000..693e4c9 --- /dev/null +++ b/OpenHarmony/oh-package.json5 @@ -0,0 +1,12 @@ +{ + "license": "", + "devDependencies": { + "@ohos/hypium": "1.0.6" + }, + "author": "", + "name": "jwks_rsa", + "description": "Please describe the basic information.", + "main": "", + "version": "2.0.1", + "dependencies": {} +}