Compare commits

...

34 Commits
v21.1.3 ... esm

Author SHA1 Message Date
d7bf5095c7 wip 2025-05-18 20:33:16 -03:00
eecfc4e933 Build standalone without pkg
Change-type: major
2025-05-16 17:16:02 -03:00
31ddacec4c v21.1.12 2025-05-16 18:54:51 +00:00
dad26328b9 Merge pull request #2935 from balena-io/fix-build-secrets-serialization
Fix build secrets serialization
2025-05-16 14:54:04 -04:00
98197eef47 Dedupe dependencies 2025-05-15 19:13:36 -04:00
0f8ce47ec6 Update @balena/compose dependency to fix error with build secrets.
See https://github.com/balena-io-modules/balena-compose/pull/79

Change-type: patch
Signed-off-by: Ken Bannister <kb2ma@runbox.com>
2025-05-15 19:03:04 -04:00
33d3be326a v21.1.11 2025-05-06 15:25:00 +00:00
3eb397de1b Merge pull request #2611 from balena-io/lmb/fix-typos
Fix typos in the help messages
2025-05-06 15:24:01 +00:00
457b81a597 Deduplicate dependencies 2025-05-06 10:57:39 -04:00
8eb1777437 Fix typos in os configure and config generate help messages
Change-type: patch
2025-05-06 09:08:01 -04:00
bbc08dcfc5 v21.1.10 2025-05-05 17:13:26 +00:00
48cee061f4 Merge pull request #2937 from balena-io/fix-windows-signing
patch: fix windows signing
2025-05-05 17:12:40 +00:00
37e96e5d67 patch: fix windows signing 2025-05-05 13:38:05 -03:00
a5c865b7f9 v21.1.9 2025-04-07 12:53:22 +00:00
3fb3dd5819 Merge pull request #2929 from balena-io/update-balena-config-json
Update balena-config-json to rely on the balena-image-fs helpers
2025-04-07 15:52:21 +03:00
daf5c518fb Deduplicate dependencies 2025-04-04 10:38:24 +03:00
4fcedd0607 Update balena-config-json to rely on the balena-image-fs helpers
Update balena-config-json from 4.2.2 to 4.2.7
Update balena-image-fs from 7.5.0 to 7.5.2

Change-type: patch
2025-04-04 10:23:39 +03:00
42d9cbb48d v21.1.8 2025-04-03 16:10:05 +00:00
408efa91c1 Merge pull request #2933 from balena-io/renovate/actions-download-artifact-4.1.x
Update actions/download-artifact action to v4.1.9
2025-04-03 16:09:08 +00:00
a2209ffe56 Update actions/download-artifact action to v4.1.9
Update actions/download-artifact from 4.1.8 to 4.1.9

Change-type: patch
2025-04-03 15:50:05 +00:00
3f27db811b v21.1.7 2025-04-03 15:12:16 +00:00
839a3050fb Merge pull request #2932 from balena-io/renovate/actions-upload-artifact-digest
Update actions/upload-artifact digest to ea165f8
2025-04-03 15:11:18 +00:00
c8ea9cfcdb Update actions/upload-artifact digest to ea165f8
Update actions/upload-artifact

Change-type: patch
2025-04-03 14:50:26 +00:00
776115ef5d v21.1.6 2025-04-03 14:12:08 +00:00
f031ec1dea Merge pull request #2931 from balena-io/renovate/actions-setup-node-digest
Update actions/setup-node digest to cdca736
2025-04-03 14:11:10 +00:00
fe42438090 Update actions/setup-node digest to cdca736
Update actions/setup-node

Change-type: patch
2025-04-03 13:50:06 +00:00
b616fbdd79 v21.1.5 2025-04-03 13:28:12 +00:00
81edfbbae1 Merge pull request #2930 from balena-io/bump_dockerode_cachefrom
Update dockerode/docker-modem dependencies for cachefrom fix
2025-04-03 09:27:11 -04:00
663e83c3b8 Dedupe dependencies 2025-04-02 18:50:31 -04:00
b650f8ff6d Update dockerode/docker-modem dependencies for fixes
Change-type: patch
Signed-off-by: Ken Bannister <kb2ma@runbox.com>
2025-04-02 18:47:43 -04:00
58234f17e1 v21.1.4 2025-04-02 09:16:30 +00:00
77905f4a74 Merge pull request #2928 from balena-io/comment_sig_file
Add comment with example of signature file in a flasher image
2025-04-02 09:15:23 +00:00
30076fabe6 Dedupe dependencies 2025-04-01 18:25:20 -04:00
28703bb5ae Add comment with secure boot signature file example for preload
Change-type: patch
Signed-off-by: Ken Bannister <kb2ma@runbox.com>
2025-04-01 18:25:16 -04:00
196 changed files with 1465 additions and 4284 deletions

View File

@ -67,7 +67,7 @@ fixed it.
- **Cloud backend: openBalena or balenaCloud?** If unsure, it will be balenaCloud
- **Operating system version:** e.g. Windows 10, Ubuntu 18.04, macOS 10.14.5
- **32/64 bit OS and processor:** e.g. 32-bit Windows on 64-bit Intel processor
- **Install method:** npm or zip package or executable installer
- **Install method:** npm or standalone package or executable installer
- **If npm install, Node.js and npm version:** e.g. Node v8.16.0 and npm v6.4.1
# Additional References

View File

@ -28,7 +28,7 @@ runs:
using: 'composite'
steps:
- name: Download custom source artifact
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4.1.9
with:
name: custom-${{ github.event.pull_request.head.sha || github.event.head_commit.id }}-${{ runner.os }}-${{ runner.arch }}
path: ${{ runner.temp }}
@ -39,7 +39,7 @@ runs:
run: tar -xf ${{ runner.temp }}/custom.tgz
- name: Setup Node.js
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
with:
node-version: ${{ inputs.NODE_VERSION }}
cache: npm
@ -48,7 +48,7 @@ runs:
if: runner.os == 'macOS'
uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # v4
with:
python-version: "3.11"
python-version: '3.11'
- name: Install additional tools
if: runner.os == 'Windows'
@ -112,8 +112,8 @@ runs:
PATH="/c/Program Files/DigiCert/DigiCert One Signing Manager Tools:${PATH}"
smksp_registrar.exe list
smctl.exe keypair ls
smctl.exe windows certsync
/c/Windows/System32/certutil.exe -csp "DigiCert Signing Manager KSP" -key -user
smksp_cert_sync.exe
# (signtool.exe) https://github.com/actions/runner-images/blob/main/images/win/Windows2019-Readme.md#installed-windows-sdks
PATH="/c/Program Files (x86)/Windows Kits/10/bin/${runner_arch}:${PATH}"
@ -135,9 +135,11 @@ runs:
XCODE_APP_LOADER_TEAM_ID: ${{ inputs.XCODE_APP_LOADER_TEAM_ID }}
- name: Upload artifacts
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: gh-release-${{ github.event.pull_request.head.sha || github.event.head_commit.id }}-${{ strategy.job-index }}
path: dist
path: |
dist
!dist/balena
retention-days: 1
if-no-files-found: error

View File

@ -26,7 +26,7 @@ runs:
steps:
# https://github.com/actions/setup-node#caching-global-packages-data
- name: Setup Node.js
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
with:
node-version: ${{ inputs.NODE_VERSION }}
cache: npm
@ -58,7 +58,7 @@ runs:
run: tar --exclude-vcs -acf ${{ runner.temp }}/custom.tgz .
- name: Upload custom artifact
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: custom-${{ github.event.pull_request.head.sha || github.event.head_commit.id }}-${{ runner.os }}-${{ runner.arch }}
path: ${{ runner.temp }}/custom.tgz

View File

@ -2,7 +2,7 @@ module.exports = {
reporter: 'spec',
require: 'ts-node/register/transpile-only',
file: './tests/config-tests',
timeout: 12000,
timeout: 48000,
// To test only, say, 'push.spec.ts', do it as follows so that
// requests are authenticated:
// spec: ['tests/auth/*.spec.ts', 'tests/**/deploy.spec.ts'],

View File

@ -1,3 +1,279 @@
- commits:
- subject: Update @balena/compose dependency to fix error with build secrets.
hash: 0f8ce47ec6523e447315bc9103267371fd028bf4
body: |
See https://github.com/balena-io-modules/balena-compose/pull/79
footer:
Change-type: patch
change-type: patch
Signed-off-by: Ken Bannister <kb2ma@runbox.com>
signed-off-by: Ken Bannister <kb2ma@runbox.com>
author: Ken Bannister
nested: []
version: 21.1.12
title: ""
date: 2025-05-16T18:54:49.177Z
- commits:
- subject: Fix typos in `os configure` and `config generate` help messages
hash: 8eb1777437aa4c34c437ebbf81c2cf0dee0cc460
body: ""
footer:
Change-type: patch
change-type: patch
author: myarmolinsky
nested: []
version: 21.1.11
title: ""
date: 2025-05-06T15:24:58.111Z
- commits:
- subject: "patch: fix windows signing"
hash: 37e96e5d670d466910ad7164d5b26faf1ef41df7
body: ""
footer: {}
author: Edwin Joassart
nested: []
version: 21.1.10
title: ""
date: 2025-05-05T17:13:23.657Z
- commits:
- subject: Update balena-config-json to rely on the balena-image-fs helpers
hash: 4fcedd0607624ddbd26917e3be5fcbd39d96d2f6
body: |
Update balena-config-json from 4.2.2 to 4.2.7
Update balena-image-fs from 7.5.0 to 7.5.2
footer:
Change-type: patch
change-type: patch
author: Thodoris Greasidis
nested:
- commits:
- subject: Fix getBootPartition always warning that the boot partitions were not
found
hash: d91290d9c4b502652c50a34482ff68448eb0a4c2
body: ""
footer:
Change-type: patch
change-type: patch
author: Thodoris Greasidis
nested: []
version: balena-config-json-4.2.7
title: ""
date: 2025-04-02T14:14:31.495Z
- commits:
- subject: "write: Allow undefined as a value for the deprecated type parameter"
hash: 9d5a44175e7f46f2f3963d794d48d3de8f49300f
body: ""
footer:
Change-type: patch
change-type: patch
author: Thodoris Greasidis
nested: []
- subject: Use the balena-image-fs findPartition() helper to find the boot
partition
hash: 49282ed9bd121d89c8d6fee5095917876cd6f501
body: |
Update balena-image-fs from 7.4.0 to 7.5.0
footer:
Change-type: patch
change-type: patch
author: Thodoris Greasidis
nested:
- commits:
- subject: Add function to find a partition by name/label
hash: 4e9b1cfb2739b738dd12bda7d1623e08ad208b46
body: ""
footer:
Change-type: minor
change-type: minor
Signed-off-by: Ken Bannister <kb2ma@runbox.com>
signed-off-by: Ken Bannister <kb2ma@runbox.com>
author: Ken Bannister
nested: []
version: balena-image-fs-7.5.0
title: ""
date: 2025-03-26T12:35:30.365Z
- commits:
- subject: bump ext2fs to 4.2.4
hash: 300cc6d5cdd12ce0c47986efe98702511a03f4a5
body: ""
footer:
Change-type: patch
change-type: patch
Signed-off-by: Ryan Cooke<ryan@balena.io>
signed-off-by: Ryan Cooke<ryan@balena.io>
author: Ryan Cooke
nested: []
version: balena-image-fs-7.4.1
title: ""
date: 2025-02-21T10:21:04.380Z
version: balena-config-json-4.2.6
title: ""
date: 2025-04-01T01:09:16.169Z
- commits:
- subject: Update @balena/lint to 9.1.4
hash: 0ff1aa1ed8803b622948214493e1f9ec88cfe910
body: |
Update @balena/lint from 6.2.2 to 9.1.4
footer:
Change-type: patch
change-type: patch
author: Thodoris Greasidis
nested: []
version: balena-config-json-4.2.5
title: ""
date: 2025-03-26T11:41:52.400Z
- commits:
- subject: Switch use ts-mocha instead of manually compiling the tests
hash: c6e46d393d8670781cf9f94512e8ef05a4236111
body: ""
footer:
Change-type: patch
change-type: patch
author: Thodoris Greasidis
nested: []
- subject: Update TypeScript to 5.8.2
hash: b8a8183bc14c24a63f5bc5dd60d8906f6d97a00d
body: ""
footer:
Change-type: patch
change-type: patch
author: Thodoris Greasidis
nested: []
version: balena-config-json-4.2.4
title: ""
date: 2025-03-26T09:09:13.516Z
- commits:
- subject: Update chai to v5
hash: 7fe83ffc781eb66ac3535749f7fdf56d458eb959
body: |
Update @types/chai from 4.3.20 to 5.2.0
footer:
Change-type: patch
change-type: patch
author: balena-renovate[bot]
nested: []
version: balena-config-json-4.2.3
title: ""
date: 2025-03-26T08:40:58.555Z
- commits:
- subject: Update dependency jsdoc-to-markdown to v9
hash: f22a0a1dae022035e5357c147f681f8b7c703fe3
body: |
Update jsdoc-to-markdown from 8.0.3 to 9.1.1
footer:
Change-type: patch
change-type: patch
author: balena-renovate[bot]
nested: []
version: balena-image-fs-7.5.2
title: ""
date: 2025-04-02T10:40:31.219Z
- commits:
- subject: Update @balena/lint to v9
hash: 4da5fa44a43047cdb4f96c37a73a0f0674c9327b
body: ""
footer:
Change-type: patch
change-type: patch
author: Thodoris Greasidis
nested: []
- subject: Remove the no longer needed gpt detection helper
hash: 0973da43aa321e4e2dad4b83c5beb965b8da7044
body: ""
footer:
Change-type: patch
change-type: patch
author: Thodoris Greasidis
nested: []
- subject: Update TypeScript to 5.8.2
hash: 1580e7d577e0183c2b5d4f9ce3d0b8f519e4dff3
body: ""
footer:
Change-type: patch
change-type: patch
author: Thodoris Greasidis
nested: []
- subject: Drop the package-lock.json
hash: 400ba55caa4c4af8098e2b164cd184651c283230
body: ""
footer:
Change-type: patch
change-type: patch
author: Thodoris Greasidis
nested: []
version: balena-image-fs-7.5.1
title: ""
date: 2025-03-26T17:51:35.381Z
version: 21.1.9
title: ""
date: 2025-04-07T12:53:16.860Z
- commits:
- subject: Update actions/download-artifact action to v4.1.9
hash: a2209ffe5677388faf7b9bbccace5343265df51f
body: |
Update actions/download-artifact from 4.1.8 to 4.1.9
footer:
Change-type: patch
change-type: patch
author: balena-renovate[bot]
nested: []
version: 21.1.8
title: ""
date: 2025-04-03T16:10:02.341Z
- commits:
- subject: Update actions/upload-artifact digest to ea165f8
hash: c8ea9cfcdbaa9a8abf221132a7d1ff29a966e515
body: |
Update actions/upload-artifact
footer:
Change-type: patch
change-type: patch
author: balena-renovate[bot]
nested: []
version: 21.1.7
title: ""
date: 2025-04-03T15:12:14.222Z
- commits:
- subject: Update actions/setup-node digest to cdca736
hash: fe4243809033735a6439f39a1a33dfd00039d656
body: |
Update actions/setup-node
footer:
Change-type: patch
change-type: patch
author: balena-renovate[bot]
nested: []
version: 21.1.6
title: ""
date: 2025-04-03T14:12:06.042Z
- commits:
- subject: Update dockerode/docker-modem dependencies for fixes
hash: b650f8ff6d01d2144886253f93aa1d1867f51980
body: ""
footer:
Change-type: patch
change-type: patch
Signed-off-by: Ken Bannister <kb2ma@runbox.com>
signed-off-by: Ken Bannister <kb2ma@runbox.com>
author: Ken Bannister
nested: []
version: 21.1.5
title: ""
date: 2025-04-03T13:28:08.855Z
- commits:
- subject: Add comment with secure boot signature file example for preload
hash: 28703bb5ae13539ab4c1c597e6a53a5292a7edde
body: ""
footer:
Change-type: patch
change-type: patch
Signed-off-by: Ken Bannister <kb2ma@runbox.com>
signed-off-by: Ken Bannister <kb2ma@runbox.com>
author: Ken Bannister
nested: []
version: 21.1.4
title: ""
date: 2025-04-02T09:16:27.791Z
- commits:
- subject: Fix device detail for open balena
hash: 0d4e411777dd53d83c475da3653ab94176e07d7d
@ -18419,7 +18695,7 @@
change-type: patch
author: Paulo Castro
nested: []
- subject: Refactor dependency import in utils/helpers.ts for performance
- subject: Refactor dependency import in utils/helpers.js.ts for performance
hash: 06f76838370fae7a2e9faf99d1698c9bf75d0d15
body: ""
footer:
@ -25899,7 +26175,7 @@
version: 11.31.18
date: 2020-04-24T20:37:38.920Z
- commits:
- subject: Convert lib/utils/docker-coffee.coffee to javascript
- subject: Convert lib/utils/docker.js-coffee.coffee to javascript
hash: 23f2242e22a09c559bcb8b62ce4e8f5c8ad6e1db
body: ""
footer:

View File

@ -4,6 +4,94 @@ All notable changes to this project will be documented in this file
automatically by Versionist. DO NOT EDIT THIS FILE MANUALLY!
This project adheres to [Semantic Versioning](http://semver.org/).
## 21.1.12 - 2025-05-16
* Update @balena/compose dependency to fix error with build secrets. [Ken Bannister]
## 21.1.11 - 2025-05-06
* Fix typos in `os configure` and `config generate` help messages [myarmolinsky]
## 21.1.10 - 2025-05-05
* patch: fix windows signing [Edwin Joassart]
## 21.1.9 - 2025-04-07
<details>
<summary> Update balena-config-json to rely on the balena-image-fs helpers [Thodoris Greasidis] </summary>
> ### balena-config-json-4.2.7 - 2025-04-02
>
> * Fix getBootPartition always warning that the boot partitions were not found [Thodoris Greasidis]
>
> ### balena-config-json-4.2.6 - 2025-04-01
>
> * write: Allow undefined as a value for the deprecated type parameter [Thodoris Greasidis]
>
> <details>
> <summary> Use the balena-image-fs findPartition() helper to find the boot partition [Thodoris Greasidis] </summary>
>
>> #### balena-image-fs-7.5.0 - 2025-03-26
>>
>> * Add function to find a partition by name/label [Ken Bannister]
>>
>> #### balena-image-fs-7.4.1 - 2025-02-21
>>
>> * bump ext2fs to 4.2.4 [Ryan Cooke]
>>
>
> </details>
>
>
> ### balena-config-json-4.2.5 - 2025-03-26
>
> * Update @balena/lint to 9.1.4 [Thodoris Greasidis]
>
> ### balena-config-json-4.2.4 - 2025-03-26
>
> * Switch use ts-mocha instead of manually compiling the tests [Thodoris Greasidis]
> * Update TypeScript to 5.8.2 [Thodoris Greasidis]
>
> ### balena-config-json-4.2.3 - 2025-03-26
>
> * Update chai to v5 [balena-renovate[bot]]
>
> ### balena-image-fs-7.5.2 - 2025-04-02
>
> * Update dependency jsdoc-to-markdown to v9 [balena-renovate[bot]]
>
> ### balena-image-fs-7.5.1 - 2025-03-26
>
> * Update @balena/lint to v9 [Thodoris Greasidis]
> * Remove the no longer needed gpt detection helper [Thodoris Greasidis]
> * Update TypeScript to 5.8.2 [Thodoris Greasidis]
> * Drop the package-lock.json [Thodoris Greasidis]
>
</details>
## 21.1.8 - 2025-04-03
* Update actions/download-artifact action to v4.1.9 [balena-renovate[bot]]
## 21.1.7 - 2025-04-03
* Update actions/upload-artifact digest to ea165f8 [balena-renovate[bot]]
## 21.1.6 - 2025-04-03
* Update actions/setup-node digest to cdca736 [balena-renovate[bot]]
## 21.1.5 - 2025-04-03
* Update dockerode/docker-modem dependencies for fixes [Ken Bannister]
## 21.1.4 - 2025-04-02
* Add comment with secure boot signature file example for preload [Ken Bannister]
## 21.1.3 - 2025-03-28
* Fix device detail for open balena [Otavio Jacobi]
@ -4963,7 +5051,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## 12.44.9 - 2021-04-13
* config inject/read/write: Fix umount errors with OS image files [Paulo Castro]
* Refactor dependency import in utils/helpers.ts for performance [Paulo Castro]
* Refactor dependency import in utils/helpers.js.ts for performance [Paulo Castro]
## 12.44.8 - 2021-04-09
@ -7078,7 +7166,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## 11.31.17 - 2020-04-24
* Convert lib/utils/docker-coffee.coffee to javascript [Pagan Gazzard]
* Convert lib/utils/docker.js-coffee.coffee to javascript [Pagan Gazzard]
## 11.31.16 - 2020-04-24

View File

@ -14,7 +14,7 @@ The balena CLI is an open source project and your contribution is welcome!
In order to ease development:
* `npm run build:fast` skips some of the build steps for interactive testing, or
* `npm run test:source` skips testing the standalone zip packages (which is rather slow)
* `npm run test:source` skips testing the standalone packages (which is rather slow)
* `./bin/balena-dev` uses `ts-node/register` to transpile on the fly.
Before opening a PR, test your changes with `npm test`. Keep compatibility in mind, as the CLI is

View File

@ -8,8 +8,8 @@ There are 3 options to choose from to install balena's CLI:
* [Executable Installer](#executable-installer): the easiest method on Windows and macOS, using the
traditional graphical desktop application installers.
* [Standalone Zip Package](#standalone-zip-package): these are plain zip files with the balena CLI
executable in them: extract and run. Available for all platforms: Linux, Windows, macOS.
* [Standalone tar.gz Package](#standalone-targz-package): these are plain tar.gz files with the balena CLI
bundled within. Available for all platforms: Linux, Windows, macOS.
Recommended also for scripted installation in CI (continuous integration) environments.
* [NPM Installation](#npm-installation): recommended for Node.js developers who may be interested
in integrating the balena CLI in their existing projects or workflow.
@ -30,9 +30,9 @@ instructions:
> If you would like to use WSL, follow the [installations instructions for
> Linux](./INSTALL-LINUX.md) rather than Windows, as WSL consists of a Linux environment.
If you had previously installed the CLI using a standalone zip package, it may be a good idea to
If you had previously installed the CLI using a standalone tar package, it may be a good idea to
check your system's `PATH` environment variable for duplicate entries, as the terminal will use the
entry that comes first. Check the [Standalone Zip Package](#standalone-zip-package) instructions
entry that comes first. Check the [Standalone tar.gz Package](#standalone-targz-package) instructions
for how to modify the PATH variable.
By default, the CLI is installed to the following folders:
@ -42,18 +42,17 @@ OS | Folders
Windows: | `C:\Program Files\balena-cli\`
macOS: | `/usr/local/src/balena-cli/` <br> `/usr/local/bin/balena`
## Standalone Zip Package
## Standalone tar.gz Package
1. Download the latest zip file from the [releases page](https://github.com/balena-io/balena-cli/releases).
1. Download the latest tar.gz file from the [releases page](https://github.com/balena-io/balena-cli/releases).
Look for a file name that ends with the word "standalone", for example:
`balena-cli-vX.Y.Z-linux-x64-standalone.zip`_also for the Windows Subsystem for Linux_
`balena-cli-vX.Y.Z-macOS-x64-standalone.zip`
`balena-cli-vX.Y.Z-windows-x64-standalone.zip`
`balena-cli-vX.Y.Z-linux-x64-standalone.tar.gz`_also for the Windows Subsystem for Linux_
`balena-cli-vX.Y.Z-macOS-x64-standalone.tar.gz`
`balena-cli-vX.Y.Z-windows-x64-standalone.tar.gz`
2. Extract the zip file contents to any folder you choose. The extracted contents will include a
`balena-cli` folder.
2. Extract the tar.gz file contents to any folder you choose. The extracted contents will be a `balena` folder containing a `bin` subdirectory.
3. Add the `balena-cli` folder to the system's `PATH` environment variable.
3. Add the `balena/bin` folder to the system's `PATH` environment variable.
See instructions for:
[Linux](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix) |
[macOS](https://www.architectryan.com/2012/10/02/add-to-the-path-on-mac-os-x-mountain-lion/#.Uydjga1dXDg) |
@ -61,14 +60,14 @@ macOS: | `/usr/local/src/balena-cli/` <br> `/usr/local/bin/balena`
> * If you are using macOS 10.15 or later (Catalina, Big Sur), [check this known issue and
> workaround](https://github.com/balena-io/balena-cli/issues/2244).
> * **Linux Alpine** and **Busybox:** the standalone zip package is not currently compatible with
> * **Linux Alpine** and **Busybox:** the standalone tar.gz package is not currently compatible with
> these "compact" Linux distributions, because of the alternative C libraries they ship with.
> For these, consider the [NPM Installation](#npm-installation) option.
> * Note that moving the `balena` executable out of the extracted `balena-cli` folder on its own
> * Note that moving the `balena/bin/balena` executable out of the extracted `balena` folder on its own
> (e.g. moving it to `/usr/local/bin/balena`) will **not** work, as it depends on the other
> folders and files also present in the `balena-cli` folder.
> folders and files also present in the `balena` folder.
To update the CLI to a new version, download a new release zip file and replace the previous
To update the CLI to a new version, download a new release tar.gz file and replace the previous
installation folder. To uninstall, simply delete the folder and edit the PATH environment variable
as described above.

View File

@ -8,15 +8,15 @@ method.
Selected operating system: **Linux**
1. Download the latest zip file from the [latest release
1. Download the latest tar.gz file from the [latest release
page](https://github.com/balena-io/balena-cli/releases/latest). Look for a file name that ends
with "-standalone.zip", for example:
`balena-cli-vX.Y.Z-linux-x64-standalone.zip`
with "-standalone.tar.gz", for example:
`balena-cli-vX.Y.Z-linux-x64-standalone.tar.gz`
2. Extract the zip file contents to any folder you choose, for example `/home/james`.
The extracted contents will include a `balena-cli` folder.
2. Extract the tar.gz file contents to any folder you choose, for example `/home/james`.
The extracted contents will include a `balena/bin` folder.
3. Add that folder (e.g. `/home/james/balena-cli`) to the `PATH` environment variable.
3. Add that folder (e.g. `/home/james/balena/bin`) to the `PATH` environment variable.
Check this [StackOverflow
post](https://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux-unix)
for instructions. Close and reopen the terminal window so that the changes to `PATH`
@ -27,7 +27,7 @@ Selected operating system: **Linux**
* `balena version` - should print the CLI's version
* `balena help` - should print a list of available commands
To update the balena CLI to a new version, download a new release zip file and replace the previous
To update the balena CLI to a new version, download a new release tar.gz file and replace the previous
installation folder. To uninstall, simply delete the folder and edit the PATH environment variable
as described above.

View File

@ -7,8 +7,8 @@ Selected operating system: **macOS**
1. Download the installer from the [latest release
page](https://github.com/balena-io/balena-cli/releases/latest).
Look for a file name that ends with "-installer.pkg":
`balena-cli-vX.Y.Z-macOS-x64-installer.pkg`
Look for a file name that ends with "-installer.pkg":
`balena-cli-vX.Y.Z-macOS-x64-installer.pkg`
2. Double click on the downloaded file to run the installer and follow the installer's
instructions.

View File

@ -8,7 +8,7 @@ Selected operating system: **Windows**
1. Download the installer from the [latest release
page](https://github.com/balena-io/balena-cli/releases/latest).
Look for a file name that ends with "-installer.exe":
`balena-cli-vX.Y.Z-windows-x64-installer.exe`
`balena-cli-vX.Y.Z-windows-x64-installer.exe`
2. Double click on the downloaded file to run the installer and follow the installer's
instructions.

View File

@ -115,7 +115,7 @@ If nothing seems to help, consider also using a different client-side terminal a
## "Docker seems to be unavailable" error when using Windows Subsystem for Linux (WSL)
When running on WSL, the recommendation is to install a CLI release for Linux, like the standalone
zip package for Linux. However, commands like "balena build" will, by default, attempt to reach the
tar.gz package for Linux. However, commands like "balena build" will, by default, attempt to reach the
Docker daemon at the Unix socket path `/var/run/docker.sock`, while Docker Desktop for Windows uses
a Windows named pipe at `//./pipe/docker_engine` (which the Linux CLI on WSL cannot use). A
solution is:

View File

@ -15,29 +15,17 @@
* limitations under the License.
*/
import type { JsonVersions } from '../src/commands/version/index';
import { run as oclifRun } from '@oclif/core';
import * as archiver from 'archiver';
import { exec, execFile } from 'child_process';
import * as filehound from 'filehound';
import type { Stats } from 'fs';
import * as fs from 'fs-extra';
import * as klaw from 'klaw';
import * as path from 'path';
import * as rimraf from 'rimraf';
import * as semver from 'semver';
import { promisify } from 'util';
import { notarize } from '@electron/notarize';
import { stripIndent } from '../build/utils/lazy';
import {
diffLines,
loadPackageJson,
ROOT,
StdOutTap,
whichSpawn,
} from './utils';
import { loadPackageJson, ROOT, whichSpawn } from './utils.js';
const execFileAsync = promisify(execFile);
const execAsync = promisify(exec);
@ -55,12 +43,6 @@ interface PathByPlatform {
[platform: string]: string;
}
const standaloneZips: PathByPlatform = {
linux: dPath(`balena-cli-${version}-linux-${arch}-standalone.zip`),
darwin: dPath(`balena-cli-${version}-macOS-${arch}-standalone.zip`),
win32: dPath(`balena-cli-${version}-windows-${arch}-standalone.zip`),
};
const getOclifInstallersOriginalNames = async (): Promise<PathByPlatform> => {
const { stdout } = await execAsync('git rev-parse --short HEAD');
const sha = stdout.trim();
@ -75,260 +57,28 @@ const renamedOclifInstallers: PathByPlatform = {
win32: dPath(`balena-cli-${version}-windows-${arch}-installer.exe`),
};
export const finalReleaseAssets: { [platform: string]: string[] } = {
win32: [standaloneZips['win32'], renamedOclifInstallers['win32']],
darwin: [standaloneZips['darwin'], renamedOclifInstallers['darwin']],
linux: [standaloneZips['linux']],
const getOclifStandaloneOriginalNames = async (): Promise<PathByPlatform> => {
const { stdout } = await execAsync('git rev-parse --short HEAD');
const sha = stdout.trim();
return {
linux: dPath(`balena-${version}-${sha}-linux-${arch}.tar.gz`),
darwin: dPath(`balena-${version}-${sha}-darwin-${arch}.tar.gz`),
win32: dPath(`balena-${version}-${sha}-win32-${arch}.tar.gz`),
};
};
/**
* Given the output of `pkg` as a string (containing warning messages),
* diff it against previously saved output of known "safe" warnings.
* Throw an error if the diff is not empty.
*/
async function diffPkgOutput(pkgOut: string) {
const { monochrome } = await import('../tests/helpers');
const relSavedPath = path.join(
'tests',
'test-data',
'pkg',
`expected-warnings-${process.platform}-${arch}.txt`,
);
const absSavedPath = path.join(ROOT, relSavedPath);
const ignoreStartsWith = [
'> pkg@',
'> Fetching base Node.js binaries',
' fetched-',
'prebuild-install WARN install No prebuilt binaries found',
];
const modulesRE =
process.platform === 'win32'
? /(?<=[ '])([A-Z]:)?\\.+?\\node_modules(?=\\)/
: /(?<=[ '])\/.+?\/node_modules(?=\/)/;
const buildRE =
process.platform === 'win32'
? /(?<=[ '])([A-Z]:)?\\.+\\build(?=\\)/
: /(?<=[ '])\/.+\/build(?=\/)/;
const cleanLines = (chunks: string | string[]) => {
const lines = typeof chunks === 'string' ? chunks.split('\n') : chunks;
return lines
.map((line: string) => monochrome(line)) // remove ASCII colors
.filter((line: string) => !/^\s*$/.test(line)) // blank lines
.filter((line: string) =>
ignoreStartsWith.every((i) => !line.startsWith(i)),
)
.map((line: string) => {
// replace absolute paths with relative paths
let replaced = line.replace(modulesRE, 'node_modules');
if (replaced === line) {
replaced = line.replace(buildRE, 'build');
}
return replaced;
});
};
pkgOut = cleanLines(pkgOut).join('\n');
const { readFile } = (await import('fs')).promises;
const expectedOut = cleanLines(await readFile(absSavedPath, 'utf8')).join(
'\n',
);
if (expectedOut !== pkgOut) {
const sep =
'================================================================================';
const diff = diffLines(expectedOut, pkgOut);
const msg = `pkg output does not match expected output from "${relSavedPath}"
Diff:
${sep}
${diff}
${sep}
Check whether the new or changed pkg warnings are safe to ignore, then update
"${relSavedPath}"
and share the result of your investigation as comments on the pull request.
Hint: the fix is often a matter of updating the 'pkg.scripts' or 'pkg.assets'
sections in the CLI's 'package.json' file, or a matter of updating the
'buildPkg' function in 'automation/build-bin.ts'. Sometimes it requires
patching dependencies: See for example 'patches/all/open+7.0.2.patch'.
${sep}
`;
throw new Error(msg);
}
}
/**
* Call `pkg.exec` to generate the standalone zip file, capturing its warning
* messages (stdout and stderr) in order to call diffPkgOutput().
*/
async function execPkg(...args: any[]) {
const { exec: pkgExec } = await import('@yao-pkg/pkg');
const outTap = new StdOutTap(true);
try {
outTap.tap();
await (pkgExec as any)(...args);
} catch (err) {
outTap.untap();
console.log(outTap.stdoutBuf.join(''));
console.error(outTap.stderrBuf.join(''));
throw err;
}
outTap.untap();
await diffPkgOutput(outTap.allBuf.join(''));
}
/**
* Use the 'pkg' module to create a single large executable file with
* the contents of 'node_modules' and the CLI's javascript code.
* Also copy a number of native modules (binary '.node' files) that are
* compiled during 'npm install' to the 'build-bin' folder, alongside
* the single large executable file created by pkg. (This is necessary
* because of a pkg limitation that does not allow binary executables
* to be directly executed from inside another binary executable.)
*/
async function buildPkg() {
// https://github.com/vercel/pkg#targets
let targets = `linux-${arch}`;
if (process.platform === 'darwin') {
targets = `macos-${arch}`;
}
// TBC: not yet possible to build for Windows arm64 on x64 nodes
if (process.platform === 'win32') {
targets = `win-x64`;
}
const args = [
'--targets',
targets,
'--output',
'build-bin/balena',
'package.json',
];
console.log('=======================================================');
console.log(`execPkg ${args.join(' ')}`);
console.log(`cwd="${process.cwd()}" ROOT="${ROOT}"`);
console.log('=======================================================');
await execPkg(args);
const paths: Array<[string, string[], string[]]> = [
// [platform, [source path], [destination path]]
['*', ['open', 'xdg-open'], ['xdg-open']],
['darwin', ['denymount', 'bin', 'denymount'], ['denymount']],
];
await Promise.all(
paths.map(([platform, source, dest]) => {
if (platform === '*' || platform === process.platform) {
// eg copy from node_modules/open/xdg-open to build-bin/xdg-open
return fs.copy(
path.join(ROOT, 'node_modules', ...source),
path.join(ROOT, 'build-bin', ...dest),
);
}
}),
);
const nativeExtensionPaths: string[] = await filehound
.create()
.paths(path.join(ROOT, 'node_modules'))
.ext(['node', 'dll'])
.find();
console.log(`\nCopying to build-bin:\n${nativeExtensionPaths.join('\n')}`);
await Promise.all(
nativeExtensionPaths.map((extPath) =>
fs.copy(
extPath,
extPath.replace(
path.join(ROOT, 'node_modules'),
path.join(ROOT, 'build-bin'),
),
),
),
);
}
/**
* Run some basic tests on the built pkg executable.
* TODO: test more than just `balena version -j`; integrate with the
* existing mocha/chai CLI command testing.
*/
async function testPkg() {
const pkgBalenaPath = path.join(
ROOT,
'build-bin',
process.platform === 'win32' ? 'balena.exe' : 'balena',
);
console.log(`Testing standalone package "${pkgBalenaPath}"...`);
// Run `balena version -j`, parse its stdout as JSON, and check that the
// reported Node.js major version matches semver.major(process.version)
let { stdout, stderr } = await execFileAsync(pkgBalenaPath, [
'version',
'-j',
]);
const { filterCliOutputForTests } = await import('../tests/helpers');
const filtered = filterCliOutputForTests({
err: stderr.split(/\r?\n/),
out: stdout.split(/\r?\n/),
});
stdout = filtered.out.join('\n');
stderr = filtered.err.join('\n');
let pkgNodeVersion = '';
let pkgNodeMajorVersion = 0;
try {
const balenaVersions: JsonVersions = JSON.parse(stdout);
pkgNodeVersion = balenaVersions['Node.js'];
pkgNodeMajorVersion = semver.major(pkgNodeVersion);
} catch (err) {
throw new Error(stripIndent`
Error parsing JSON output of "balena version -j": ${err}
Original output: "${stdout}"`);
}
if (semver.major(process.version) !== pkgNodeMajorVersion) {
throw new Error(
`Mismatched major version: built-in pkg Node version="${pkgNodeVersion}" vs process.version="${process.version}"`,
);
}
if (filtered.err.length > 0) {
const err = filtered.err.join('\n');
throw new Error(`"${pkgBalenaPath}": non-empty stderr "${err}"`);
}
console.log('Success! (standalone package test successful)');
}
/**
* Create the zip file for the standalone 'pkg' bundle previously created
* by the buildPkg() function in 'build-bin.ts'.
*/
async function zipPkg() {
const outputFile = standaloneZips[process.platform];
if (!outputFile) {
throw new Error(
`Standalone installer unavailable for platform "${process.platform}"`,
);
}
await fs.mkdirp(path.dirname(outputFile));
await new Promise<void>((resolve, reject) => {
console.log(`Zipping standalone package to "${outputFile}"...`);
const archive = archiver('zip', {
zlib: { level: 7 },
});
archive.directory(path.join(ROOT, 'build-bin'), 'balena-cli');
const outputStream = fs.createWriteStream(outputFile);
outputStream.on('close', resolve);
outputStream.on('error', reject);
archive.on('error', reject);
archive.on('warning', console.warn);
archive.pipe(outputStream);
archive.finalize().catch(reject);
});
}
const renamedOclifStandalone: PathByPlatform = {
linux: dPath(`balena-cli-${version}-linux-${arch}-standalone.tar.gz`),
darwin: dPath(`balena-cli-${version}-macOS-${arch}-standalone.tar.gz`),
win32: dPath(`balena-cli-${version}-windows-${arch}-standalone.tar.gz`),
};
export async function signFilesForNotarization() {
console.log('Signing files for notarization');
if (process.platform !== 'darwin') {
// If signFilesForNotarization is called on the test CI environment (which will not set CSC_LINK)
// then we skip the signing process.
if (process.platform !== 'darwin' || !process.env.CSC_LINK) {
console.log('Skipping signing for notarization');
return;
}
console.log('Deleting unneeded zip files...');
@ -416,20 +166,39 @@ export async function signFilesForNotarization() {
]);
}
export async function buildStandaloneZip() {
console.log(`Building standalone zip package for CLI ${version}`);
export async function buildStandalone() {
console.log(`Building standalone tarball for CLI ${version}`);
fs.rmSync('./tmp', { recursive: true, force: true });
fs.rmSync('./dist', { recursive: true, force: true });
fs.mkdirSync('./dist');
try {
await buildPkg();
await testPkg();
await zipPkg();
console.log(`Standalone zip package build completed`);
let packOpts = ['-r', ROOT, '--no-xz'];
if (process.platform === 'darwin') {
packOpts = packOpts.concat('--targets', `darwin-${arch}`);
} else if (process.platform === 'win32') {
packOpts = packOpts.concat('--targets', 'win32-x64');
} else if (process.platform === 'linux') {
packOpts = packOpts.concat('--targets', `linux-${arch}`);
}
console.log(`Building oclif installer for CLI ${version}`);
const packCmd = `pack:tarballs`;
console.log('=======================================================');
console.log(`oclif ${packCmd} ${packOpts.join(' ')}`);
console.log(`cwd="${process.cwd()}" ROOT="${ROOT}"`);
console.log('=======================================================');
const oclifPath = path.join(ROOT, 'node_modules', 'oclif');
await oclifRun([packCmd].concat(...packOpts), oclifPath);
await renameStandalone();
console.log(`Standalone tarball package build completed`);
} catch (error) {
console.error(`Error creating or testing standalone zip package`);
console.error(`Error creating or testing standalone tarball package`);
throw error;
}
}
async function renameInstallerFiles() {
async function renameInstallers() {
const oclifInstallers = await getOclifInstallersOriginalNames();
if (await fs.pathExists(oclifInstallers[process.platform])) {
await fs.rename(
@ -439,6 +208,16 @@ async function renameInstallerFiles() {
}
}
async function renameStandalone() {
const oclifStandalone = await getOclifStandaloneOriginalNames();
if (await fs.pathExists(oclifStandalone[process.platform])) {
await fs.rename(
oclifStandalone[process.platform],
renamedOclifStandalone[process.platform],
);
}
}
/**
* If the CSC_LINK and CSC_KEY_PASSWORD env vars are set, digitally sign the
* executable installer using Microsoft SignTool.exe (Sign Tool)
@ -446,7 +225,7 @@ async function renameInstallerFiles() {
*/
async function signWindowsInstaller() {
if (process.env.SM_CODE_SIGNING_CERT_SHA1_HASH) {
const exeName = renamedOclifInstallers[process.platform];
const exeName = (await getOclifInstallersOriginalNames())[process.platform];
console.log(`Signing installer "${exeName}"`);
// trust ...
await execFileAsync('signtool.exe', [
@ -480,12 +259,14 @@ async function notarizeMacInstaller(): Promise<void> {
const appleId =
process.env.XCODE_APP_LOADER_EMAIL || 'accounts+apple@balena.io';
const appleIdPassword = process.env.XCODE_APP_LOADER_PASSWORD;
const appPath = (await getOclifInstallersOriginalNames())[process.platform];
console.log(`Notarizing file "${appPath}"`);
if (appleIdPassword && teamId) {
await notarize({
tool: 'notarytool',
teamId,
appPath: renamedOclifInstallers.darwin,
appPath,
appleId,
appleIdPassword,
});
@ -525,7 +306,6 @@ export async function buildOclifInstaller() {
console.log('=======================================================');
const oclifPath = path.join(ROOT, 'node_modules', 'oclif');
await oclifRun([packCmd].concat(...packOpts), oclifPath);
await renameInstallerFiles();
// The Windows installer is explicitly signed here (oclif doesn't do it).
// The macOS installer is automatically signed by oclif (which runs the
// `pkgbuild` tool), using the certificate name given in package.json
@ -537,6 +317,7 @@ export async function buildOclifInstaller() {
await notarizeMacInstaller(); // Notarize
console.log('Package notarized.');
}
await renameInstallers();
console.log(`oclif installer build completed`);
}
}
@ -572,4 +353,5 @@ export async function testShrinkwrap(): Promise<void> {
if (process.platform !== 'win32') {
await whichSpawn(path.resolve(__dirname, 'test-lock-deduplicated.sh'));
}
await Promise.resolve();
}

View File

@ -16,7 +16,7 @@
*/
import * as path from 'path';
import { MarkdownFileParser } from './utils';
import { MarkdownFileParser } from './utils.js';
import { GlobSync } from 'glob';
/**

View File

@ -16,7 +16,7 @@
*/
import { Parser } from '@oclif/core';
import * as ent from 'ent';
import * as _ from 'lodash';
import _ from 'lodash';
import { capitanoizeOclifUsage } from '../../src/utils/oclif-utils';
import type { Category, Document } from './doc-types';

View File

@ -17,7 +17,7 @@
// eslint-disable-next-line no-restricted-imports
import { stripIndent } from 'common-tags';
import * as _ from 'lodash';
import _ from 'lodash';
import { promises as fs } from 'fs';
import * as path from 'path';
import { simpleGit } from 'simple-git';

View File

@ -15,11 +15,11 @@
* limitations under the License.
*/
import * as _ from 'lodash';
import _ from 'lodash';
import {
buildOclifInstaller,
buildStandaloneZip,
buildStandalone,
catchUncommitted,
signFilesForNotarization,
testShrinkwrap,
@ -36,7 +36,7 @@ process.env.DEBUG = ['0', 'no', 'false', '', undefined].includes(
* Trivial command-line parser. Check whether the command-line argument is one
* of the following strings, then call the appropriate functions:
* 'build:installer' (to build a native oclif installer)
* 'build:standalone' (to build a standalone pkg package)
* 'build:standalone' (to build a standalone package)
*
* @param args Arguments to parse (default is process.argv.slice(2))
*/
@ -49,7 +49,7 @@ async function parse(args?: string[]) {
}
const commands: { [cmd: string]: () => void | Promise<void> } = {
'build:installer': buildOclifInstaller,
'build:standalone': buildStandaloneZip,
'build:standalone': buildStandalone,
'sign:binaries': signFilesForNotarization,
'catch-uncommitted': catchUncommitted,
'test-shrinkwrap': testShrinkwrap,

View File

@ -18,73 +18,10 @@
import { spawn } from 'child_process';
import * as path from 'path';
import * as fs from 'fs';
import { diffTrimmedLines } from 'diff';
import * as whichMod from 'which';
export const ROOT = path.join(__dirname, '..');
/** Tap and buffer this process' stdout and stderr */
export class StdOutTap {
public stdoutBuf: string[] = [];
public stderrBuf: string[] = [];
public allBuf: string[] = []; // both stdout and stderr
protected origStdoutWrite: typeof process.stdout.write;
protected origStderrWrite: typeof process.stdout.write;
constructor(protected printDots = false) {}
tap() {
this.origStdoutWrite = process.stdout.write;
this.origStderrWrite = process.stderr.write;
process.stdout.write = (chunk: string, ...args: any[]): boolean => {
this.stdoutBuf.push(chunk);
this.allBuf.push(chunk);
const str = this.printDots ? '.' : chunk;
return this.origStdoutWrite.call(process.stdout, str, ...args);
};
process.stderr.write = (chunk: string, ...args: any[]): boolean => {
this.stderrBuf.push(chunk);
this.allBuf.push(chunk);
const str = this.printDots ? '.' : chunk;
return this.origStderrWrite.call(process.stderr, str, ...args);
};
}
untap() {
process.stdout.write = this.origStdoutWrite;
process.stderr.write = this.origStderrWrite;
if (this.printDots) {
console.error('');
}
}
}
/**
* Diff strings by line, using the 'diff' npm package:
* https://www.npmjs.com/package/diff
*/
export function diffLines(str1: string, str2: string): string {
const diffObjs = diffTrimmedLines(str1, str2);
const prefix = (chunk: string, char: string) =>
chunk
.split('\n')
.map((line: string) => `${char} ${line}`)
.join('\n');
const diffStr = diffObjs
.map((part: any) => {
return part.added
? prefix(part.value, '+')
: part.removed
? prefix(part.value, '-')
: prefix(part.value, ' ');
})
.join('\n');
return diffStr;
}
export function loadPackageJson() {
const packageJsonPath = path.join(ROOT, 'package.json');

View File

@ -574,9 +574,9 @@ Generate a config.json file for a device or fleet.
The target balenaOS version must be specified with the --version option.
The '--dev' option is used to configure balenaOS to operate in development mode,
allowing anauthenticated root ssh access and exposing network ports such as
allowing unauthenticated root ssh access and exposing network ports such as
balenaEngine's 2375 (unencrypted). This option causes `"developmentMode": true`
to be inserted in the 'config.json' file in the image's boot partion. Development
to be inserted in the 'config.json' file in the image's boot partition. Development
mode (as a configurable option) is applicable to balenaOS releases from early
2022. Older releases have separate development and production balenaOS images
that cannot be reconfigured through 'config.json' or the '--dev' option. Do not
@ -2872,9 +2872,9 @@ The --device-type option is used to override the fleet's default device type,
in case of a fleet with mixed device types.
The '--dev' option is used to configure balenaOS to operate in development mode,
allowing anauthenticated root ssh access and exposing network ports such as
allowing unauthenticated root ssh access and exposing network ports such as
balenaEngine's 2375 (unencrypted). This option causes `"developmentMode": true`
to be inserted in the 'config.json' file in the image's boot partion. Development
to be inserted in the 'config.json' file in the image's boot partition. Development
mode (as a configurable option) is applicable to balenaOS releases from early
2022. Older releases have separate development and production balenaOS images
that cannot be reconfigured through 'config.json' or the '--dev' option. Do not

1397
npm-shrinkwrap.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,10 @@
{
"name": "balena-cli",
"version": "21.1.3",
"version": "21.1.12",
"description": "The official balena Command Line Interface",
"main": "./build/app.js",
"homepage": "https://github.com/balena-io/balena-cli",
"type": "module",
"repository": {
"type": "git",
"url": "git@github.com:balena-io/balena-cli.git"
@ -24,26 +25,6 @@
"bin": {
"balena": "./bin/run.js"
},
"pkg": {
"scripts": [
"build/**/*.js",
"node_modules/balena-sdk/es2018/index.js",
"node_modules/pinejs-client-request/node_modules/pinejs-client-core/es2018/index.js",
"node_modules/@balena/compose/dist/parse/schemas/*.json"
],
"assets": [
"build/auth/pages/*.ejs",
"node_modules/balena-sdk/node_modules/balena-pine/**/*",
"node_modules/balena-pine/**/*",
"node_modules/pinejs-client-core/**/*",
"node_modules/open/xdg-open",
"node_modules/windosu/*.bat",
"node_modules/windosu/*.cmd",
"node_modules/axios/**/*",
"npm-shrinkwrap.json",
"oclif.manifest.json"
]
},
"scripts": {
"postinstall": "node patches/apply-patches.js",
"prebuild": "rimraf build/ build-bin/",
@ -114,14 +95,12 @@
"devDependencies": {
"@balena/lint": "^9.1.3",
"@electron/notarize": "^2.0.0",
"@types/archiver": "^6.0.2",
"@types/bluebird": "^3.5.36",
"@types/body-parser": "^1.19.2",
"@types/chai": "^4.3.0",
"@types/chai-as-promised": "^7.1.4",
"@types/cli-truncate": "^2.0.0",
"@types/common-tags": "^1.8.1",
"@types/diff": "^5.0.3",
"@types/dockerode": "3.3.23",
"@types/ejs": "^3.1.0",
"@types/express": "^4.17.13",
@ -160,16 +139,12 @@
"@types/update-notifier": "^4.1.1",
"@types/which": "^2.0.1",
"@types/window-size": "^1.1.1",
"@yao-pkg/pkg": "^5.11.1",
"archiver": "^7.0.1",
"catch-uncommitted": "^2.0.0",
"chai": "^4.3.4",
"chai-as-promised": "^7.1.1",
"cross-env": "^7.0.3",
"deep-object-diff": "^1.1.0",
"diff": "^5.0.0",
"ent": "^2.2.0",
"filehound": "^1.17.5",
"fs-extra": "^11.2.0",
"http-proxy": "^1.18.1",
"husky": "^9.1.5",
@ -190,16 +165,16 @@
"typescript": "^5.8.2"
},
"dependencies": {
"@balena/compose": "^7.0.1",
"@balena/compose": "^7.0.9",
"@balena/dockerignore": "^1.0.2",
"@balena/env-parsing": "^1.1.8",
"@balena/es-version": "^1.0.1",
"@oclif/core": "^4.1.0",
"@sentry/node": "^6.16.1",
"balena-config-json": "^4.2.2",
"balena-config-json": "^4.2.7",
"balena-device-init": "^8.1.3",
"balena-errors": "^4.7.3",
"balena-image-fs": "^7.5.0",
"balena-image-fs": "^7.5.2",
"balena-preload": "^18.0.1",
"balena-sdk": "^21.3.0",
"balena-semver": "^2.3.0",
@ -214,9 +189,9 @@
"common-tags": "^1.7.2",
"date-fns": "^4.1.0",
"denymount": "^2.3.0",
"docker-modem": "5.0.5",
"docker-modem": "^5.0.6",
"docker-progress": "^5.1.3",
"dockerode": "4.0.3",
"dockerode": "^4.0.5",
"ejs": "^3.1.6",
"etcher-sdk": "9.1.0",
"express": "^4.17.2",
@ -276,6 +251,6 @@
}
},
"versionist": {
"publishedAt": "2025-03-28T16:57:01.229Z"
"publishedAt": "2025-05-16T18:54:50.104Z"
}
}

View File

@ -1,16 +0,0 @@
diff --git a/node_modules/open/index.js b/node_modules/open/index.js
index 13147d0..ff161dd 100644
--- a/node_modules/open/index.js
+++ b/node_modules/open/index.js
@@ -10,7 +10,10 @@ const pAccess = promisify(fs.access);
const pReadFile = promisify(fs.readFile);
// Path to included `xdg-open`.
-const localXdgOpenPath = path.join(__dirname, 'xdg-open');
+const localXdgOpenPath = process.pkg
+ ? path.join(path.dirname(process.execPath), 'xdg-open')
+ : path.join(__dirname, 'xdg-open');
+
/**
Get the mount point for fixed drives in WSL.

View File

@ -1,14 +0,0 @@
diff --git a/node_modules/node-gyp-build/node-gyp-build.js b/node_modules/node-gyp-build/node-gyp-build.js
index 61b398e..3cc3be8 100644
--- a/node_modules/node-gyp-build/node-gyp-build.js
+++ b/node_modules/node-gyp-build/node-gyp-build.js
@@ -30,6 +30,9 @@ load.resolve = load.path = function (dir) {
if (process.env[name + '_PREBUILD']) dir = process.env[name + '_PREBUILD']
} catch (err) {}
+ // pkg fix: native node modules are located externally to the pkg executable
+ dir = dir.replace(/^\/snapshot\/.+?\/node_modules\//, path.dirname(process.execPath) + path.sep)
+
if (!prebuildsOnly) {
var release = getFirst(path.join(dir, 'build/Release'), matchBuild)
if (release) return release

View File

@ -1,38 +0,0 @@
diff --git a/node_modules/windosu/lib/pipe.js b/node_modules/windosu/lib/pipe.js
index dc81fa5..a381cc7 100644
--- a/node_modules/windosu/lib/pipe.js
+++ b/node_modules/windosu/lib/pipe.js
@@ -42,7 +42,8 @@ function pipe(path, options) {
return d.promise;
}
module.exports = pipe;
-if (module === require.main) {
+
+function main() {
if (!process.argv[4]) {
console.error('Incorrect arguments!');
process.exit(-1);
@@ -52,3 +53,8 @@ if (module === require.main) {
serve: process.argv[3] == 'server'
});
}
+module.exports.main = main;
+
+if (module === require.main) {
+ main();
+}
diff --git a/node_modules/windosu/lib/windosu.js b/node_modules/windosu/lib/windosu.js
index 6502812..dd0391a 100644
--- a/node_modules/windosu/lib/windosu.js
+++ b/node_modules/windosu/lib/windosu.js
@@ -16,7 +16,9 @@ module.exports.exec = function (command, options, callback) {
temp: temp,
command: command,
cliWidth: cliWidth(),
- pipe: '"' + process.execPath + '" "' + path.join(__dirname, 'pipe.js') + '"',
+ pipe: process.pkg
+ ? '"' + process.execPath + '" pkgExec "' + path.join(__dirname, 'pipe.js') + '::main"'
+ : '"' + process.execPath + '" "' + path.join(__dirname, 'pipe.js') + '"',
input: inputName = id + '-in',
output: outputName = id + '-out',
stderr_redir: process.stdout.isTTY ? '2>&1' : '2> %ERROR%'

View File

@ -16,14 +16,14 @@
*/
import * as packageJSON from '../package.json';
import type { AppOptions } from './preparser';
import type { AppOptions } from './preparser.js';
import {
checkDeletedCommand,
preparseArgs,
unsupportedFlag,
} from './preparser';
import { CliSettings } from './utils/bootstrap';
import { onceAsync } from './utils/lazy';
} from './preparser.js';
import { CliSettings } from './utils/bootstrap.js';
import { onceAsync } from './utils/lazy.js';
import { run as mainRun, settings } from '@oclif/core';
/**
@ -31,7 +31,7 @@ import { run as mainRun, settings } from '@oclif/core';
* @see https://docs.sentry.io/error-reporting/quickstart/?platform=node
*/
export const setupSentry = onceAsync(async () => {
const config = await import('./config');
const config = await import('./config.js');
const Sentry = await import('@sentry/node');
Sentry.init({
autoSessionTracking: false,
@ -51,7 +51,7 @@ export const setupSentry = onceAsync(async () => {
async function checkNodeVersion() {
const validNodeVersions = packageJSON.engines.node;
if (!(await import('semver')).satisfies(process.version, validNodeVersions)) {
const { getNodeEngineVersionWarn } = await import('./utils/messages');
const { getNodeEngineVersionWarn } = await import('./utils/messages.js');
console.warn(getNodeEngineVersionWarn(process.version, validNodeVersions));
}
}
@ -89,13 +89,13 @@ async function init() {
const settings = new CliSettings();
// Proxy setup should be done early on, before loading balena-sdk
await (await import('./utils/proxy')).setupGlobalHttpProxy(settings);
await (await import('./utils/proxy.js')).setupGlobalHttpProxy(settings);
setupBalenaSdkSharedOptions(settings);
// check for CLI updates once a day
if (!process.env.BALENARC_OFFLINE_MODE) {
(await import('./utils/update')).notify();
(await import('./utils/update.js')).notify();
}
}
@ -104,7 +104,7 @@ async function oclifRun(command: string[], options: AppOptions) {
let deprecationPromise: Promise<void> | undefined;
// check and enforce the CLI's deprecation policy
if (!(unsupportedFlag || process.env.BALENARC_UNSUPPORTED)) {
const { DeprecationChecker } = await import('./deprecation');
const { DeprecationChecker } = await import('./deprecation.js');
const deprecationChecker = new DeprecationChecker(packageJSON.version);
// warnAndAbortIfDeprecated uses previously cached data only
await deprecationChecker.warnAndAbortIfDeprecated();
@ -147,11 +147,11 @@ async function oclifRun(command: string[], options: AppOptions) {
// the try/catch block above, execution does not get past the
// Promise.all() call below, but I don't understand why.
if (isEEXIT) {
(await import('./fast-boot')).stop();
(await import('./fast-boot.js')).stop();
}
})(!options.noFlush);
const { trackPromise } = await import('./hooks/prerun');
const { trackPromise } = await import('./hooks/prerun.js');
await Promise.all([trackPromise, deprecationPromise, runPromise]);
}
@ -159,18 +159,12 @@ async function oclifRun(command: string[], options: AppOptions) {
/** CLI entrypoint. Called by the `bin/run.js` and `bin/dev.js` scripts. */
export async function run(cliArgs = process.argv, options: AppOptions) {
try {
const { setOfflineModeEnvVars, normalizeEnvVars, pkgExec } = await import(
'./utils/bootstrap'
const { setOfflineModeEnvVars, normalizeEnvVars } = await import(
'./utils/bootstrap.js'
);
setOfflineModeEnvVars();
normalizeEnvVars();
// The 'pkgExec' special/internal command provides a Node.js interpreter
// for use of the standalone zip package. See pkgExec function.
if (cliArgs.length > 3 && cliArgs[2] === 'pkgExec') {
return pkgExec(cliArgs[3], cliArgs.slice(4));
}
await init();
// Look for commands that have been removed and if so, exit with a notice
@ -179,10 +173,10 @@ export async function run(cliArgs = process.argv, options: AppOptions) {
const args = await preparseArgs(cliArgs);
await oclifRun(args, options);
} catch (err) {
await (await import('./errors')).handleError(err);
await (await import('./errors.js')).handleError(err);
} finally {
try {
(await import('./fast-boot')).stop();
(await import('./fast-boot.js')).stop();
} catch (e) {
if (process.env.DEBUG) {
console.error(`[debug] Stopping fast-boot: ${e}`);

View File

@ -14,8 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import { getBalenaSdk } from '../utils/lazy';
import { LoginServer } from './server';
import { getBalenaSdk } from '../utils/lazy.js';
import { LoginServer } from './server.js';
/**
* @module auth
@ -42,7 +42,7 @@ import { LoginServer } from './server';
* console.log("My session token is: #{sessionToken}")
*/
export async function login({ host = '127.0.0.1', port = 0 }) {
const utils = await import('./utils');
const utils = await import('./utils.js');
const loginServer = new LoginServer();
const {
@ -55,7 +55,7 @@ export async function login({ host = '127.0.0.1', port = 0 }) {
const loginUrl = await utils.getDashboardLoginURL(callbackUrl);
console.info(`Opening web browser for URL:\n${loginUrl}`);
const open = await import('open');
const { default: open } = await import('open');
await open(loginUrl, { wait: false });
const balena = getBalenaSdk();

View File

@ -16,12 +16,12 @@ limitations under the License.
import * as bodyParser from 'body-parser';
import { EventEmitter } from 'events';
import * as express from 'express';
import express from 'express';
import type { Socket } from 'net';
import * as path from 'path';
import * as utils from './utils';
import { ExpectedError } from '../errors';
import * as utils from './utils.js';
import { ExpectedError } from '../errors.js';
export class LoginServer extends EventEmitter {
protected expressApp: express.Express;

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import { getBalenaSdk } from '../utils/lazy';
import { getBalenaSdk } from '../utils/lazy.js';
/**
* Get dashboard CLI login URL

View File

@ -16,8 +16,8 @@
*/
import { Args, Command } from '@oclif/core';
import { ExpectedError } from '../../errors';
import { getBalenaSdk, getCliForm, stripIndent } from '../../utils/lazy';
import { ExpectedError } from '../../errors.js';
import { getBalenaSdk, getCliForm, stripIndent } from '../../utils/lazy.js';
import {
formatDuration,
intervalToDuration,
@ -33,7 +33,7 @@ async function isLoggedInWithJwt() {
try {
const token = await balena.auth.getToken();
const { default: jwtDecode } = await import('jwt-decode');
jwtDecode(token);
jwtDecode.default(token);
return true;
} catch {
return false;

View File

@ -16,8 +16,8 @@
*/
import { Flags, Command } from '@oclif/core';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
import * as cf from '../../utils/common-flags.js';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy.js';
export default class APIKeyListCmd extends Command {
public static aliases = ['api-keys'];
@ -45,7 +45,7 @@ export default class APIKeyListCmd extends Command {
public async run() {
const { flags: options } = await this.parse(APIKeyListCmd);
const { getApplication } = await import('../../utils/sdk');
const { getApplication } = await import('../../utils/sdk.js');
const actorId = options.fleet
? (
await getApplication(getBalenaSdk(), options.fleet, {

View File

@ -16,7 +16,7 @@
*/
import { Args, Command } from '@oclif/core';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
export default class RevokeCmd extends Command {
public static description = stripIndent`

View File

@ -16,7 +16,7 @@
*/
import { Flags, Args, Command } from '@oclif/core';
import { stripIndent } from '../../utils/lazy';
import { stripIndent } from '../../utils/lazy.js';
export default class AppCreateCmd extends Command {
public static description = stripIndent`
@ -71,7 +71,7 @@ export default class AppCreateCmd extends Command {
const { args: params, flags: options } = await this.parse(AppCreateCmd);
await (
await import('../../utils/application-create')
await import('../../utils/application-create.js')
).applicationCreateBase('app', options, params);
}
}

View File

@ -16,7 +16,7 @@
*/
import { Flags, Args, Command } from '@oclif/core';
import { stripIndent } from '../../utils/lazy';
import { stripIndent } from '../../utils/lazy.js';
export default class BlockCreateCmd extends Command {
public static description = stripIndent`
@ -71,7 +71,7 @@ export default class BlockCreateCmd extends Command {
const { args: params, flags: options } = await this.parse(BlockCreateCmd);
await (
await import('../../utils/application-create')
await import('../../utils/application-create.js')
).applicationCreateBase('block', options, params);
}
}

View File

@ -16,9 +16,9 @@
*/
import { Args, Flags, Command } from '@oclif/core';
import { getBalenaSdk } from '../../utils/lazy';
import * as cf from '../../utils/common-flags';
import * as compose from '../../utils/compose';
import { getBalenaSdk } from '../../utils/lazy.js';
import * as cf from '../../utils/common-flags.js';
import * as compose from '../../utils/compose.js';
import type {
ApplicationType,
BalenaSDK,
@ -30,11 +30,11 @@ import {
buildArgDeprecation,
dockerignoreHelp,
registrySecretsHelp,
} from '../../utils/messages';
import type { ComposeCliFlags, ComposeOpts } from '../../utils/compose-types';
import { buildProject, composeCliFlags } from '../../utils/compose_ts';
import type { BuildOpts, DockerCliFlags } from '../../utils/docker';
import { dockerCliFlags } from '../../utils/docker';
} from '../../utils/messages.js';
import type { ComposeCliFlags, ComposeOpts } from '../../utils/compose-types.js';
import { buildProject, composeCliFlags } from '../../utils/compose_ts.js';
import type { BuildOpts, DockerCliFlags } from '../../utils/docker.js';
import { dockerCliFlags } from '../../utils/docker.js';
type ComposeGenerateOptsParam = Parameters<typeof compose.generateOpts>[0];
@ -103,8 +103,8 @@ ${dockerignoreHelp}
public async run() {
const { args: params, flags: options } = await this.parse(BuildCmd);
const Logger = await import('../../utils/logger');
const { checkLoggedInIf } = await import('../../utils/patterns');
const { default: Logger } = await import('../../utils/logger.js');
const { checkLoggedInIf } = await import('../../utils/patterns.js');
await checkLoggedInIf(!!options.fleet);
@ -157,14 +157,14 @@ ${dockerignoreHelp}
(opts.fleet == null && (opts.arch == null || opts.deviceType == null)) ||
(opts.fleet != null && (opts.arch != null || opts.deviceType != null))
) {
const { ExpectedError } = await import('../../errors');
const { ExpectedError } = await import('../../errors.js');
throw new ExpectedError(
'You must specify either a fleet (-f), or the device type (-d) and optionally the architecture (-A)',
);
}
// Validate project directory
const { validateProjectDirectory } = await import('../../utils/compose_ts');
const { validateProjectDirectory } = await import('../../utils/compose_ts.js');
const { dockerfilePath, registrySecrets } = await validateProjectDirectory(
sdk,
{
@ -200,7 +200,7 @@ ${dockerignoreHelp}
)) as PineTypedResult<DeviceType, typeof deviceTypeOpts>
).is_of__cpu_architecture[0].slug;
} catch (err) {
const { ExpectedError } = await import('../../errors');
const { ExpectedError } = await import('../../errors.js');
if (err instanceof sdk.errors.BalenaInvalidDeviceType) {
let message = err.message;
if (!(await sdk.auth.isLoggedIn())) {
@ -217,7 +217,7 @@ ${dockerignoreHelp}
protected async getAppAndResolveArch(opts: PrepareBuildOpts) {
if (opts.fleet) {
const { getAppWithArch } = await import('../../utils/helpers');
const { getAppWithArch } = await import('../../utils/helpers.js');
const app = await getAppWithArch(opts.fleet);
opts.arch = app.arch;
opts.deviceType = app.is_for__device_type[0].slug;
@ -226,7 +226,7 @@ ${dockerignoreHelp}
}
protected async prepareBuild(options: PrepareBuildOpts) {
const { getDocker, generateBuildOpts } = await import('../../utils/docker');
const { getDocker, generateBuildOpts } = await import('../../utils/docker.js');
const [docker, buildOpts, composeOpts] = await Promise.all([
getDocker(options),
generateBuildOpts(options),
@ -254,7 +254,7 @@ ${dockerignoreHelp}
*/
protected async buildProject(
docker: import('dockerode'),
logger: import('../../utils/logger'),
logger: import('../../utils/logger.js').default,
composeOpts: ComposeOpts,
opts: {
appType?: Pick<ApplicationType, 'supports_multicontainer'>;
@ -264,7 +264,7 @@ ${dockerignoreHelp}
buildOpts: BuildOpts;
},
) {
const { loadProject } = await import('../../utils/compose_ts');
const { loadProject } = await import('../../utils/compose_ts.js');
const project = await loadProject(
logger,

View File

@ -17,13 +17,13 @@
import { Flags, Command } from '@oclif/core';
import type { Interfaces } from '@oclif/core';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, getCliForm, stripIndent } from '../../utils/lazy';
import * as cf from '../../utils/common-flags.js';
import { getBalenaSdk, getCliForm, stripIndent } from '../../utils/lazy.js';
import {
applicationIdInfo,
devModeInfo,
secureBootInfo,
} from '../../utils/messages';
} from '../../utils/messages.js';
import type { BalenaSDK, PineDeferred } from 'balena-sdk';
export default class ConfigGenerateCmd extends Command {
@ -122,7 +122,7 @@ export default class ConfigGenerateCmd extends Command {
public static authenticated = true;
public async getApplication(balena: BalenaSDK, fleet: string) {
const { getApplication } = await import('../../utils/sdk');
const { getApplication } = await import('../../utils/sdk.js');
return await getApplication(balena, fleet, {
$select: 'slug',
$expand: {
@ -148,7 +148,7 @@ export default class ConfigGenerateCmd extends Command {
$expand: { is_of__device_type: { $select: 'slug' } },
});
if (!rawDevice.belongs_to__application) {
const { ExpectedError } = await import('../../errors');
const { ExpectedError } = await import('../../errors.js');
throw new ExpectedError(stripIndent`
Device ${options.device} does not appear to belong to an accessible fleet.
Try with a different device, or use '--fleet' instead of '--device'.`);
@ -167,14 +167,14 @@ export default class ConfigGenerateCmd extends Command {
// Check compatibility if application and deviceType provided
if (options.fleet && options.deviceType) {
const helpers = await import('../../utils/helpers');
const helpers = await import('../../utils/helpers.js');
if (
!(await helpers.areDeviceTypesCompatible(
resourceDeviceType,
deviceType,
))
) {
const { ExpectedError } = await import('../../errors');
const { ExpectedError } = await import('../../errors.js');
throw new ExpectedError(
`Device type ${options.deviceType} is incompatible with fleet ${options.fleet}`,
);
@ -185,7 +185,7 @@ export default class ConfigGenerateCmd extends Command {
await balena.models.config.getDeviceTypeManifestBySlug(deviceType);
const { validateSecureBootOptionAndWarn } = await import(
'../../utils/config'
'../../utils/config.js'
);
await validateSecureBootOptionAndWarn(
options.secureBoot,
@ -207,7 +207,7 @@ export default class ConfigGenerateCmd extends Command {
// Generate config
const { generateDeviceConfig, generateApplicationConfig } = await import(
'../../utils/config'
'../../utils/config.js'
);
let config;
@ -246,7 +246,7 @@ export default class ConfigGenerateCmd extends Command {
protected async validateOptions(
options: Interfaces.InferredFlags<typeof ConfigGenerateCmd.flags>,
) {
const { ExpectedError } = await import('../../errors');
const { ExpectedError } = await import('../../errors.js');
if (options.device == null && options.fleet == null) {
throw new ExpectedError(this.missingDeviceOrAppMessage);
@ -255,9 +255,9 @@ export default class ConfigGenerateCmd extends Command {
if (!options.fleet && options.deviceType) {
throw new ExpectedError(this.deviceTypeNotAllowedMessage);
}
const { normalizeOsVersion } = await import('../../utils/normalization');
const { normalizeOsVersion } = await import('../../utils/normalization.js');
options.version = normalizeOsVersion(options.version);
const { validateDevOptionAndWarn } = await import('../../utils/config');
const { validateDevOptionAndWarn } = await import('../../utils/config.js');
await validateDevOptionAndWarn(options.dev, options.version);
}
}

View File

@ -16,8 +16,8 @@
*/
import { Args, Command } from '@oclif/core';
import * as cf from '../../utils/common-flags';
import { getVisuals, stripIndent } from '../../utils/lazy';
import * as cf from '../../utils/common-flags.js';
import { getVisuals, stripIndent } from '../../utils/lazy.js';
export default class ConfigInjectCmd extends Command {
public static description = stripIndent`
@ -52,7 +52,7 @@ export default class ConfigInjectCmd extends Command {
public async run() {
const { args: params, flags: options } = await this.parse(ConfigInjectCmd);
const { safeUmount } = await import('../../utils/umount');
const { safeUmount } = await import('../../utils/umount.js');
const drive =
options.drive || (await getVisuals().drive('Select the device/OS drive'));
@ -64,7 +64,12 @@ export default class ConfigInjectCmd extends Command {
);
const config = await import('balena-config-json');
await config.write(drive, '', configJSON);
await config.write(
drive,
// Will be removed in the next major of balena-config-json
undefined,
configJSON,
);
console.info('Done');
}

View File

@ -16,8 +16,8 @@
*/
import { Command } from '@oclif/core';
import * as cf from '../../utils/common-flags';
import { getVisuals, stripIndent } from '../../utils/lazy';
import * as cf from '../../utils/common-flags.js';
import { getVisuals, stripIndent } from '../../utils/lazy.js';
export default class ConfigReadCmd extends Command {
public static description = stripIndent`
@ -47,14 +47,14 @@ export default class ConfigReadCmd extends Command {
public async run() {
const { flags: options } = await this.parse(ConfigReadCmd);
const { safeUmount } = await import('../../utils/umount');
const { safeUmount } = await import('../../utils/umount.js');
const drive =
options.drive || (await getVisuals().drive('Select the device drive'));
await safeUmount(drive);
const config = await import('balena-config-json');
const configJSON = await config.read(drive, '');
const configJSON = await config.read(drive);
if (options.json) {
console.log(JSON.stringify(configJSON, null, 4));

View File

@ -16,8 +16,8 @@
*/
import { Flags, Command } from '@oclif/core';
import * as cf from '../../utils/common-flags';
import { getVisuals, stripIndent } from '../../utils/lazy';
import * as cf from '../../utils/common-flags.js';
import { getVisuals, stripIndent } from '../../utils/lazy.js';
export default class ConfigReconfigureCmd extends Command {
public static description = stripIndent`
@ -55,18 +55,18 @@ export default class ConfigReconfigureCmd extends Command {
public async run() {
const { flags: options } = await this.parse(ConfigReconfigureCmd);
const { safeUmount } = await import('../../utils/umount');
const { safeUmount } = await import('../../utils/umount.js');
const drive =
options.drive || (await getVisuals().drive('Select the device drive'));
await safeUmount(drive);
const config = await import('balena-config-json');
const { uuid } = await config.read(drive, '');
const { uuid } = await config.read(drive);
await safeUmount(drive);
if (!uuid) {
const { ExpectedError } = await import('../../errors');
const { ExpectedError } = await import('../../errors.js');
throw new ExpectedError(
`Error: UUID not found in 'config.json' file for '${drive}'`,
);
@ -80,7 +80,7 @@ export default class ConfigReconfigureCmd extends Command {
configureCommand.push('--advanced');
}
const { runCommand } = await import('../../utils/helpers');
const { runCommand } = await import('../../utils/helpers.js');
await runCommand(configureCommand);
console.info('Done');

View File

@ -16,8 +16,8 @@
*/
import { Args, Command } from '@oclif/core';
import * as cf from '../../utils/common-flags';
import { getVisuals, stripIndent } from '../../utils/lazy';
import * as cf from '../../utils/common-flags.js';
import { getVisuals, stripIndent } from '../../utils/lazy.js';
export default class ConfigWriteCmd extends Command {
public static description = stripIndent`
@ -57,21 +57,26 @@ export default class ConfigWriteCmd extends Command {
public async run() {
const { args: params, flags: options } = await this.parse(ConfigWriteCmd);
const { denyMount, safeUmount } = await import('../../utils/umount');
const { denyMount, safeUmount } = await import('../../utils/umount.js');
const drive =
options.drive || (await getVisuals().drive('Select the device drive'));
await safeUmount(drive);
const config = await import('balena-config-json');
const configJSON = await config.read(drive, '');
const configJSON = await config.read(drive);
console.info(`Setting ${params.key} to ${params.value}`);
ConfigWriteCmd.updateConfigJson(configJSON, params.key, params.value);
await denyMount(drive, async () => {
await safeUmount(drive);
await config.write(drive, '', configJSON);
await config.write(
drive,
// Will be removed in the next major of balena-config-json
undefined,
configJSON,
);
});
console.info('Done');

View File

@ -16,31 +16,31 @@
*/
import { Args, Flags, Command } from '@oclif/core';
import type { ImageDescriptor } from '@balena/compose/dist/parse';
import { ExpectedError } from '../../errors';
import { getBalenaSdk, getChalk, stripIndent } from '../../utils/lazy';
import type { ImageDescriptor } from '@balena/compose/dist/parse/index.js';
import { ExpectedError } from '../../errors.js';
import { getBalenaSdk, getChalk, stripIndent } from '../../utils/lazy.js';
import {
dockerignoreHelp,
registrySecretsHelp,
buildArgDeprecation,
} from '../../utils/messages';
} from '../../utils/messages.js';
import * as ca from '../../utils/common-args';
import * as compose from '../../utils/compose';
import * as compose from '../../utils/compose.js';
import type {
BuiltImage,
ComposeCliFlags,
ComposeOpts,
Release as ComposeReleaseInfo,
} from '../../utils/compose-types';
import type { BuildOpts, DockerCliFlags } from '../../utils/docker';
} from '../../utils/compose-types.js';
import type { BuildOpts, DockerCliFlags } from '../../utils/docker.js';
import {
applyReleaseTagKeysAndValues,
buildProject,
composeCliFlags,
isBuildConfig,
parseReleaseTagKeysAndValues,
} from '../../utils/compose_ts';
import { dockerCliFlags } from '../../utils/docker';
} from '../../utils/compose_ts.js';
import { dockerCliFlags } from '../../utils/docker.js';
import type { ApplicationType, DeviceType, Release } from 'balena-sdk';
interface ApplicationWithArch {
@ -149,7 +149,7 @@ ${dockerignoreHelp}
(await import('events')).defaultMaxListeners = 1000;
const Logger = await import('../../utils/logger');
const { default: Logger } = await import('../../utils/logger.js');
const logger = Logger.getLogger();
logger.logDebug('Parsing input...');
@ -169,7 +169,7 @@ ${dockerignoreHelp}
const sdk = getBalenaSdk();
const { getRegistrySecrets, validateProjectDirectory } = await import(
'../../utils/compose_ts'
'../../utils/compose_ts.js'
);
const { releaseTagKeys, releaseTagValues } = parseReleaseTagKeysAndValues(
@ -193,10 +193,10 @@ ${dockerignoreHelp}
(options as FlagsDef)['registry-secrets'] = registrySecrets;
}
const helpers = await import('../../utils/helpers');
const helpers = await import('../../utils/helpers.js');
const app = await helpers.getAppWithArch(fleet);
const dockerUtils = await import('../../utils/docker');
const dockerUtils = await import('../../utils/docker.js');
const [docker, buildOpts, composeOpts] = await Promise.all([
dockerUtils.getDocker(options),
dockerUtils.generateBuildOpts(options as FlagsDef),
@ -244,7 +244,7 @@ ${dockerignoreHelp}
const doodles = await import('resin-doodles');
const sdk = getBalenaSdk();
const { deployProject: $deployProject, loadProject } = await import(
'../../utils/compose_ts'
'../../utils/compose_ts.js'
);
const appType = opts.app.application_type[0];

View File

@ -16,8 +16,8 @@
*/
import { Flags, Command } from '@oclif/core';
import type * as BalenaSdk from 'balena-sdk';
import * as _ from 'lodash';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
import _ from 'lodash';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy.js';
export default class DeviceTypeListCmd extends Command {
public static aliases = ['devices supported'];

View File

@ -16,8 +16,8 @@
*/
import { Args, Command } from '@oclif/core';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import * as cf from '../../utils/common-flags.js';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
export default class DeviceDeactivateCmd extends Command {
public static description = stripIndent`
@ -51,7 +51,7 @@ export default class DeviceDeactivateCmd extends Command {
await this.parse(DeviceDeactivateCmd);
const balena = getBalenaSdk();
const patterns = await import('../../utils/patterns');
const patterns = await import('../../utils/patterns.js');
const uuid = params.uuid;
const deactivationWarning = `

View File

@ -16,7 +16,7 @@
*/
import { Flags, Command } from '@oclif/core';
import { getCliUx, stripIndent } from '../../utils/lazy';
import { getCliUx, stripIndent } from '../../utils/lazy.js';
export default class DeviceDetectCmd extends Command {
public static aliases = ['scan'];
@ -66,7 +66,7 @@ export default class DeviceDetectCmd extends Command {
'../../utils/discover'
);
const prettyjson = await import('prettyjson');
const dockerUtils = await import('../../utils/docker');
const dockerUtils = await import('../../utils/docker.js');
const dockerPort = 2375;
const dockerTimeout = 2000;

View File

@ -16,8 +16,8 @@
*/
import { Args, Command } from '@oclif/core';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { ExpectedError } from '../../errors';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
import { ExpectedError } from '../../errors.js';
export default class DeviceIdentifyCmd extends Command {
public static description = stripIndent`

View File

@ -16,10 +16,10 @@
*/
import { Flags, Args, Command } from '@oclif/core';
import * as cf from '../../utils/common-flags';
import { expandForAppName } from '../../utils/helpers';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
import { jsonInfo } from '../../utils/messages';
import * as cf from '../../utils/common-flags.js';
import { expandForAppName } from '../../utils/helpers.js';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy.js';
import { jsonInfo } from '../../utils/messages.js';
import type { Application, Release } from 'balena-sdk';
@ -132,7 +132,7 @@ export default class DeviceCmd extends Command {
}
if (options.view) {
const open = await import('open');
const { default: open } = await import('open');
const dashboardUrl = balena.models.device.getDashboardUrl(device.uuid);
await open(dashboardUrl, { wait: false });
return;

View File

@ -16,10 +16,10 @@
*/
import { Flags, Command } from '@oclif/core';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { applicationIdInfo } from '../../utils/messages';
import { runCommand } from '../../utils/helpers';
import * as cf from '../../utils/common-flags.js';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
import { applicationIdInfo } from '../../utils/messages.js';
import { runCommand } from '../../utils/helpers.js';
interface FlagsDef {
fleet?: string;
@ -113,8 +113,8 @@ export default class DeviceInitCmd extends Command {
const tmpNameAsync = promisify(tmp.tmpName);
tmp.setGracefulCleanup();
const { downloadOSImage } = await import('../../utils/cloud');
const { getApplication } = await import('../../utils/sdk');
const Logger = await import('../../utils/logger');
const { getApplication } = await import('../../utils/sdk.js');
const { default: Logger } = await import('../../utils/logger.js');
const logger = Logger.getLogger();
const balena = getBalenaSdk();
@ -129,7 +129,7 @@ export default class DeviceInitCmd extends Command {
},
},
})
: await (await import('../../utils/patterns')).selectApplication();
: await (await import('../../utils/patterns.js')).selectApplication();
// Register new device
const deviceUuid = balena.models.device.generateUniqueKey();

View File

@ -16,10 +16,10 @@
*/
import { Command } from '@oclif/core';
import * as cf from '../../utils/common-flags';
import { expandForAppName } from '../../utils/helpers';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
import { applicationIdInfo, jsonInfo } from '../../utils/messages';
import * as cf from '../../utils/common-flags.js';
import { expandForAppName } from '../../utils/helpers.js';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy.js';
import { applicationIdInfo, jsonInfo } from '../../utils/messages.js';
import type { Device, PineOptions } from 'balena-sdk';
@ -78,7 +78,7 @@ export default class DeviceListCmd extends Command {
const devices = (
await (async () => {
if (options.fleet != null) {
const { getApplication } = await import('../../utils/sdk');
const { getApplication } = await import('../../utils/sdk.js');
const application = await getApplication(balena, options.fleet, {
$select: 'slug',
$expand: {
@ -115,7 +115,7 @@ export default class DeviceListCmd extends Command {
];
if (options.json) {
const { pickAndRename } = await import('../../utils/helpers');
const { pickAndRename } = await import('../../utils/helpers.js');
const mapped = devices.map((device) => pickAndRename(device, fields));
console.log(JSON.stringify(mapped, null, 4));
} else {

View File

@ -16,7 +16,7 @@
*/
import { Flags, Args, Command } from '@oclif/core';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
export default class DeviceLocalModeCmd extends Command {
public static description = stripIndent`

View File

@ -16,7 +16,7 @@
*/
import { Flags, Args, Command } from '@oclif/core';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
import type { LogMessage } from 'balena-sdk';
const MAX_RETRY = 1000;
@ -101,7 +101,7 @@ export default class DeviceLogsCmd extends Command {
const { validateIPAddress, validateDotLocalUrl } = await import(
'../../utils/validation'
);
const Logger = await import('../../utils/logger');
const { default: Logger } = await import('../../utils/logger.js');
const logger = Logger.getLogger();
@ -136,7 +136,7 @@ export default class DeviceLogsCmd extends Command {
try {
await deviceApi.ping();
} catch {
const { ExpectedError } = await import('../../errors');
const { ExpectedError } = await import('../../errors.js');
throw new ExpectedError(
`Cannot access device at address ${params.device}. Device may not be in local mode.`,
);
@ -151,7 +151,7 @@ export default class DeviceLogsCmd extends Command {
maxAttempts: 1 + (options['max-retry'] ?? MAX_RETRY),
});
} else {
const { checkLoggedIn } = await import('../../utils/patterns');
const { checkLoggedIn } = await import('../../utils/patterns.js');
// Logs from cloud
await checkLoggedIn();
if (options.tail) {

View File

@ -22,10 +22,10 @@ import type {
PineOptions,
PineTypedResult,
} from 'balena-sdk';
import * as cf from '../../utils/common-flags';
import { ExpectedError } from '../../errors';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { applicationIdInfo } from '../../utils/messages';
import * as cf from '../../utils/common-flags.js';
import { ExpectedError } from '../../errors.js';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
import { applicationIdInfo } from '../../utils/messages.js';
export default class DeviceMoveCmd extends Command {
public static description = stripIndent`
@ -97,7 +97,7 @@ export default class DeviceMoveCmd extends Command {
const devices = await this.getDevices(balena, deviceUuids);
// Disambiguate application
const { getApplication } = await import('../../utils/sdk');
const { getApplication } = await import('../../utils/sdk.js');
// Get destination application
const application = options.fleet
@ -147,7 +147,7 @@ export default class DeviceMoveCmd extends Command {
})
.map((deviceType) => deviceType.id);
const patterns = await import('../../utils/patterns');
const patterns = await import('../../utils/patterns.js');
try {
const application = await patterns.selectApplication(
{

View File

@ -16,9 +16,9 @@
*/
import { Flags, Args, Command } from '@oclif/core';
import { ExpectedError } from '../../errors';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { ExpectedError } from '../../errors.js';
import * as cf from '../../utils/common-flags.js';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
export default class DeviceNoteCmd extends Command {
public static aliases = ['notes'];

View File

@ -16,10 +16,10 @@
*/
import { Flags, Args, Command } from '@oclif/core';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy';
import * as cf from '../../utils/common-flags.js';
import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy.js';
import type { Device } from 'balena-sdk';
import { ExpectedError } from '../../errors';
import { ExpectedError } from '../../errors.js';
import { getExpandedProp } from '../../utils/pine';
export default class DeviceOsUpdateCmd extends Command {
@ -119,7 +119,7 @@ export default class DeviceOsUpdateCmd extends Command {
// Get target OS version
let targetOsVersion = options.version;
if (targetOsVersion != null) {
const { normalizeOsVersion } = await import('../../utils/normalization');
const { normalizeOsVersion } = await import('../../utils/normalization.js');
targetOsVersion = normalizeOsVersion(targetOsVersion);
if (!hupVersionInfo.versions.includes(targetOsVersion)) {
throw new ExpectedError(
@ -155,7 +155,7 @@ export default class DeviceOsUpdateCmd extends Command {
currentOsVersion,
targetOsVersion,
)) === 'takeover';
const patterns = await import('../../utils/patterns');
const patterns = await import('../../utils/patterns.js');
// Warn the user if the update requires a takeover
if (takeoverRequired) {
await patterns.confirm(

View File

@ -16,7 +16,7 @@
*/
import { Args, Command } from '@oclif/core';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
import { getExpandedProp } from '../../utils/pine';
export default class DevicePinCmd extends Command {

View File

@ -16,8 +16,8 @@
*/
import { Flags, Args, Command } from '@oclif/core';
import { ExpectedError } from '../../errors';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { ExpectedError } from '../../errors.js';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
export default class DevicePublicUrlCmd extends Command {
public static description = stripIndent`

View File

@ -16,7 +16,7 @@
*/
import { Args, Command } from '@oclif/core';
import { getBalenaSdk, getCliUx, stripIndent } from '../../utils/lazy';
import { getBalenaSdk, getCliUx, stripIndent } from '../../utils/lazy.js';
export default class DevicePurgeCmd extends Command {
public static description = stripIndent`

View File

@ -16,8 +16,8 @@
*/
import { Args, Command } from '@oclif/core';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import * as cf from '../../utils/common-flags.js';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
export default class DeviceRebootCmd extends Command {
public static description = stripIndent`

View File

@ -17,8 +17,8 @@
import { Flags, Command } from '@oclif/core';
import * as ca from '../../utils/common-args';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { applicationIdInfo } from '../../utils/messages';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
import { applicationIdInfo } from '../../utils/messages.js';
export default class DeviceRegisterCmd extends Command {
public static description = stripIndent`
@ -59,7 +59,7 @@ export default class DeviceRegisterCmd extends Command {
const { args: params, flags: options } =
await this.parse(DeviceRegisterCmd);
const { getApplication } = await import('../../utils/sdk');
const { getApplication } = await import('../../utils/sdk.js');
const balena = getBalenaSdk();

View File

@ -16,7 +16,7 @@
*/
import { Args, Command } from '@oclif/core';
import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy';
import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy.js';
export default class DeviceRenameCmd extends Command {
public static description = stripIndent`

View File

@ -16,7 +16,7 @@
*/
import { Flags, Args, Command } from '@oclif/core';
import { getBalenaSdk, getCliUx, stripIndent } from '../../utils/lazy';
import { getBalenaSdk, getCliUx, stripIndent } from '../../utils/lazy.js';
import type {
BalenaSDK,
DeviceWithServiceDetails,
@ -89,7 +89,7 @@ export default class DeviceRestartCmd extends Command {
deviceUuid: string,
serviceNames: string[],
) {
const { ExpectedError, instanceOf } = await import('../../errors');
const { ExpectedError, instanceOf } = await import('../../errors.js');
const { getExpandedProp } = await import('../../utils/pine');
// Get device
@ -156,7 +156,7 @@ export default class DeviceRestartCmd extends Command {
// Note: device.restartApplication throws `BalenaDeviceNotFound: Device not found` if device not online.
// Need to use device.get first to distinguish between non-existant and disconnected devices.
// Remove this workaround when SDK issue resolved: https://github.com/balena-io/balena-sdk/issues/649
const { instanceOf, ExpectedError } = await import('../../errors');
const { instanceOf, ExpectedError } = await import('../../errors.js');
try {
const device = await balena.models.device.get(deviceUuid);
if (!device.is_online) {

View File

@ -16,8 +16,8 @@
*/
import { Args, Command } from '@oclif/core';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import * as cf from '../../utils/common-flags.js';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
export default class DeviceRmCmd extends Command {
public static description = stripIndent`
@ -52,7 +52,7 @@ export default class DeviceRmCmd extends Command {
const { args: params, flags: options } = await this.parse(DeviceRmCmd);
const balena = getBalenaSdk();
const patterns = await import('../../utils/patterns');
const patterns = await import('../../utils/patterns.js');
// Confirm
const uuids = params.uuid.split(',');

View File

@ -16,9 +16,9 @@
*/
import { Args, Command } from '@oclif/core';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { ExpectedError } from '../../errors';
import * as cf from '../../utils/common-flags.js';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
import { ExpectedError } from '../../errors.js';
export default class DeviceShutdownCmd extends Command {
public static description = stripIndent`

View File

@ -16,11 +16,11 @@
*/
import { Flags, Args, Command } from '@oclif/core';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
import {
parseAsInteger,
validateLocalHostnameOrIp,
} from '../../utils/validation';
} from '../../utils/validation.js';
export default class DeviceSSHCmd extends Command {
public static aliases = ['ssh'];
@ -121,12 +121,12 @@ export default class DeviceSSHCmd extends Command {
}
// Remote connection
const { getProxyConfig } = await import('../../utils/helpers');
const { getProxyConfig } = await import('../../utils/helpers.js');
const {
getOnlineTargetDeviceUuid,
checkLoggedIn,
checkNotUsingOfflineMode,
} = await import('../../utils/patterns');
} = await import('../../utils/patterns.js');
const sdk = getBalenaSdk();
const proxyConfig = getProxyConfig();

View File

@ -16,7 +16,7 @@
*/
import { Args, Command } from '@oclif/core';
import { getBalenaSdk, getCliUx, stripIndent } from '../../utils/lazy';
import { getBalenaSdk, getCliUx, stripIndent } from '../../utils/lazy.js';
import type { BalenaSDK } from 'balena-sdk';
export default class DeviceStartServiceCmd extends Command {
@ -70,7 +70,7 @@ export default class DeviceStartServiceCmd extends Command {
deviceUuid: string,
serviceNames: string[],
) {
const { ExpectedError } = await import('../../errors');
const { ExpectedError } = await import('../../errors.js');
const { getExpandedProp } = await import('../../utils/pine');
// Get device

View File

@ -16,7 +16,7 @@
*/
import { Args, Command } from '@oclif/core';
import { getBalenaSdk, getCliUx, stripIndent } from '../../utils/lazy';
import { getBalenaSdk, getCliUx, stripIndent } from '../../utils/lazy.js';
import type { BalenaSDK } from 'balena-sdk';
export default class DeviceStopServiceCmd extends Command {
@ -70,7 +70,7 @@ export default class DeviceStopServiceCmd extends Command {
deviceUuid: string,
serviceNames: string[],
) {
const { ExpectedError } = await import('../../errors');
const { ExpectedError } = await import('../../errors.js');
const { getExpandedProp } = await import('../../utils/pine');
// Get device

View File

@ -16,7 +16,7 @@
*/
import { Args, Command } from '@oclif/core';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
export default class DeviceTrackFleetCmd extends Command {
public static description = stripIndent`

View File

@ -20,9 +20,9 @@ import {
NoPortsDefinedError,
InvalidPortMappingError,
ExpectedError,
} from '../../errors';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { lowercaseIfSlug } from '../../utils/normalization';
} from '../../errors.js';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
import { lowercaseIfSlug } from '../../utils/normalization.js';
import type { Server, Socket } from 'net';
@ -94,7 +94,7 @@ export default class DeviceTunnelCmd extends Command {
public async run() {
const { args: params, flags: options } = await this.parse(DeviceTunnelCmd);
const Logger = await import('../../utils/logger');
const { default: Logger } = await import('../../utils/logger.js');
const logger = Logger.getLogger();
const sdk = getBalenaSdk();
@ -122,7 +122,7 @@ export default class DeviceTunnelCmd extends Command {
}
// Ascertain device uuid
const { getOnlineTargetDeviceUuid } = await import('../../utils/patterns');
const { getOnlineTargetDeviceUuid } = await import('../../utils/patterns.js');
const uuid = await getOnlineTargetDeviceUuid(sdk, params.deviceOrFleet);
logger.logInfo(`Opening a tunnel to ${uuid}...`);

View File

@ -17,11 +17,11 @@
import { Flags, Command } from '@oclif/core';
import type { Interfaces } from '@oclif/core';
import type * as SDK from 'balena-sdk';
import * as _ from 'lodash';
import { ExpectedError } from '../../errors';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
import { applicationIdInfo } from '../../utils/messages';
import _ from 'lodash';
import { ExpectedError } from '../../errors.js';
import * as cf from '../../utils/common-flags.js';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy.js';
import { applicationIdInfo } from '../../utils/messages.js';
type FlagsDef = Interfaces.InferredFlags<typeof EnvListCmd.flags>;
@ -114,7 +114,7 @@ export default class EnvListCmd extends Command {
const variables: EnvironmentVariableInfo[] = [];
const { checkLoggedIn } = await import('../../utils/patterns');
const { checkLoggedIn } = await import('../../utils/patterns.js');
await checkLoggedIn();
@ -187,7 +187,7 @@ export default class EnvListCmd extends Command {
}
if (options.json) {
const { pickAndRename } = await import('../../utils/helpers');
const { pickAndRename } = await import('../../utils/helpers.js');
const mapped = varArray.map((o) => pickAndRename(o, fields));
this.log(JSON.stringify(mapped, null, 4));
} else {

View File

@ -16,8 +16,8 @@
*/
import { Args, Command } from '@oclif/core';
import * as ec from '../../utils/env-common';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { parseAsInteger } from '../../utils/validation';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
import { parseAsInteger } from '../../utils/validation.js';
export default class EnvRenameCmd extends Command {
public static description = stripIndent`
@ -59,7 +59,7 @@ export default class EnvRenameCmd extends Command {
public async run() {
const { args: params, flags: opt } = await this.parse(EnvRenameCmd);
const { checkLoggedIn } = await import('../../utils/patterns');
const { checkLoggedIn } = await import('../../utils/patterns.js');
await checkLoggedIn();

View File

@ -17,8 +17,8 @@
import { Flags, Args, Command } from '@oclif/core';
import * as ec from '../../utils/env-common';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { parseAsInteger } from '../../utils/validation';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
import { parseAsInteger } from '../../utils/validation.js';
export default class EnvRmCmd extends Command {
public static description = stripIndent`
@ -65,11 +65,11 @@ export default class EnvRmCmd extends Command {
public async run() {
const { args: params, flags: opt } = await this.parse(EnvRmCmd);
const { checkLoggedIn } = await import('../../utils/patterns');
const { checkLoggedIn } = await import('../../utils/patterns.js');
await checkLoggedIn();
const { confirm } = await import('../../utils/patterns');
const { confirm } = await import('../../utils/patterns.js');
await confirm(
opt.yes || false,
'Are you sure you want to delete the environment variable?',

View File

@ -17,10 +17,10 @@
import { Args, Command } from '@oclif/core';
import type * as BalenaSdk from 'balena-sdk';
import { ExpectedError } from '../../errors';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { applicationIdInfo } from '../../utils/messages';
import { ExpectedError } from '../../errors.js';
import * as cf from '../../utils/common-flags.js';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
import { applicationIdInfo } from '../../utils/messages.js';
interface FlagsDef {
fleet?: string;
@ -111,7 +111,7 @@ export default class EnvSetCmd extends Command {
);
}
const { checkLoggedIn } = await import('../../utils/patterns');
const { checkLoggedIn } = await import('../../utils/patterns.js');
await checkLoggedIn();
@ -186,7 +186,7 @@ async function resolveFleetSlugs(
fleetOption: string,
) {
const fleetSlugs: string[] = [];
const { getFleetSlug } = await import('../../utils/sdk');
const { getFleetSlug } = await import('../../utils/sdk.js');
for (const appNameOrSlug of fleetOption.split(',')) {
try {
fleetSlugs.push(await getFleetSlug(balena, appNameOrSlug));

View File

@ -16,7 +16,7 @@
*/
import { Flags, Args, Command } from '@oclif/core';
import { stripIndent } from '../../utils/lazy';
import { stripIndent } from '../../utils/lazy.js';
export default class FleetCreateCmd extends Command {
public static description = stripIndent`
@ -71,7 +71,7 @@ export default class FleetCreateCmd extends Command {
const { args: params, flags: options } = await this.parse(FleetCreateCmd);
await (
await import('../../utils/application-create')
await import('../../utils/application-create.js')
).applicationCreateBase('fleet', options, params);
}
}

View File

@ -16,10 +16,10 @@
*/
import { Flags, Command } from '@oclif/core';
import * as cf from '../../utils/common-flags';
import * as cf from '../../utils/common-flags.js';
import * as ca from '../../utils/common-args';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
import { applicationIdInfo } from '../../utils/messages';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy.js';
import { applicationIdInfo } from '../../utils/messages.js';
export default class FleetCmd extends Command {
public static description = stripIndent`
@ -53,7 +53,7 @@ export default class FleetCmd extends Command {
public async run() {
const { args: params, flags: options } = await this.parse(FleetCmd);
const { getApplication } = await import('../../utils/sdk');
const { getApplication } = await import('../../utils/sdk.js');
const balena = getBalenaSdk();
@ -65,7 +65,7 @@ export default class FleetCmd extends Command {
});
if (options.view) {
const open = await import('open');
const { default: open } = await import('open');
const dashboardUrl = balena.models.application.getDashboardUrl(
application.id,
);

View File

@ -16,8 +16,8 @@
*/
import type * as BalenaSdk from 'balena-sdk';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
import * as cf from '../../utils/common-flags.js';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy.js';
import { Command } from '@oclif/core';
interface ExtendedApplication extends ApplicationWithDeviceTypeSlug {

View File

@ -16,7 +16,7 @@
*/
import { Args, Command } from '@oclif/core';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
import { getExpandedProp } from '../../utils/pine';
export default class FleetPinCmd extends Command {

View File

@ -17,8 +17,8 @@
import { Command } from '@oclif/core';
import * as ca from '../../utils/common-args';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { applicationIdInfo } from '../../utils/messages';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
import { applicationIdInfo } from '../../utils/messages.js';
export default class FleetPurgeCmd extends Command {
public static description = stripIndent`
@ -44,7 +44,7 @@ export default class FleetPurgeCmd extends Command {
public async run() {
const { args: params } = await this.parse(FleetPurgeCmd);
const { getApplication } = await import('../../utils/sdk');
const { getApplication } = await import('../../utils/sdk.js');
const balena = getBalenaSdk();

View File

@ -17,8 +17,8 @@
import { Args, Command } from '@oclif/core';
import * as ca from '../../utils/common-args';
import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy';
import { applicationIdInfo } from '../../utils/messages';
import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy.js';
import { applicationIdInfo } from '../../utils/messages.js';
export default class FleetRenameCmd extends Command {
public static description = stripIndent`
@ -51,12 +51,12 @@ export default class FleetRenameCmd extends Command {
const { args: params } = await this.parse(FleetRenameCmd);
const { validateApplicationName } = await import('../../utils/validation');
const { ExpectedError } = await import('../../errors');
const { ExpectedError } = await import('../../errors.js');
const balena = getBalenaSdk();
// Disambiguate target application (if params.params is a number, it could either be an ID or a numerical name)
const { getApplication } = await import('../../utils/sdk');
const { getApplication } = await import('../../utils/sdk.js');
const application = await getApplication(balena, params.fleet, {
$select: ['id', 'app_name', 'slug'],
$expand: {

View File

@ -17,8 +17,8 @@
import { Command } from '@oclif/core';
import * as ca from '../../utils/common-args';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { applicationIdInfo } from '../../utils/messages';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
import { applicationIdInfo } from '../../utils/messages.js';
export default class FleetRestartCmd extends Command {
public static description = stripIndent`
@ -43,7 +43,7 @@ export default class FleetRestartCmd extends Command {
public async run() {
const { args: params } = await this.parse(FleetRestartCmd);
const { getApplication } = await import('../../utils/sdk');
const { getApplication } = await import('../../utils/sdk.js');
const balena = getBalenaSdk();

View File

@ -15,10 +15,10 @@
* limitations under the License.
*/
import * as cf from '../../utils/common-flags';
import * as cf from '../../utils/common-flags.js';
import * as ca from '../../utils/common-args';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { applicationIdInfo } from '../../utils/messages';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
import { applicationIdInfo } from '../../utils/messages.js';
import { Command } from '@oclif/core';
export default class FleetRmCmd extends Command {
@ -51,8 +51,8 @@ export default class FleetRmCmd extends Command {
public async run() {
const { args: params, flags: options } = await this.parse(FleetRmCmd);
const { confirm } = await import('../../utils/patterns');
const { getApplication } = await import('../../utils/sdk');
const { confirm } = await import('../../utils/patterns.js');
const { getApplication } = await import('../../utils/sdk.js');
const balena = getBalenaSdk();
// Confirm

View File

@ -16,7 +16,7 @@
*/
import { Args, Command } from '@oclif/core';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
export default class FleetTrackLatestCmd extends Command {
public static description = stripIndent`

View File

@ -16,7 +16,7 @@
*/
import { Args, Command } from '@oclif/core';
import { stripIndent } from '../../utils/lazy';
import { stripIndent } from '../../utils/lazy.js';
// 'Internal' commands are called during the execution of other commands.
// `osinit` is called during `os initialize`
@ -56,7 +56,7 @@ export default class OsinitCmd extends Command {
const config = JSON.parse(params.config);
const { getManifest, osProgressHandler } = await import(
'../../utils/helpers'
'../../utils/helpers.js'
);
const manifest = await getManifest(params.image, params.type);

View File

@ -16,10 +16,10 @@
*/
import { Args, Flags, Command } from '@oclif/core';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { applicationIdInfo } from '../../utils/messages';
import { parseAsLocalHostnameOrIp } from '../../utils/validation';
import * as cf from '../../utils/common-flags.js';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
import { applicationIdInfo } from '../../utils/messages.js';
import { parseAsLocalHostnameOrIp } from '../../utils/validation.js';
export default class JoinCmd extends Command {
public static description = stripIndent`
@ -73,9 +73,9 @@ export default class JoinCmd extends Command {
public async run() {
const { args: params, flags: options } = await this.parse(JoinCmd);
const promote = await import('../../utils/promote');
const promote = await import('../../utils/promote.js');
const sdk = getBalenaSdk();
const Logger = await import('../../utils/logger');
const { default: Logger } = await import('../../utils/logger.js');
const logger = Logger.getLogger();
return promote.join(
logger,

View File

@ -16,8 +16,8 @@
*/
import { Args, Command } from '@oclif/core';
import { stripIndent } from '../../utils/lazy';
import { parseAsLocalHostnameOrIp } from '../../utils/validation';
import { stripIndent } from '../../utils/lazy.js';
import { parseAsLocalHostnameOrIp } from '../../utils/validation.js';
export default class LeaveCmd extends Command {
public static description = stripIndent`
@ -54,8 +54,8 @@ export default class LeaveCmd extends Command {
public async run() {
const { args: params } = await this.parse(LeaveCmd);
const promote = await import('../../utils/promote');
const Logger = await import('../../utils/logger');
const promote = await import('../../utils/promote.js');
const { default: Logger } = await import('../../utils/logger.js');
const logger = Logger.getLogger();
return promote.leave(logger, params.deviceIpOrHostname);
}

View File

@ -16,7 +16,7 @@
*/
import { Args, Command } from '@oclif/core';
import { stripIndent } from '../../utils/lazy';
import { stripIndent } from '../../utils/lazy.js';
export default class LocalConfigureCmd extends Command {
public static description = stripIndent`
@ -44,8 +44,8 @@ export default class LocalConfigureCmd extends Command {
const { args: params } = await this.parse(LocalConfigureCmd);
const reconfix = await import('reconfix');
const { denyMount, safeUmount } = await import('../../utils/umount');
const Logger = await import('../../utils/logger');
const { denyMount, safeUmount } = await import('../../utils/umount.js');
const { default: Logger } = await import('../../utils/logger.js');
const logger = Logger.getLogger();

View File

@ -17,9 +17,9 @@
import { Args, Command } from '@oclif/core';
import type { BlockDevice } from 'etcher-sdk/build/source-destination';
import { ExpectedError } from '../../errors';
import * as cf from '../../utils/common-flags';
import { getChalk, getVisuals, stripIndent } from '../../utils/lazy';
import { ExpectedError } from '../../errors.js';
import * as cf from '../../utils/common-flags.js';
import { getChalk, getVisuals, stripIndent } from '../../utils/lazy.js';
export default class LocalFlashCmd extends Command {
public static description = stripIndent`
@ -75,7 +75,7 @@ export default class LocalFlashCmd extends Command {
const drive = await this.getDrive(options);
const { confirm } = await import('../../utils/patterns');
const { confirm } = await import('../../utils/patterns.js');
await confirm(
options.yes,
'This will erase the selected drive. Are you sure?',

View File

@ -16,8 +16,8 @@
*/
import { Flags, Args, Command } from '@oclif/core';
import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy';
import { ExpectedError } from '../../errors';
import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy.js';
import { ExpectedError } from '../../errors.js';
import type { WhoamiResult } from 'balena-sdk';
interface FlagsDef {
@ -117,7 +117,7 @@ export default class LoginCmd extends Command {
const { flags: options, args: params } = await this.parse(LoginCmd);
const balena = getBalenaSdk();
const messages = await import('../../utils/messages');
const messages = await import('../../utils/messages.js');
const balenaUrl = await balena.settings.get('balenaUrl');
// Consolidate user/email options
@ -196,7 +196,7 @@ ${messages.reachingOut}`);
}
// Credentials
else if (loginOptions.credentials) {
const patterns = await import('../../utils/patterns');
const patterns = await import('../../utils/patterns.js');
return patterns.authenticate(loginOptions);
}
// Web
@ -205,11 +205,11 @@ ${messages.reachingOut}`);
await auth.login({ port: loginOptions.port });
return;
} else {
const patterns = await import('../../utils/patterns');
const patterns = await import('../../utils/patterns.js');
// User had not selected login preference, prompt interactively
const loginType = await patterns.askLoginType();
if (loginType === 'register') {
const open = await import('open');
const { default: open } = await import('open');
const signupUrl = `https://dashboard.${balenaUrl}/signup`;
await open(signupUrl, { wait: false });
throw new ExpectedError(`Please sign up at ${signupUrl}`);

View File

@ -16,7 +16,7 @@
*/
import { Command } from '@oclif/core';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
export default class LogoutCmd extends Command {
public static description = stripIndent`

View File

@ -16,7 +16,7 @@
*/
import { Command } from '@oclif/core';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy.js';
export default class OrganizationListCmd extends Command {
public static aliases = ['orgs'];
@ -34,7 +34,7 @@ export default class OrganizationListCmd extends Command {
public async run() {
await this.parse(OrganizationListCmd);
const { getOwnOrganizations } = await import('../../utils/sdk');
const { getOwnOrganizations } = await import('../../utils/sdk.js');
// Get organizations
const organizations = await getOwnOrganizations(getBalenaSdk(), {

View File

@ -16,8 +16,8 @@
*/
import { Flags, Args, Command } from '@oclif/core';
import { getCliForm, stripIndent } from '../../utils/lazy';
import * as _ from 'lodash';
import { getCliForm, stripIndent } from '../../utils/lazy.js';
import _ from 'lodash';
import type { DeviceTypeJson } from 'balena-sdk';
export default class OsBuildConfigCmd extends Command {
@ -77,7 +77,7 @@ export default class OsBuildConfigCmd extends Command {
async buildConfig(image: string, deviceTypeSlug: string, advanced: boolean) {
advanced = advanced || false;
const { getManifest } = await import('../../utils/helpers');
const { getManifest } = await import('../../utils/helpers.js');
const deviceTypeManifest = await getManifest(image, deviceTypeSlug);
return this.buildConfigForDeviceType(deviceTypeManifest, advanced);
@ -98,7 +98,7 @@ export default class OsBuildConfigCmd extends Command {
});
if (advancedGroup != null) {
const { getGroupDefaults } = await import('../../utils/helpers');
const { getGroupDefaults } = await import('../../utils/helpers.js');
override = getGroupDefaults(advancedGroup);
}
}

View File

@ -18,15 +18,15 @@
import { Flags, Args, Command } from '@oclif/core';
import type { Interfaces } from '@oclif/core';
import type * as BalenaSdk from 'balena-sdk';
import * as _ from 'lodash';
import { ExpectedError } from '../../errors';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy';
import _ from 'lodash';
import { ExpectedError } from '../../errors.js';
import * as cf from '../../utils/common-flags.js';
import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy.js';
import {
applicationIdInfo,
devModeInfo,
secureBootInfo,
} from '../../utils/messages';
} from '../../utils/messages.js';
const CONNECTIONS_FOLDER = '/system-connections';
@ -165,10 +165,10 @@ export default class OsConfigureCmd extends Command {
const devInit = await import('balena-device-init');
const { promises: fs } = await import('fs');
const { generateDeviceConfig, generateApplicationConfig } = await import(
'../../utils/config'
'../../utils/config.js'
);
const helpers = await import('../../utils/helpers');
const { getApplication } = await import('../../utils/sdk');
const helpers = await import('../../utils/helpers.js');
const { getApplication } = await import('../../utils/sdk.js');
let app: ApplicationWithDeviceTypeSlug | undefined;
let device;
@ -200,13 +200,13 @@ export default class OsConfigureCmd extends Command {
deviceTypeSlug,
);
let configJson: import('../../utils/config').ImgConfig | undefined;
let configJson: import('../../utils/config.js').ImgConfig | undefined;
if (options.config) {
const rawConfig = await fs.readFile(options.config, 'utf8');
configJson = JSON.parse(rawConfig);
}
const { normalizeOsVersion } = await import('../../utils/normalization');
const { normalizeOsVersion } = await import('../../utils/normalization.js');
const osVersion = normalizeOsVersion(
options.version ||
(await getOsVersionFromImage(
@ -216,11 +216,11 @@ export default class OsConfigureCmd extends Command {
)),
);
const { validateDevOptionAndWarn } = await import('../../utils/config');
const { validateDevOptionAndWarn } = await import('../../utils/config.js');
await validateDevOptionAndWarn(options.dev, osVersion);
const { validateSecureBootOptionAndWarn } = await import(
'../../utils/config'
'../../utils/config.js'
);
await validateSecureBootOptionAndWarn(
options.secureBoot,
@ -316,7 +316,7 @@ async function validateOptions(options: FlagsDef) {
);
}
const { checkLoggedIn } = await import('../../utils/patterns');
const { checkLoggedIn } = await import('../../utils/patterns.js');
await checkLoggedIn();
}
@ -360,7 +360,7 @@ async function checkDeviceTypeCompatibility(
},
) {
if (options['device-type']) {
const helpers = await import('../../utils/helpers');
const helpers = await import('../../utils/helpers.js');
if (
!(await helpers.areDeviceTypesCompatible(
app.is_for__device_type[0].slug,
@ -391,7 +391,7 @@ async function checkDeviceTypeCompatibility(
async function askQuestionsForDeviceType(
deviceType: BalenaSdk.DeviceTypeJson.DeviceType,
options: FlagsDef,
configJson?: import('../../utils/config').ImgConfig,
configJson?: import('../../utils/config.js').ImgConfig,
): Promise<Answers> {
const answerSources: any[] = [
{
@ -414,7 +414,7 @@ async function askQuestionsForDeviceType(
isGroup: true,
});
if (!_.isEmpty(advancedGroup)) {
const helpers = await import('../../utils/helpers');
const helpers = await import('../../utils/helpers.js');
answerSources.push(helpers.getGroupDefaults(advancedGroup));
}
}

View File

@ -16,7 +16,7 @@
*/
import { Flags, Args, Command } from '@oclif/core';
import { stripIndent } from '../../utils/lazy';
import { stripIndent } from '../../utils/lazy.js';
export default class OsDownloadCmd extends Command {
public static description = stripIndent`
@ -87,11 +87,11 @@ export default class OsDownloadCmd extends Command {
const { isESR } = await import('../../utils/image-manager');
if (options.version === 'menu-esr' || isESR(options.version)) {
try {
const { checkLoggedIn } = await import('../../utils/patterns');
const { checkLoggedIn } = await import('../../utils/patterns.js');
await checkLoggedIn();
} catch (e) {
const { ExpectedError, NotLoggedInError } = await import(
'../../errors'
'../../errors.js'
);
if (e instanceof NotLoggedInError) {
throw new ExpectedError(stripIndent`

View File

@ -16,8 +16,8 @@
*/
import { Args, Command } from '@oclif/core';
import * as cf from '../../utils/common-flags';
import { getCliForm, stripIndent } from '../../utils/lazy';
import * as cf from '../../utils/common-flags.js';
import { getCliForm, stripIndent } from '../../utils/lazy.js';
const INIT_WARNING_MESSAGE = `
@ -58,7 +58,7 @@ export default class OsInitializeCmd extends Command {
public async run() {
const { args: params, flags: options } = await this.parse(OsInitializeCmd);
const { getManifest, sudo } = await import('../../utils/helpers');
const { getManifest, sudo } = await import('../../utils/helpers.js');
console.info(`Initializing device ${INIT_WARNING_MESSAGE}`);
@ -71,13 +71,13 @@ export default class OsInitializeCmd extends Command {
});
if (answers.drive != null) {
const { confirm } = await import('../../utils/patterns');
const { confirm } = await import('../../utils/patterns.js');
await confirm(
options.yes,
`This will erase ${answers.drive}. Are you sure?`,
`Going to erase ${answers.drive}.`,
);
const { safeUmount } = await import('../../utils/umount');
const { safeUmount } = await import('../../utils/umount.js');
await safeUmount(answers.drive);
}
@ -90,7 +90,7 @@ export default class OsInitializeCmd extends Command {
]);
if (answers.drive != null) {
const { safeUmount } = await import('../../utils/umount');
const { safeUmount } = await import('../../utils/umount.js');
await safeUmount(answers.drive);
console.info(`You can safely remove ${answers.drive} now`);
}

View File

@ -16,7 +16,7 @@
*/
import { Flags, Args, Command } from '@oclif/core';
import { stripIndent } from '../../utils/lazy';
import { stripIndent } from '../../utils/lazy.js';
export default class OsVersionsCmd extends Command {
public static description = stripIndent`
@ -53,7 +53,7 @@ export default class OsVersionsCmd extends Command {
const { args: params, flags: options } = await this.parse(OsVersionsCmd);
if (options['include-draft']) {
const { warnify } = await import('../../utils/messages');
const { warnify } = await import('../../utils/messages.js');
console.error(
warnify(stripIndent`
Using pre-release balenaOS versions is only supported for OS updates

View File

@ -15,19 +15,19 @@
* limitations under the License.
*/
import { ExpectedError } from '../../errors';
import * as cf from '../../utils/common-flags';
import { ExpectedError } from '../../errors.js';
import * as cf from '../../utils/common-flags.js';
import {
getBalenaSdk,
getCliForm,
getVisuals,
stripIndent,
} from '../../utils/lazy';
import { applicationIdInfo } from '../../utils/messages';
import { dockerConnectionCliFlags } from '../../utils/docker';
import { parseAsInteger } from '../../utils/validation';
} from '../../utils/lazy.js';
import { applicationIdInfo } from '../../utils/messages.js';
import { dockerConnectionCliFlags } from '../../utils/docker.js';
import { parseAsInteger } from '../../utils/validation.js';
import { Flags, Args, Command } from '@oclif/core';
import * as _ from 'lodash';
import _ from 'lodash';
import type {
Application,
BalenaSDK,
@ -142,7 +142,7 @@ Can be repeated to add multiple certificates.\
const balenaPreload = await import('balena-preload');
const visuals = getVisuals();
const nodeCleanup = await import('node-cleanup');
const { instanceOf } = await import('../../errors');
const { instanceOf } = await import('../../errors.js');
// Check image file exists
try {
@ -162,8 +162,13 @@ Can be repeated to add multiple certificates.\
);
}
// Verify that image is not enabled for secure boot. First, confirm it
// is a secure boot image with an /opt/*.sig file in the rootA partition.
// Verify that image is not enabled for secure boot. First, confirm it is
// a secure boot image with a .sig file in the /opt directory of the rootA
// partition. For example, below are contents for generic-amd64 device type:
// $ ls -l opt
// total 864696
// -rw-r--r-- 1 root root 2378170368 Mar 26 09:14 balena-image-generic-amd64.balenaos-img
// -rw-r--r-- 1 root root 512 Mar 9 2018 balena-image-generic-amd64.balenaos-img.sig
const { explorePartition, BalenaPartition } = await import(
'../../utils/image-contents'
);
@ -187,7 +192,7 @@ Can be repeated to add multiple certificates.\
// Next verify that config.json enables secureboot.
if (isSecureBoot) {
const { read } = await import('balena-config-json');
const config = await read(params.image, '');
const config = await read(params.image);
if (config.installer?.secureboot === true) {
throw new ExpectedError("Can't preload image with secure boot enabled");
}
@ -254,7 +259,7 @@ Can be repeated to add multiple certificates.\
}
// Get a configured dockerode instance
const dockerUtils = await import('../../utils/docker');
const dockerUtils = await import('../../utils/docker.js');
const docker = await dockerUtils.getDocker(options);
const preloader = new balenaPreload.Preloader(
undefined,
@ -508,7 +513,7 @@ Would you like to disable automatic updates for this fleet now?\
}
async getAppWithReleases(balenaSdk: BalenaSDK, slug: string) {
const { getApplication } = await import('../../utils/sdk');
const { getApplication } = await import('../../utils/sdk.js');
return await getApplication(balenaSdk, slug, {
$expand: this.applicationExpandOptions,

View File

@ -17,16 +17,16 @@
import { Flags, Args, Command } from '@oclif/core';
import type { Interfaces } from '@oclif/core';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { dockerignoreHelp, registrySecretsHelp } from '../../utils/messages';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
import { dockerignoreHelp, registrySecretsHelp } from '../../utils/messages.js';
import type { BalenaSDK } from 'balena-sdk';
import { ExpectedError, instanceOf } from '../../errors';
import type { RegistrySecrets } from '@balena/compose/dist/multibuild';
import { lowercaseIfSlug } from '../../utils/normalization';
import { ExpectedError, instanceOf } from '../../errors.js';
import type { RegistrySecrets } from '@balena/compose/dist/multibuild/index.js';
import { lowercaseIfSlug } from '../../utils/normalization.js';
import {
applyReleaseTagKeysAndValues,
parseReleaseTagKeysAndValues,
} from '../../utils/compose_ts';
} from '../../utils/compose_ts.js';
enum BuildTarget {
Cloud,
@ -224,13 +224,13 @@ export default class PushCmd extends Command {
public async run() {
const { args: params, flags: options } = await this.parse(PushCmd);
const Logger = await import('../../utils/logger');
const { default: Logger } = await import('../../utils/logger.js');
const logger = Logger.getLogger();
logger.logDebug(`Using build source directory: ${options.source} `);
const sdk = getBalenaSdk();
const { validateProjectDirectory } = await import('../../utils/compose_ts');
const { validateProjectDirectory } = await import('../../utils/compose_ts.js');
const { dockerfilePath, registrySecrets } = await validateProjectDirectory(
sdk,
{
@ -274,7 +274,7 @@ export default class PushCmd extends Command {
registrySecrets: RegistrySecrets,
) {
const remote = await import('../../utils/remote-build');
const { getApplication } = await import('../../utils/sdk');
const { getApplication } = await import('../../utils/sdk.js');
// Check for invalid options
const localOnlyOptions: Array<keyof FlagsDef> = [
@ -293,7 +293,7 @@ export default class PushCmd extends Command {
options['release-tag'] ?? [],
);
const { checkLoggedIn } = await import('../../utils/patterns');
const { checkLoggedIn } = await import('../../utils/patterns.js');
await checkLoggedIn();
const [token, baseUrl] = await Promise.all([
@ -375,7 +375,7 @@ export default class PushCmd extends Command {
convertEol: !options['noconvert-eol'],
});
} catch (e) {
const { BuildError } = await import('../../utils/device/errors');
const { BuildError } = await import('../../utils/device/errors.js');
if (instanceOf(e, BuildError)) {
throw new ExpectedError(e.toString());
} else {

View File

@ -17,7 +17,7 @@
import { Command } from '@oclif/core';
import { commitOrIdArg } from '.';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
export default class ReleaseFinalizeCmd extends Command {
public static description = stripIndent`

View File

@ -16,12 +16,12 @@
*/
import { Flags, Args, type Interfaces, Command } from '@oclif/core';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
import * as cf from '../../utils/common-flags.js';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy.js';
import type * as BalenaSdk from 'balena-sdk';
import * as yaml from 'js-yaml';
import { tryAsInteger } from '../../utils/validation';
import { jsonInfo } from '../../utils/messages';
import { tryAsInteger } from '../../utils/validation.js';
import { jsonInfo } from '../../utils/messages.js';
export const commitOrIdArg = Args.custom({
parse: tryAsInteger,

View File

@ -17,7 +17,7 @@
import { Command } from '@oclif/core';
import { commitOrIdArg } from '.';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
export default class ReleaseInvalidateCmd extends Command {
public static description = stripIndent`

View File

@ -16,11 +16,11 @@
*/
import { Args, Command } from '@oclif/core';
import * as cf from '../../utils/common-flags';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy';
import { applicationNameNote } from '../../utils/messages';
import * as cf from '../../utils/common-flags.js';
import { getBalenaSdk, getVisuals, stripIndent } from '../../utils/lazy.js';
import { applicationNameNote } from '../../utils/messages.js';
import type * as BalenaSdk from 'balena-sdk';
import { jsonInfo } from '../../utils/messages';
import { jsonInfo } from '../../utils/messages.js';
export default class ReleaseListCmd extends Command {
public static aliases = ['releases'];
@ -66,7 +66,7 @@ export default class ReleaseListCmd extends Command {
] satisfies BalenaSdk.PineOptions<BalenaSdk.Release>['$select'];
const balena = getBalenaSdk();
const { getFleetSlug } = await import('../../utils/sdk');
const { getFleetSlug } = await import('../../utils/sdk.js');
const releases = await balena.models.release.getAllByApplication(
await getFleetSlug(balena, params.fleet),

View File

@ -17,7 +17,7 @@
import { Command } from '@oclif/core';
import { commitOrIdArg } from '.';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
export default class ReleaseValidateCmd extends Command {
public static description = stripIndent`

View File

@ -16,7 +16,7 @@
*/
import { Command } from '@oclif/core';
import { getBalenaSdk, stripIndent } from '../../utils/lazy';
import { getBalenaSdk, stripIndent } from '../../utils/lazy.js';
export default class SettingsCmd extends Command {
public static description = stripIndent`

Some files were not shown because too many files have changed in this diff Show More