@oniroproject/oniro-app 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +116 -1
- package/dist/oniro-app.js +104 -9
- package/dist/oniro-app.js.map +1 -1
- package/package.json +2 -2
- package/templates/HarmonyOSApp/AppScope/app.json5 +10 -0
- package/templates/HarmonyOSApp/AppScope/resources/base/element/string.json +8 -0
- package/templates/HarmonyOSApp/AppScope/resources/base/media/background.png +0 -0
- package/templates/HarmonyOSApp/AppScope/resources/base/media/foreground.png +0 -0
- package/templates/HarmonyOSApp/AppScope/resources/base/media/layered_image.json +7 -0
- package/templates/HarmonyOSApp/build-profile.json5 +35 -0
- package/templates/HarmonyOSApp/entry/build-profile.json5 +33 -0
- package/templates/HarmonyOSApp/entry/hvigorfile.ts +6 -0
- package/templates/HarmonyOSApp/entry/obfuscation-rules.txt +23 -0
- package/templates/HarmonyOSApp/entry/oh-package.json5 +10 -0
- package/templates/HarmonyOSApp/entry/src/main/ets/entryability/EntryAbility.ets +48 -0
- package/templates/HarmonyOSApp/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets +16 -0
- package/templates/HarmonyOSApp/entry/src/main/ets/pages/Index.ets +23 -0
- package/templates/HarmonyOSApp/entry/src/main/module.json5 +50 -0
- package/templates/HarmonyOSApp/entry/src/main/resources/base/element/color.json +8 -0
- package/templates/HarmonyOSApp/entry/src/main/resources/base/element/float.json +8 -0
- package/templates/HarmonyOSApp/entry/src/main/resources/base/element/string.json +16 -0
- package/templates/HarmonyOSApp/entry/src/main/resources/base/media/background.png +0 -0
- package/templates/HarmonyOSApp/entry/src/main/resources/base/media/foreground.png +0 -0
- package/templates/HarmonyOSApp/entry/src/main/resources/base/media/layered_image.json +7 -0
- package/templates/HarmonyOSApp/entry/src/main/resources/base/media/startIcon.png +0 -0
- package/templates/HarmonyOSApp/entry/src/main/resources/base/profile/backup_config.json +3 -0
- package/templates/HarmonyOSApp/entry/src/main/resources/base/profile/main_pages.json +5 -0
- package/templates/HarmonyOSApp/entry/src/main/resources/dark/element/color.json +8 -0
- package/templates/HarmonyOSApp/entry/src/mock/mock-config.json5 +2 -0
- package/templates/HarmonyOSApp/entry/src/ohosTest/ets/test/Ability.test.ets +35 -0
- package/templates/HarmonyOSApp/entry/src/ohosTest/ets/test/List.test.ets +5 -0
- package/templates/HarmonyOSApp/entry/src/ohosTest/module.json5 +11 -0
- package/templates/HarmonyOSApp/entry/src/test/List.test.ets +5 -0
- package/templates/HarmonyOSApp/entry/src/test/LocalUnit.test.ets +33 -0
- package/templates/HarmonyOSApp/hvigor/hvigor-config.json5 +23 -0
- package/templates/HarmonyOSApp/hvigorfile.ts +6 -0
- package/templates/HarmonyOSApp/oh-package.json5 +10 -0
- package/templates/HarmonyOSApp/template.json +6 -0
package/README.md
CHANGED
|
@@ -103,7 +103,7 @@ All flags are required except where a default is shown (non-interactive). On suc
|
|
|
103
103
|
| `--bundle <bundleName>` | Bundle name in reverse-DNS form, e.g. `com.example.myapp`. |
|
|
104
104
|
| `--location <dir>` | Parent directory the new project folder is created in. |
|
|
105
105
|
| `--sdk <api>` | Target SDK API level (e.g. `18`, `20`). |
|
|
106
|
-
| `--template <id>` | Template id (default `EmptyAbility`). |
|
|
106
|
+
| `--template <id>` | Template id (default `EmptyAbility`; `HarmonyOSApp` targets HarmonyOS). |
|
|
107
107
|
| `--module <name>` | Module folder name (defaults to the template default, usually `entry`). |
|
|
108
108
|
| `--overwrite` | Replace the destination if it already exists. |
|
|
109
109
|
|
|
@@ -113,6 +113,17 @@ All flags are required except where a default is shown (non-interactive). On suc
|
|
|
113
113
|
| --- | --- |
|
|
114
114
|
| `templates list [--json]` | List the project templates shipped with the CLI. |
|
|
115
115
|
|
|
116
|
+
#### `auth` — sign in to a Huawei developer account
|
|
117
|
+
|
|
118
|
+
Only needed for HarmonyOS signing; see [HarmonyOS apps](#harmonyos-apps).
|
|
119
|
+
|
|
120
|
+
| Command | Description |
|
|
121
|
+
| --- | --- |
|
|
122
|
+
| `auth login [--timeout <s>]` | Sign in via the browser (default timeout 600s). |
|
|
123
|
+
| `auth logout` | Delete the locally stored token. |
|
|
124
|
+
| `auth status [--json]` | Show the signed-in account; exits non-zero when signed out. |
|
|
125
|
+
| `auth team list [--json]` | List AGC teams. |
|
|
126
|
+
|
|
116
127
|
#### `sign` — generate signing keys, certs, and `signingConfigs`
|
|
117
128
|
|
|
118
129
|
`sign [project-dir]` (defaults to the current directory). Requires `java` on `PATH`. Rewrites only the `signingConfigs` block of `build-profile.json5` (other keys are preserved). The generated profile uses the SDK's built-in development cert (`issuer=pki_internal`) and its validity window — **dev/local builds only, not distribution.** See [Signing apps that need system permissions](#signing-apps-that-need-system-permissions) for `--apl` / `--acls`.
|
|
@@ -123,6 +134,10 @@ All flags are required except where a default is shown (non-interactive). On suc
|
|
|
123
134
|
| `--app-feature <feature>` | `hos_normal_app` or `hos_system_app`. Defaults follow `--apl`. |
|
|
124
135
|
| `--acls <list>` | Comma-separated permissions to write into the profile's `acls.allowed-acls`. |
|
|
125
136
|
| `--bootstrap` | No-op if signing material is already present; otherwise generate it. |
|
|
137
|
+
| `--harmonyos` | Sign a HarmonyOS project via AppGallery Connect instead of the offline flow. See [HarmonyOS apps](#harmonyos-apps). |
|
|
138
|
+
| `--team-id <id>` | With `--harmonyos`: AGC team to sign under. |
|
|
139
|
+
| `--product <name>` | With `--harmonyos`: product to sign (default `default`). |
|
|
140
|
+
| `--force` | With `--harmonyos`: regenerate even when the existing material is still valid. |
|
|
126
141
|
| `--store-password <pwd>` / `--key-password <pwd>` | Keystore passwords (default `123456`, the SDK keystore password). |
|
|
127
142
|
|
|
128
143
|
#### `build` — build the app via `hvigorw`
|
|
@@ -300,6 +315,9 @@ The CLI reads paths and URLs from environment variables. All are optional; defau
|
|
|
300
315
|
| `ONIRO_EMULATOR_URL` | Latest `oniro_emulator.zip` | Emulator download URL |
|
|
301
316
|
| `ONIRO_TMP_DIR` | `<install root>/.oniro-tmp` | Scratch directory for download/extract temporaries (see [Temporary space](#temporary-space)) |
|
|
302
317
|
| `ONIRO_APPLICATION_CERT_PATH` | (unset) | External application-cert chain to use when signing system apps |
|
|
318
|
+
| `ONIRO_HARMONYOS_SDK_PATH` | autodetected | HarmonyOS SDK: a DevEco Studio or HarmonyOS command-line-tools install, or its `sdk` directory |
|
|
319
|
+
| `ONIRO_HARMONYOS_AUTH_DIR` | `~/.oniro/harmonyos` | Where the encrypted Huawei account token is stored |
|
|
320
|
+
| `ONIRO_HARMONYOS_SIGNING_DIR` | `~/.ohos/config` | Where generated HarmonyOS signing material (p12/csr/cer/p7b) is written |
|
|
303
321
|
| `ONIRO_DEBUG` | (unset) | Set to `1` for full stack traces on error |
|
|
304
322
|
|
|
305
323
|
### Temporary space
|
|
@@ -332,6 +350,103 @@ through.
|
|
|
332
350
|
|
|
333
351
|
**Command-line tools on Windows / macOS.** The Huawei mirror only publishes a Linux build of the command-line tools. On Windows and macOS you must either download the ZIP manually from the Huawei developer portal and install it with `oniro-app cmdtools install --from-zip path/to/commandline-tools-<platform>.zip`, or host the archive yourself and set `ONIRO_CMD_TOOLS_URL_WINDOWS` / `ONIRO_CMD_TOOLS_URL_MAC` so `cmdtools install` can fetch it.
|
|
334
352
|
|
|
353
|
+
## HarmonyOS apps
|
|
354
|
+
|
|
355
|
+
`oniro-app` builds and signs **HarmonyOS** projects as well as OpenHarmony ones. A project
|
|
356
|
+
is HarmonyOS when its product declares `runtimeOS: "HarmonyOS"` in `build-profile.json5`, as
|
|
357
|
+
DevEco Studio writes; every other project is OpenHarmony and behaves exactly as before.
|
|
358
|
+
|
|
359
|
+
The two paths differ in one way that matters:
|
|
360
|
+
|
|
361
|
+
| | OpenHarmony | HarmonyOS |
|
|
362
|
+
| --- | --- | --- |
|
|
363
|
+
| SDK | `oniro-app sdk install` downloads it | Ships inside DevEco Studio or the HarmonyOS command-line tools. Found automatically in Studio's default location or at the command-line-tools path; otherwise set `ONIRO_HARMONYOS_SDK_PATH` |
|
|
364
|
+
| Signing | `oniro-app sign` — fully offline, uses the SDK's development certificate | `oniro-app sign --harmonyos` — AppGallery Connect issues the certificate and profile |
|
|
365
|
+
| Account | none | a Huawei developer account (`oniro-app auth login`) |
|
|
366
|
+
| Network | none | required |
|
|
367
|
+
| Device | not required | one registered to the AGC team — a debug profile names the devices it is valid for |
|
|
368
|
+
|
|
369
|
+
### Workflow
|
|
370
|
+
|
|
371
|
+
```bash
|
|
372
|
+
oniro-app auth login # once per machine
|
|
373
|
+
oniro-app create --name MyApp --bundle com.example.myapp \
|
|
374
|
+
--location ~/projects --sdk 24 --template HarmonyOSApp
|
|
375
|
+
cd ~/projects/MyApp
|
|
376
|
+
oniro-app sign --harmonyos # registers any connected device
|
|
377
|
+
oniro-app build
|
|
378
|
+
oniro-app app install && oniro-app app launch
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
Pass `--sdk` the API level of the installed HarmonyOS SDK (`apiVersion` in its
|
|
382
|
+
`default/sdk-pkg.json`). hvigor builds a HarmonyOS project only against the release its
|
|
383
|
+
`compileSdkVersion` names ("SDK component missing" otherwise), so `create` writes the
|
|
384
|
+
installed SDK's release, e.g. `6.1.1(24)`, and warns when `--sdk` asks for another one.
|
|
385
|
+
|
|
386
|
+
### `oniro-app auth`
|
|
387
|
+
|
|
388
|
+
| Command | What it does |
|
|
389
|
+
| --- | --- |
|
|
390
|
+
| `auth login [--timeout <s>]` | Opens the Huawei sign-in page and waits for the browser to redirect back to a loopback port. The URL is also printed, so a headless host can be signed in from another machine. |
|
|
391
|
+
| `auth logout` | Deletes the locally stored token. |
|
|
392
|
+
| `auth status [--json]` | Prints the signed-in account, and warns when it is not allowed to sign. Exits non-zero when signed out. |
|
|
393
|
+
| `auth team list [--json]` | Lists AGC teams; pass an id to `sign --harmonyos --team-id`. |
|
|
394
|
+
|
|
395
|
+
The token is stored encrypted under `ONIRO_HARMONYOS_AUTH_DIR`. It is a credential: the
|
|
396
|
+
directory is created `0700` and the files `0600`.
|
|
397
|
+
|
|
398
|
+
### `oniro-app sign --harmonyos`
|
|
399
|
+
|
|
400
|
+
Mirrors DevEco Studio's automatic signing:
|
|
401
|
+
|
|
402
|
+
1. generates a local p12 keystore and a CSR (via the SDK's `hap-sign-tool.jar`, so a JDK is needed — DevEco Studio's bundled JBR is used when present);
|
|
403
|
+
2. has AppGallery Connect issue a debug certificate for that CSR;
|
|
404
|
+
3. registers every connected device's UDID with the team — no device is needed when the team already has some registered (from another machine, or by DevEco Studio);
|
|
405
|
+
4. issues a debug provisioning profile naming that certificate, all of the team's registered devices, and any ACL-gated permissions the project requests;
|
|
406
|
+
5. writes an encrypted `signingConfigs` entry into `build-profile.json5`, leaving other entries untouched.
|
|
407
|
+
|
|
408
|
+
Material lands in `ONIRO_HARMONYOS_SIGNING_DIR` (default `~/.ohos/config`, the directory
|
|
409
|
+
DevEco Studio also uses) and is **reused**, without contacting AGC for anything, while it is
|
|
410
|
+
still valid: same bundle name and team, unexpired, naming the attached devices and requested
|
|
411
|
+
permissions, and wired into this project's `build-profile.json5`. Certificates are a small
|
|
412
|
+
per-team quota; `--force` regenerates anyway.
|
|
413
|
+
|
|
414
|
+
The AGC certificate is named `oniro_debug_<team>.cer`, distinct from DevEco Studio's
|
|
415
|
+
`auto_debug_<team>.cer`: each tool replaces only its own certificate when regenerating, so
|
|
416
|
+
using both on one team does not revoke the other's signing material.
|
|
417
|
+
|
|
418
|
+
| Flag | Meaning |
|
|
419
|
+
| --- | --- |
|
|
420
|
+
| `--harmonyos` | Use the AGC path instead of the offline OpenHarmony one |
|
|
421
|
+
| `--team-id <id>` | AGC team to issue under (default: the account's own id) |
|
|
422
|
+
| `--product <name>` | Product to sign (default `default`) |
|
|
423
|
+
| `--force` | Regenerate even when the existing material is still valid |
|
|
424
|
+
|
|
425
|
+
### Account regions
|
|
426
|
+
|
|
427
|
+
Accounts from every Huawei region can sign. Sign-in redirects to the account's own region,
|
|
428
|
+
which then decides the hosts every later call goes to — the ones DevEco Studio resolves
|
|
429
|
+
through Huawei's routing service:
|
|
430
|
+
|
|
431
|
+
| Region | Sign-in host | AGC signing host |
|
|
432
|
+
| --- | --- | --- |
|
|
433
|
+
| `CN` | `cn.devecostudio.huawei.com` | `connect-api.cloud.huawei.com` |
|
|
434
|
+
| `EU` | `de.devecostudio.huawei.com` | `connect-api-dre.cloud.huawei.com` |
|
|
435
|
+
| `SG` | `sg.devecostudio.huawei.com` | `connect-api-dra.cloud.huawei.com` |
|
|
436
|
+
| `RU` | `ru.devecostudio.huawei.com` | `connect-api-drru.cloud.huawei.com` |
|
|
437
|
+
|
|
438
|
+
The whole flow has been run with an `EU` account. Huawei's own CLI accepts only `CN` accounts.
|
|
439
|
+
|
|
440
|
+
### Limitations
|
|
441
|
+
|
|
442
|
+
- **Real-name verification is not required**, but an account without it must have accepted
|
|
443
|
+
the current HUAWEI Developer Basic Service Agreement — in AppGallery Connect, or by running
|
|
444
|
+
automatic signing once in DevEco Studio. `oniro-app auth status --json` reports it as
|
|
445
|
+
`developerAgreement`; `oniro-app` checks it but never accepts it for you.
|
|
446
|
+
- A refusal from AGC surfaces as a permissions or not-enrolled error, not as a crash.
|
|
447
|
+
- The AGC endpoints are private and undocumented, and can change without notice. See
|
|
448
|
+
`packages/core/src/harmonyos/NOTICE.md` for provenance and attribution.
|
|
449
|
+
|
|
335
450
|
## Signing apps that need system permissions
|
|
336
451
|
|
|
337
452
|
`oniro-app sign` defaults to `--apl normal` / `--app-feature hos_normal_app`, which is fine for ordinary apps. Apps that request permissions above `normal` (anything with `system_basic` or `system_core` availability — e.g. `ohos.permission.GET_WIFI_INFO_INTERNAL`, `ohos.permission.ACCESS_PIN_AUTH`) need a higher APL, otherwise `bm install` fails with `grant request permissions failed`.
|
package/dist/oniro-app.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/bin/oniro-app.ts
|
|
4
4
|
import { Command as Command4 } from "commander";
|
|
5
|
-
import { OniroError } from "@oniroproject/core";
|
|
5
|
+
import { OniroError as OniroError2 } from "@oniroproject/core";
|
|
6
6
|
|
|
7
7
|
// src/commands/sdk.ts
|
|
8
8
|
import * as fs from "fs";
|
|
@@ -73,7 +73,10 @@ var ENV_VAR_BY_KEY = {
|
|
|
73
73
|
emulatorUrl: "ONIRO_EMULATOR_URL",
|
|
74
74
|
tmpDir: "ONIRO_TMP_DIR",
|
|
75
75
|
sdkUrlBase: "ONIRO_SDK_URL_BASE",
|
|
76
|
-
applicationCertPath: "ONIRO_APPLICATION_CERT_PATH"
|
|
76
|
+
applicationCertPath: "ONIRO_APPLICATION_CERT_PATH",
|
|
77
|
+
harmonyosSdkPath: "ONIRO_HARMONYOS_SDK_PATH",
|
|
78
|
+
harmonyosAuthDir: "ONIRO_HARMONYOS_AUTH_DIR",
|
|
79
|
+
harmonyosSigningDir: "ONIRO_HARMONYOS_SIGNING_DIR"
|
|
77
80
|
};
|
|
78
81
|
function createEnvConfig(env = process.env) {
|
|
79
82
|
return {
|
|
@@ -252,7 +255,9 @@ function registerEmulatorCommand(program) {
|
|
|
252
255
|
import * as path2 from "path";
|
|
253
256
|
import { buildHap } from "@oniroproject/core";
|
|
254
257
|
function registerBuildCommand(program) {
|
|
255
|
-
program.command("build [project-dir]").description(
|
|
258
|
+
program.command("build [project-dir]").description(
|
|
259
|
+
'Build an OpenHarmony or HarmonyOS app via hvigorw. Defaults to the current directory. Projects declaring runtimeOS "HarmonyOS" build against the HarmonyOS SDK (ONIRO_HARMONYOS_SDK_PATH or an installed DevEco Studio).'
|
|
260
|
+
).option("--product <product>", "hvigor product name", "default").option("--module <module>", "restrict the build to a specific module").option("--mode <mode>", "hvigor build mode (e.g. release, debug)").option("--task <task>", "hvigor task to run", "assembleHap").option("--no-deps", "skip the automatic `ohpm install --all` when oh_modules/ is missing").option("--no-parallel", "build modules serially (default: parallel)").option("--json", "emit the build result (discovered HAPs, warnings) as JSON").action(async (projectDir, opts) => {
|
|
256
261
|
const { config, logger } = getRuntime();
|
|
257
262
|
const dir = path2.resolve(projectDir ?? process.cwd());
|
|
258
263
|
logger.info(`Building project at ${dir}...`);
|
|
@@ -285,7 +290,11 @@ import * as path3 from "path";
|
|
|
285
290
|
import {
|
|
286
291
|
APL_VALUES,
|
|
287
292
|
APP_FEATURE_VALUES,
|
|
293
|
+
OniroError,
|
|
294
|
+
createHarmonyOsSession,
|
|
295
|
+
detectRuntimeOs,
|
|
288
296
|
generateSigningConfigs,
|
|
297
|
+
harmonyOsAutoSign,
|
|
289
298
|
prepareSigning,
|
|
290
299
|
getOhosBaseSdkHome
|
|
291
300
|
} from "@oniroproject/core";
|
|
@@ -298,7 +307,9 @@ function registerSignCommand(program) {
|
|
|
298
307
|
"Generate signing keys, certificates, and signingConfigs for an OpenHarmony project.",
|
|
299
308
|
"Requires java on PATH. The generated profile uses the SDK's built-in development",
|
|
300
309
|
"cert (issuer=pki_internal) and its bundled validity window \u2014 dev/local builds only.",
|
|
301
|
-
"Overwrites the `signingConfigs` block in build-profile.json5 (other keys preserved)."
|
|
310
|
+
"Overwrites the `signingConfigs` block in build-profile.json5 (other keys preserved).",
|
|
311
|
+
"HarmonyOS projects need --harmonyos instead, which has AppGallery Connect issue the",
|
|
312
|
+
"certificate and profile for a signed-in Huawei account (`oniro-app auth login`)."
|
|
302
313
|
].join(" ")
|
|
303
314
|
).addOption(
|
|
304
315
|
new Option(
|
|
@@ -315,10 +326,31 @@ function registerSignCommand(program) {
|
|
|
315
326
|
"--acls <list>",
|
|
316
327
|
"Comma-separated permission names to write into the profile's acls.allowed-acls. Required for apps that request permissions above their apl (e.g. a system_basic app requesting ohos.permission.CAPTURE_SCREEN). Example: --acls ohos.permission.REBOOT,ohos.permission.INJECT_INPUT_EVENT"
|
|
317
328
|
).argParser(parseAclsList)
|
|
318
|
-
).option(
|
|
319
|
-
|
|
329
|
+
).option(
|
|
330
|
+
"--harmonyos",
|
|
331
|
+
"Sign a HarmonyOS project through AppGallery Connect. Needs `oniro-app auth login`, and a connected device unless the team already has devices registered."
|
|
332
|
+
).option("--team-id <id>", "With --harmonyos: the AGC team to sign under. Default: the account's own (`oniro-app auth team list`).").option("--product <name>", "With --harmonyos: the product to sign. Default `default`.").option("--force", "With --harmonyos: regenerate the certificate and profile even when they are still valid.").option("--bootstrap", "No-op if signing material is already present; otherwise generate it.").option("--store-password <pwd>", "Keystore store password (default 123456 \u2014 the SDK keystore password).").option("--key-password <pwd>", "Keystore key password (default 123456 \u2014 the SDK keystore password).").action(
|
|
333
|
+
async (projectDir, opts) => {
|
|
320
334
|
const { config, logger } = getRuntime();
|
|
321
335
|
const dir = path3.resolve(projectDir ?? process.cwd());
|
|
336
|
+
if (opts.harmonyos) {
|
|
337
|
+
const result = await harmonyOsAutoSign({
|
|
338
|
+
config,
|
|
339
|
+
session: createHarmonyOsSession({ config, logger }),
|
|
340
|
+
projectDir: dir,
|
|
341
|
+
productName: opts.product,
|
|
342
|
+
teamId: opts.teamId,
|
|
343
|
+
force: opts.force,
|
|
344
|
+
logger
|
|
345
|
+
});
|
|
346
|
+
logger.info(`Signing configs ready for ${result.bundleName} (profile names ${result.deviceIds.length} device(s)).`);
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
if (detectRuntimeOs(dir, opts.product) === "HarmonyOS") {
|
|
350
|
+
throw new OniroError(
|
|
351
|
+
`${dir} targets HarmonyOS, which needs a certificate from AppGallery Connect: run \`oniro-app auth login\` once, then \`oniro-app sign --harmonyos\`.`
|
|
352
|
+
);
|
|
353
|
+
}
|
|
322
354
|
const passwords = opts.storePassword || opts.keyPassword ? { store: opts.storePassword ?? "123456", key: opts.keyPassword ?? "123456" } : void 0;
|
|
323
355
|
if (opts.bootstrap) {
|
|
324
356
|
const result = prepareSigning({
|
|
@@ -349,6 +381,68 @@ function registerSignCommand(program) {
|
|
|
349
381
|
);
|
|
350
382
|
}
|
|
351
383
|
|
|
384
|
+
// src/commands/auth.ts
|
|
385
|
+
import { HUAWEI_SITES, createHarmonyOsSession as createHarmonyOsSession2 } from "@oniroproject/core";
|
|
386
|
+
function session() {
|
|
387
|
+
const { config, logger } = getRuntime();
|
|
388
|
+
return createHarmonyOsSession2({
|
|
389
|
+
config,
|
|
390
|
+
logger,
|
|
391
|
+
onLoginUrl: (url) => process.stderr.write(`Opening the Huawei sign-in page. If no browser opens, visit:
|
|
392
|
+
${url}
|
|
393
|
+
`)
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
function registerAuthCommand(program) {
|
|
397
|
+
const auth = program.command("auth").description(
|
|
398
|
+
"Sign in to a Huawei developer account, which HarmonyOS signing (`oniro-app sign --harmonyos`) needs. OpenHarmony signing needs no account. The token is stored encrypted under ONIRO_HARMONYOS_AUTH_DIR (default ~/.oniro/harmonyos)."
|
|
399
|
+
);
|
|
400
|
+
auth.command("login").description("Sign in through the browser, which redirects back to a loopback port on this machine.").option("--timeout <seconds>", "How long to wait for the browser sign-in. Default 600.", (v) => Number(v)).action(async (opts) => {
|
|
401
|
+
const user = await session().login(opts.timeout ? { timeoutMs: Math.max(1, opts.timeout) * 1e3 } : void 0);
|
|
402
|
+
process.stdout.write(`${user.userName || user.userId}
|
|
403
|
+
`);
|
|
404
|
+
});
|
|
405
|
+
auth.command("logout").description("Sign out and delete the stored token.").action(async () => {
|
|
406
|
+
const signedOut = await session().logout();
|
|
407
|
+
getRuntime().logger.info(signedOut ? "Signed out." : "Not signed in; nothing to do.");
|
|
408
|
+
});
|
|
409
|
+
auth.command("status").description("Show the signed-in account. Exits non-zero when not signed in.").option("--json", "Emit the account details as JSON.").action(async (opts) => {
|
|
410
|
+
const s = session();
|
|
411
|
+
const user = await s.getUserInfo({ refresh: true });
|
|
412
|
+
if (!user) {
|
|
413
|
+
process.stderr.write("Not signed in. Run `oniro-app auth login`.\n");
|
|
414
|
+
process.exitCode = 1;
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
const agreement = user.isRealName ? null : await s.getDeveloperAgreement(user);
|
|
418
|
+
if (opts.json) {
|
|
419
|
+
const { userId, userName, countryCode, siteCode, isRealName } = user;
|
|
420
|
+
const agcBaseUrl = HUAWEI_SITES[siteCode].agcBaseUrl;
|
|
421
|
+
const status = { userId, userName, countryCode, site: siteCode, agcBaseUrl, isRealName, developerAgreement: agreement, tokenPath: s.tokenPath };
|
|
422
|
+
process.stdout.write(`${JSON.stringify(status, null, 2)}
|
|
423
|
+
`);
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
process.stdout.write(`${user.userName || user.userId} (${user.userId}) [${user.siteCode}]
|
|
427
|
+
`);
|
|
428
|
+
if (agreement && !(agreement.signed && agreement.latest)) {
|
|
429
|
+
process.stderr.write(
|
|
430
|
+
"[warn] This account has neither real-name verification nor the current HUAWEI Developer Basic Service Agreement accepted, so AppGallery Connect will not issue signing material. Accept the agreement in AppGallery Connect or DevEco Studio.\n"
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
});
|
|
434
|
+
auth.command("team").description("AGC teams this account belongs to.").command("list").description("List the AGC teams this account belongs to, for `oniro-app sign --harmonyos --team-id <id>`.").option("--json", "Emit the team list as JSON.").action(async (opts) => {
|
|
435
|
+
const teams = await session().listTeams();
|
|
436
|
+
if (opts.json) {
|
|
437
|
+
process.stdout.write(`${JSON.stringify(teams, null, 2)}
|
|
438
|
+
`);
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
for (const t of teams) process.stdout.write(`${t.id} ${t.name}
|
|
442
|
+
`);
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
|
|
352
446
|
// src/commands/app.ts
|
|
353
447
|
import * as path4 from "path";
|
|
354
448
|
import { installApp, launchApp, uninstallApp, forceStop, applyChanges, getBundleName } from "@oniroproject/core";
|
|
@@ -443,7 +537,7 @@ function getBundledTemplateRoot() {
|
|
|
443
537
|
|
|
444
538
|
// src/commands/create.ts
|
|
445
539
|
function registerCreateCommand(program) {
|
|
446
|
-
program.command("create").description("Scaffold a new Oniro/OpenHarmony app from a template. All flags are required (non-interactive).").requiredOption("--name <name>", "Project folder name (letters, digits, ._- only)").requiredOption("--bundle <bundleName>", "Bundle name in reverse-DNS form, e.g. com.example.myapp").requiredOption("--location <dir>", "Parent directory where the new project folder will be created").requiredOption("--sdk <api>", "Target SDK API level (e.g. 18, 20)").option("--template <id>", "Template id", "EmptyAbility").option("--module <name>", "Module folder name (defaults to the template default, usually `entry`)").option("--overwrite", "Replace the destination if it already exists").action(async (opts) => {
|
|
540
|
+
program.command("create").description("Scaffold a new Oniro/OpenHarmony or HarmonyOS app from a template. All flags are required (non-interactive).").requiredOption("--name <name>", "Project folder name (letters, digits, ._- only)").requiredOption("--bundle <bundleName>", "Bundle name in reverse-DNS form, e.g. com.example.myapp").requiredOption("--location <dir>", "Parent directory where the new project folder will be created").requiredOption("--sdk <api>", "Target SDK API level (e.g. 18, 20)").option("--template <id>", "Template id", "EmptyAbility").option("--module <name>", "Module folder name (defaults to the template default, usually `entry`)").option("--overwrite", "Replace the destination if it already exists").action(async (opts) => {
|
|
447
541
|
const { config, logger } = getRuntime();
|
|
448
542
|
if (!isValidProjectName(opts.name)) {
|
|
449
543
|
throw new Error(`Invalid --name '${opts.name}'. Use letters/numbers/._- and no slashes.`);
|
|
@@ -901,7 +995,7 @@ function registerInputCommand(program) {
|
|
|
901
995
|
}
|
|
902
996
|
|
|
903
997
|
// src/bin/oniro-app.ts
|
|
904
|
-
var CLI_VERSION = "0.
|
|
998
|
+
var CLI_VERSION = "0.11.0";
|
|
905
999
|
function buildProgram() {
|
|
906
1000
|
const program = new Command4().name("oniro-app").description(
|
|
907
1001
|
"Cross-platform CLI for Oniro/OpenHarmony app development.\n\nDesigned for non-interactive use (CI, scripts, agents): every command\ntakes explicit flags, results go to stdout, progress/logs go to stderr,\nand a non-zero exit code indicates failure."
|
|
@@ -911,6 +1005,7 @@ function buildProgram() {
|
|
|
911
1005
|
registerEmulatorCommand(program);
|
|
912
1006
|
registerBuildCommand(program);
|
|
913
1007
|
registerSignCommand(program);
|
|
1008
|
+
registerAuthCommand(program);
|
|
914
1009
|
registerAppCommand(program);
|
|
915
1010
|
registerCreateCommand(program);
|
|
916
1011
|
registerTemplatesCommand(program);
|
|
@@ -930,7 +1025,7 @@ async function main() {
|
|
|
930
1025
|
try {
|
|
931
1026
|
await program.parseAsync(process.argv);
|
|
932
1027
|
} catch (err) {
|
|
933
|
-
const message = err instanceof
|
|
1028
|
+
const message = err instanceof OniroError2 ? err.message : err instanceof Error ? err.message : String(err);
|
|
934
1029
|
process.stderr.write(`[error] ${message}
|
|
935
1030
|
`);
|
|
936
1031
|
if (process.env.ONIRO_DEBUG === "1" && err instanceof Error && err.stack) {
|