@lakutata/cli 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +378 -309
- package/README.zh-CN.md +356 -0
- package/dist/esm/controllers/WorkspaceController.js +5 -3
- package/dist/esm/dtos/AddPackageDTO.js +1 -1
- package/dist/esm/dtos/MigrationDTO.js +1 -1
- package/dist/esm/lib/AddPackage.js +35 -22
- package/dist/esm/lib/Migration.js +2 -2
- package/dist/esm/lib/Output.js +1 -1
- package/dist/esm/lib/Processes.js +62 -0
- package/dist/esm/lib/ProjectCreator.js +25 -15
- package/dist/esm/lib/Registry.js +7 -0
- package/dist/esm/lib/TemplateFeatures.js +9 -1
- package/dist/esm/lib/native/NativeProject.js +16 -5
- package/dist/esm/lib/workspace/Run.js +9 -5
- package/dist/esm/lib/workspace/Version.js +24 -8
- package/dist/esm/lib/workspace/Workspace.js +33 -7
- package/dist/esm/locales/zh-CN.json +4 -4
- package/dist/esm/locales/zh-TW.json +4 -4
- package/package.json +28 -5
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# @lakutata/cli
|
|
2
2
|
|
|
3
|
+
English | [中文](README.zh-CN.md)
|
|
4
|
+
|
|
3
5
|
The command line tool of the [lakutata](https://github.com/lakutata/lakutata) framework.
|
|
4
6
|
|
|
5
7
|
```bash
|
|
@@ -12,159 +14,190 @@ lakutata create --name my-app
|
|
|
12
14
|
|
|
13
15
|
### `lakutata create`
|
|
14
16
|
|
|
15
|
-
Create a project from a template. The options are given on the command line
|
|
16
|
-
and the project
|
|
17
|
+
Create a project from a template. The options are given on the command line. In a terminal, the tool asks for the
|
|
18
|
+
name when it is missing, offers the features of the template, and creates the project once you confirm (`--yes` skips
|
|
19
|
+
both the features and the confirmation).
|
|
17
20
|
|
|
18
21
|
| Option | |
|
|
19
22
|
|---|---|
|
|
20
23
|
| `--name <name>` | the name of the application (required) |
|
|
21
|
-
| `--id <id>` | the ID of the application (a package name), its name in lower case
|
|
22
|
-
| `--template <template>` | the template
|
|
23
|
-
| `--path <directory>` | the directory the project directory is created
|
|
24
|
-
| `--init` | create the project in the directory itself
|
|
25
|
-
| `--description`, `--author`, `--license` |
|
|
26
|
-
| `--with <features>` | the optional features of the template
|
|
27
|
-
| `--package-manager <npm\|pnpm\|yarn\|none>` | the package manager
|
|
24
|
+
| `--id <id>` | the ID of the application (a package name), by default its name in lower case |
|
|
25
|
+
| `--template <template>` | the template (`default` when it is not given): an official template (listed by `lakutata templates`), `npm:<package>[@<version>]`, `github:<owner>/<repo>[#<ref>]` or a directory |
|
|
26
|
+
| `--path <directory>` | the directory in which the project directory is created, by default the current one |
|
|
27
|
+
| `--init` | create the project in the `--path` directory itself, which must exist and may hold files: the files it already has are kept (a warning lists those that the template also has, to merge by hand), and only the files the tool writes are filled with the information of the project |
|
|
28
|
+
| `--description`, `--author`, `--license` | information about the application |
|
|
29
|
+
| `--with <features>` | the optional features of the template to enable, separated by commas (listed by `lakutata templates`): `i18n`, `installer`. In a terminal, without `--with` or `--yes`, you choose them from a list |
|
|
30
|
+
| `--package-manager <npm\|pnpm\|yarn\|none>` | the package manager that installs the dependencies (`none` installs nothing): npm by default, or pnpm or yarn when one of them started the tool |
|
|
28
31
|
| `--no-git` | do not initialize a git repository |
|
|
29
|
-
| `--yes` | create the project without confirmation |
|
|
32
|
+
| `--yes` | create the project without asking for the features or for a confirmation |
|
|
30
33
|
|
|
31
34
|
```bash
|
|
32
35
|
lakutata create --name my-service --template service --package-manager pnpm --yes
|
|
33
36
|
lakutata create --name my-service --template service --with i18n --yes
|
|
34
37
|
```
|
|
35
38
|
|
|
36
|
-
|
|
37
|
-
(`lakutata/com/i18n`), in `src/locales` (`en.json`, `zh-CN.json`)
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
Every official template has the `i18n` feature: the messages of the application in several languages
|
|
40
|
+
(`lakutata/com/i18n`), in `src/locales` (`en.json`, `zh-CN.json`) and bundled with the code. Each request is answered in
|
|
41
|
+
its own language, including its validation errors (command line tools and Electron applications use the language of the
|
|
42
|
+
environment). The feature also adds the `i18n:check` and `i18n:types` scripts. The `cli`, `service` and `web-*`
|
|
43
|
+
templates also have the `installer` feature: the `lakutata.installer` configuration of the application and the scripts
|
|
44
|
+
that make its installers (on the machine, and for Linux in Docker), and, in the `service` and `web-*` templates, a
|
|
45
|
+
system service.
|
|
40
46
|
|
|
41
47
|
### `lakutata templates`
|
|
42
48
|
|
|
43
|
-
List the official templates. They are npm packages (`@lakutata/template-<name>`) listed by the catalog package
|
|
44
|
-
`@lakutata/templates
|
|
45
|
-
dependencies)
|
|
49
|
+
List the official templates. They are npm packages (`@lakutata/template-<name>`), listed by the catalog package
|
|
50
|
+
`@lakutata/templates` and downloaded from the user's npm registry (a mirror such as npmmirror works, as it does for the
|
|
51
|
+
dependencies), so no access to GitHub is needed. The catalog is cached for a day (`--refresh` fetches it again).
|
|
46
52
|
|
|
47
|
-
The
|
|
48
|
-
|
|
53
|
+
The tool uses the newest release of an official template within its own major version. Downloaded templates are
|
|
54
|
+
cached: when the registry cannot be reached, the newest cached release of that major version is used, and without one
|
|
55
|
+
the command fails.
|
|
49
56
|
|
|
50
|
-
A template package
|
|
51
|
-
|
|
52
|
-
with the information of the project: `{$APP_NAME}`, `{$APP_ID}`, `{$APP_DESC}`, `{$APP_AUTHOR}`,
|
|
53
|
-
`{$LAKUTATA_VERSION}` (the version of the framework).
|
|
57
|
+
A template package keeps its files in its `template/` directory. npm packages cannot hold some files under their real
|
|
58
|
+
names, so `_gitignore`, `_npmrc`… are renamed `.gitignore`, `.npmrc`… when the project is created. The text files are
|
|
59
|
+
filled with the information of the project: `{$APP_NAME}`, `{$APP_ID}`, `{$APP_DESC}`, `{$APP_AUTHOR}`,
|
|
60
|
+
`{$APP_LICENSE}` and `{$LAKUTATA_VERSION}` (the version of the framework).
|
|
54
61
|
|
|
55
|
-
A template
|
|
62
|
+
A template can have optional features, which `lakutata create --with <features>` enables (or which the user chooses in
|
|
63
|
+
a terminal):
|
|
56
64
|
|
|
57
|
-
-
|
|
65
|
+
- the `package.json` of the template package declares them, with their names and descriptions:
|
|
58
66
|
`"lakutata": {"template": "default", "features": {"i18n": "The messages in several languages"}}`;
|
|
59
|
-
- the files of a feature are in `features/<name>/`, beside `template/` (published with it, in the `files` of the
|
|
60
|
-
package)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
67
|
+
- the files of a feature are in `features/<name>/`, beside `template/` (and published with it, in the `files` of the
|
|
68
|
+
package). They are added to the project when the feature is enabled: a JSON file that the project already has is
|
|
69
|
+
merged into it (its objects merged by key, such as the scripts of `package.json` and the options of `tsconfig.json`,
|
|
70
|
+
and its arrays replaced), and any other file replaces the one of the template;
|
|
71
|
+
- the files of the template can hold blocks for a feature: the lines between `//@if <feature>` and `//@end` (or
|
|
72
|
+
`//@else`; `//@if !<feature>` for when the feature is not enabled) are kept when the feature is enabled and removed
|
|
73
|
+
otherwise, and the marker lines are always removed. The markers are written as comments of the file's language:
|
|
74
|
+
`//@if i18n`, `#@if i18n`, `<!--@if i18n-->`, `/*@if i18n*/`.
|
|
66
75
|
|
|
67
76
|
### `lakutata info`
|
|
68
77
|
|
|
69
|
-
Show the versions of the tool
|
|
70
|
-
project
|
|
78
|
+
Show the versions of the tool and of the framework (with their latest versions), of Node.js, and the version of the
|
|
79
|
+
framework that the project in the current directory uses.
|
|
71
80
|
|
|
72
81
|
### `lakutata clean [paths...]`
|
|
73
82
|
|
|
74
|
-
Remove paths of the package
|
|
75
|
-
`lakutata clean build dist`. Without paths, the output directories of its `tsconfig.json`
|
|
76
|
-
`declarationDir` when
|
|
77
|
-
path is skipped
|
|
78
|
-
|
|
83
|
+
Remove paths of the package in the current directory, on every platform (like `rm -rf`, without `shx` or `rimraf`):
|
|
84
|
+
`lakutata clean build dist`. Without paths, it removes the output directories of its `tsconfig.json` (`outDir`, and
|
|
85
|
+
`declarationDir` when there is one, following the configurations it extends): `"clean": "lakutata clean"`. A missing
|
|
86
|
+
path is skipped. Paths outside the package, the package itself, `src`, `node_modules`, `.git` and `package.json` are
|
|
87
|
+
never removed. In a workspace, `lakutata run clean` runs the `clean` script of each package.
|
|
79
88
|
|
|
80
89
|
## Workspaces
|
|
81
90
|
|
|
82
|
-
|
|
83
|
-
`package.json
|
|
84
|
-
|
|
91
|
+
Projects made of several packages (`app`, `ui`, `proxy`…) are npm workspaces. The workspace of a directory is the
|
|
92
|
+
nearest one, from that directory up, whose `package.json` has a `workspaces` field (a list of patterns, or
|
|
93
|
+
`{"packages": [...]}`), or whose `package.json` is next to a `pnpm-workspace.yaml` (its `packages:` list). The patterns
|
|
94
|
+
match directories (`*` within one name, `**` any number of directories, `!` leaves one out), and the ones holding a
|
|
95
|
+
`package.json` with a name are the packages. The tool builds and versions their packages: it covers the part of lerna
|
|
96
|
+
that these projects use, without lerna.
|
|
85
97
|
|
|
86
98
|
### `lakutata run <script>`
|
|
87
99
|
|
|
88
|
-
Run a script in
|
|
89
|
-
|
|
100
|
+
Run a script in every package that has it, in the order of their dependencies (in `dependencies`, `devDependencies`,
|
|
101
|
+
`peerDependencies` and `optionalDependencies`): a package starts once the packages it depends on, directly or not, have
|
|
102
|
+
finished, and packages that do not depend on each other run at the same time. The scripts run with the package manager
|
|
103
|
+
of the project: the `packageManager` field of the root `package.json`, else the files at the root (`pnpm-lock.yaml` or
|
|
104
|
+
`pnpm-workspace.yaml` for pnpm, `yarn.lock`, `package-lock.json`); npm by default. Each line of output starts with the
|
|
105
|
+
name of its package. The scripts take no extra arguments. When no package has the script, the command says so and
|
|
106
|
+
succeeds.
|
|
90
107
|
|
|
91
108
|
| Option | |
|
|
92
109
|
|---|---|
|
|
93
|
-
| `--concurrency <n>` | how many packages run at a time, the number of
|
|
94
|
-
| `--parallel` | run all the packages at once, without waiting for their dependencies:
|
|
95
|
-
| `--no-bail` |
|
|
96
|
-
| `--scope <names...>` | the packages
|
|
110
|
+
| `--concurrency <n>` | how many packages run at a time, by default the number of processors |
|
|
111
|
+
| `--parallel` | run all the packages at once, without waiting for their dependencies: for scripts that keep running (`lakutata run dev --parallel`) |
|
|
112
|
+
| `--no-bail` | go on after a failure: the packages that do not depend on a failed one still run (by default, no package starts after the first failure, and the ones running finish) |
|
|
113
|
+
| `--scope <names...>` | only the packages with these names (`*` is a wildcard); the packages they depend on are neither run nor waited for, and a scope matching no package is an error |
|
|
97
114
|
|
|
98
115
|
### `lakutata version <bump>`
|
|
99
116
|
|
|
100
|
-
Give
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
117
|
+
Give every package the next version (`major`, `minor`, `patch`, `premajor`, `preminor`, `prepatch`, `prerelease`, or a
|
|
118
|
+
version; `--preid <id>` names the prerelease of the `pre…` bumps), the private packages and the ones without a version
|
|
119
|
+
included, and update the dependencies between them, in the packages and the root `package.json` (`^0.0.16` becomes
|
|
120
|
+
`^0.0.17`, and so do `~`, `>=`, `=` and `workspace:^` ranges, while `*`, `workspace:*` and `file:` are kept). With `0.x`
|
|
121
|
+
versions this matters, as a range matches only its own version. The command also updates `package-lock.json` or
|
|
122
|
+
`pnpm-lock.yaml`, without which `npm ci` would fail. A `yarn.lock` is not updated (the command warns you to run
|
|
123
|
+
`yarn install`), and a failed update is only a warning. The version of the workspace is the `version` of `lerna.json`
|
|
124
|
+
when that file gives one, else that of the root `package.json`, else the highest version of the packages, a prerelease
|
|
125
|
+
included (`0.0.0` when none has one), and the new version is written back there. `--git` commits the files of the
|
|
126
|
+
version, and only them, with the message `v<version>`, and tags the commit `v<version>` (a lightweight tag, not pushed);
|
|
127
|
+
the repository and the tag are checked before a file is changed. The command asks for a confirmation in a terminal only,
|
|
128
|
+
and `--yes` gives the version without asking.
|
|
105
129
|
|
|
106
130
|
### `lakutata add <name>`
|
|
107
131
|
|
|
108
|
-
Add a package to the workspace
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
132
|
+
Add a package to the workspace, in its directory of packages (without its scope): the directory of the first pattern of
|
|
133
|
+
the workspace of the form `<directory>/*`, such as `apps/*`, or `packages/*` when there is one, so that the other
|
|
134
|
+
commands see the package; a workspace without such a pattern (its packages named one by one, or `packages/**`) is
|
|
135
|
+
refused. Its version is that of the workspace (`lerna.json`, else the root `package.json`, else the highest version of
|
|
136
|
+
the packages; `0.0.1` without one, or with the independent versions of lerna). It is private (remove `"private": true`
|
|
137
|
+
to publish it), has `clean`, `build`, `rebuild` and `test` scripts and a test, and `--to <package>` adds it to the
|
|
138
|
+
dependencies of another package of the workspace, as `^<version>`. The command installs nothing: run the install of the
|
|
139
|
+
package manager of the project afterwards, as its output says, to link the package.
|
|
140
|
+
|
|
141
|
+
- `lakutata add greeting`: a TypeScript package (`src/index.ts` compiled into `build`, with its declarations).
|
|
142
|
+
- `lakutata add @acme/capture --native [gyp|cmake|rust]`: a native addon, with one of these build systems:
|
|
143
|
+
- `gyp` (the default): C++ with [node-addon-api](https://github.com/nodejs/node-addon-api), built by node-gyp from
|
|
115
144
|
`binding.gyp`;
|
|
116
145
|
- `cmake`: C++ with node-addon-api, built by [cmake-js](https://github.com/cmake-js/cmake-js) from `CMakeLists.txt`;
|
|
117
146
|
- `rust`: Rust with [napi-rs](https://napi.rs), built by cargo (`Cargo.toml`, `build.rs`, `rust/lib.rs`).
|
|
118
147
|
|
|
119
|
-
Node-API is stable across
|
|
120
|
-
|
|
121
|
-
node-gyp-build from `src/index.ts`, compiled into `dist
|
|
122
|
-
silicon in one file
|
|
123
|
-
|
|
124
|
-
static libraries of the package,
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
`lakutata package bundle` and `lakutata package exe` ship the addon
|
|
128
|
-
it needs a C++ toolchain (with CMake for `cmake`), or Rust for
|
|
148
|
+
Node-API is stable across versions of Node.js and Electron, so the same addon runs in both without being rebuilt. The
|
|
149
|
+
addon is built into `build/Release` (by `npm run build:native`, and by its `install` script when the package is
|
|
150
|
+
installed) and loaded by node-gyp-build from `src/index.ts`, which is compiled into `dist`. The C++ addons are built
|
|
151
|
+
for Intel and Apple silicon Macs in one file, a Rust addon for the architecture of the machine. `lakutata native`
|
|
152
|
+
links their libraries. The comments of `binding.gyp` and `CMakeLists.txt` also show how to give libraries and build
|
|
153
|
+
options: system libraries, pkg-config, static libraries of the package, dynamic libraries shipped with the addon
|
|
154
|
+
(copied next to it and found there through its rpath), and in `binding.gyp` the C++ standard and the options of each
|
|
155
|
+
platform (`CMakeLists.txt` sets C++20). A library with its own Makefile is built before the addon by a script, as the
|
|
156
|
+
README of the package shows (`build:deps`). `lakutata package bundle` and `lakutata package exe` ship the addon, and
|
|
157
|
+
its dynamic libraries, with the application. Building it needs a C++ toolchain (with CMake for `cmake`), or Rust for
|
|
158
|
+
`rust`.
|
|
129
159
|
|
|
130
160
|
### `lakutata native <action> <value>`
|
|
131
161
|
|
|
132
|
-
Change the build of the native addon
|
|
133
|
-
`CMakeLists.txt
|
|
134
|
-
addon are not changed.
|
|
162
|
+
Change the build of the native addon in the current directory, found by its build file (`binding.gyp`,
|
|
163
|
+
`CMakeLists.txt` or `Cargo.toml`). The file is edited in place, keeping its comments and layout; the sources of the
|
|
164
|
+
addon are not changed. Repeating a change changes nothing.
|
|
135
165
|
|
|
136
166
|
- `lakutata native link <library>`: link a library:
|
|
137
|
-
- a library
|
|
167
|
+
- a system library: `lakutata native link pcap` (`ws2_32` with `--platform win`);
|
|
138
168
|
- `--pkg-config`: a library found by pkg-config (`lakutata native link libpcap --pkg-config`; not on Windows);
|
|
139
|
-
- `--framework`: a framework
|
|
169
|
+
- `--framework`: a macOS framework (`lakutata native link CoreFoundation --framework`);
|
|
140
170
|
- a file of the package: a static library (`deps/lib/libfoo.a`; `foo.lib` on Windows) is linked into the addon; a
|
|
141
|
-
dynamic
|
|
142
|
-
the addon and found there at run time
|
|
143
|
-
install name must be `@rpath/libfoo.dylib` (`install_name_tool -id`): the command
|
|
144
|
-
|
|
145
|
-
-
|
|
146
|
-
- `lakutata native
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
171
|
+
dynamic library (`deps/lib/libfoo.dylib`, `libfoo.so`, or `foo.dll` with its import library `foo.lib`) is copied
|
|
172
|
+
next to the addon and found there at run time through its rpath (`@loader_path` on macOS, `$ORIGIN` on Linux). On
|
|
173
|
+
macOS, its install name must be `@rpath/libfoo.dylib` (set with `install_name_tool -id`): the command says so when
|
|
174
|
+
it is not;
|
|
175
|
+
- `--crate`: a crate, for a Rust addon (`cargo add`).
|
|
176
|
+
- `lakutata native include <directory>`: a directory of headers (C++), of the package or an absolute directory of the
|
|
177
|
+
system.
|
|
178
|
+
- `lakutata native define <NAME[=value]>`: a preprocessor definition (C++).
|
|
179
|
+
|
|
180
|
+
`--platform mac|linux|win` makes the change for one platform only (a library file sets its own platform: `.dylib` macOS,
|
|
181
|
+
`.so` Linux, `.dll` and `.lib` Windows, `.a` every platform but Windows, like pkg-config). `--target <name>` names the
|
|
182
|
+
target to change when the build file has several. What is written, by build system:
|
|
151
183
|
|
|
152
184
|
| | gyp | CMake | Rust |
|
|
153
185
|
|---|---|---|---|
|
|
154
|
-
| File | `binding.gyp`, or the `.gypi` it includes
|
|
186
|
+
| File | `binding.gyp`, or the `.gypi` it includes that declares the target | `CMakeLists.txt` | `.cargo/config.toml` (`[env]`), read by `build.rs` |
|
|
155
187
|
| Library | `libraries` | `target_link_libraries` | `rustc-link-lib` |
|
|
156
188
|
| pkg-config | `<!@(pkg-config ...)` | `pkg_check_modules(... IMPORTED_TARGET ...)` | the `-sys` crates |
|
|
157
189
|
| Framework | `xcode_settings.OTHER_LDFLAGS` | `-framework` in `if(APPLE)` | `rustc-link-lib=framework=` |
|
|
158
|
-
| Dynamic library | `copies`, the rpath | `
|
|
190
|
+
| Dynamic library | `copies`, the rpath | `INSTALL_RPATH` (`BUILD_WITH_INSTALL_RPATH`), a `POST_BUILD` copy | `rustc-cdylib-link-arg`, a copy in `build:native` |
|
|
159
191
|
| Headers, definitions | `include_dirs`, `defines` | `target_include_directories`, `target_compile_definitions` | none (crates) |
|
|
160
|
-
| Platform | `conditions` (`OS=="mac"`) | `if(APPLE)`, `if(WIN32)`, `if(CMAKE_SYSTEM_NAME STREQUAL "Linux")` | `LAKUTATA_NATIVE_MACOS`, `_LINUX`, `_WINDOWS`, `_UNIX` |
|
|
192
|
+
| Platform | `conditions` (`OS=="mac"`, `OS!="win"`) | `if(APPLE)`, `if(WIN32)`, `if(NOT WIN32)`, `if(CMAKE_SYSTEM_NAME STREQUAL "Linux")` | `LAKUTATA_NATIVE_MACOS`, `_LINUX`, `_WINDOWS`, `_UNIX` |
|
|
161
193
|
|
|
162
|
-
|
|
163
|
-
only:
|
|
194
|
+
For a Rust addon, the libraries are passed to `build.rs` (written by `lakutata add --native rust`), which passes them
|
|
195
|
+
to cargo for the addon only: flags given to rustc would apply to every crate it builds.
|
|
164
196
|
|
|
165
197
|
### `lakutata list`
|
|
166
198
|
|
|
167
|
-
List the packages
|
|
199
|
+
List the packages: the first line gives their number and the version of the workspace, then each package has its
|
|
200
|
+
version, ` (private)` when it is private, its directory and the packages of the workspace it depends on.
|
|
168
201
|
|
|
169
202
|
### From lerna
|
|
170
203
|
|
|
@@ -174,142 +207,158 @@ List the packages, their versions and the packages they depend on.
|
|
|
174
207
|
| `lerna version patch --no-git-tag-version --no-push -y` | `lakutata version patch --yes` |
|
|
175
208
|
| `lerna version patch` | `lakutata version patch --git` (the tag is not pushed) |
|
|
176
209
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
210
|
+
Packages are still published with `npm publish -w <package>` (the packages `lakutata add` makes are private: remove
|
|
211
|
+
`"private": true` first). From `lerna.json`, the tool reads and writes only `version`: the packages come from the
|
|
212
|
+
`workspaces` of the root `package.json`, or from `pnpm-workspace.yaml`. It does not version packages independently (a
|
|
213
|
+
`lerna.json` with `"version": "independent"` cannot be bumped), write changelogs from the commits or cache builds:
|
|
214
|
+
workspaces that need these keep lerna (or nx, turborepo) alongside it.
|
|
180
215
|
|
|
181
216
|
## Bundles and executables
|
|
182
217
|
|
|
183
|
-
|
|
184
|
-
`@lakutata/builder`: the
|
|
185
|
-
|
|
186
|
-
|
|
218
|
+
These commands pack the application in the current directory, which must be compiled first (by `tsc`, which emits the
|
|
219
|
+
metadata of the decorators). The work is done by `@lakutata/builder`: the copy installed in the project
|
|
220
|
+
(`npm install --save-dev @lakutata/builder`, as the templates that pack their application do), else the one installed
|
|
221
|
+
with the tool (a global install of the tool does not include it, as the builder is an optional peer dependency). Scripts
|
|
222
|
+
can also pack applications with its functions (`bundleProject`, `buildExecutable`).
|
|
187
223
|
|
|
188
224
|
### `lakutata package bundle`
|
|
189
225
|
|
|
190
|
-
Bundle the application and its dependencies into one CommonJS file (esbuild)
|
|
191
|
-
`dist/<name>.cjs`, the name
|
|
192
|
-
`main` of the `package.json` (`--entry` changes it)
|
|
193
|
-
(`--no-minify`), `import.meta.url` is the
|
|
226
|
+
Bundle the application and its dependencies into one CommonJS file (with esbuild) that node runs without
|
|
227
|
+
`node_modules`: `dist/<name>.cjs`, where the name is the first `bin` of the `package.json`, else the package name
|
|
228
|
+
without its scope. The entry is the `main` of the `package.json`, else `build/App.js` (`--entry` changes it). The
|
|
229
|
+
bundle is minified, keeping the names of the classes (`--no-minify` turns minifying off), and `import.meta.url` is the
|
|
230
|
+
URL of the bundle.
|
|
194
231
|
|
|
195
232
|
| Option | |
|
|
196
233
|
|---|---|
|
|
197
|
-
| `--entry <file>` | the compiled entry, the `main` of the `package.json
|
|
234
|
+
| `--entry <file>` | the compiled entry, by default the `main` of the `package.json`, else `build/App.js` |
|
|
198
235
|
| `--outfile <file>` | the bundle, `dist/<name>.cjs` by default |
|
|
199
236
|
| `--no-minify` | do not minify the bundle |
|
|
200
237
|
| `--external <modules...>` | the modules left out of the bundle, loaded at run time from a `node_modules` next to it |
|
|
201
238
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
packages
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
holds the files loaded at run time: the
|
|
210
|
-
|
|
211
|
-
files
|
|
212
|
-
maps,
|
|
213
|
-
the
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
of
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
239
|
+
Bundles are CommonJS modules, because the executables of Node.js run them. The ES modules of the application are
|
|
240
|
+
converted, so they cannot use top-level `await`: await inside an async function instead.
|
|
241
|
+
|
|
242
|
+
Native addons (`.node` files) cannot be bundled. While bundling, the tool finds the packages that hold addons, and the
|
|
243
|
+
packages that load them through computed paths (such as sharp). It leaves them out of the bundle, with what they load at
|
|
244
|
+
run time (the JavaScript they require, and the packages of the shared libraries linked with their addons, such as
|
|
245
|
+
libvips), and lays them out as in `node_modules` in `dist/<name>.native/`, which is distributed with the bundle. This
|
|
246
|
+
tree holds the files loaded at run time: all the files of the packages of addons and shared libraries; for the other
|
|
247
|
+
packages, the JavaScript they load (traced) and their other files (the data they read); and all the files of the
|
|
248
|
+
packages that load their files through paths that cannot be followed (`require(path.join(__dirname, name))`). The type
|
|
249
|
+
declarations, source maps, TypeScript sources and documentation of the packages are left out, and so are the C and C++
|
|
250
|
+
sources and objects of the addons (better-sqlite3 holds the source of SQLite) and what built them: the files of node-gyp
|
|
251
|
+
and of CMake in `build/`, the `target` directory of cargo, the static and import libraries. The addons of the
|
|
252
|
+
application itself (`require('./x.node')`, `createRequire(import.meta.url)('./x.node')`) go into the tree too. The
|
|
253
|
+
packages of the framework, and those built on it, are always bundled with the application, whatever they depend on, so
|
|
254
|
+
that there is one copy of the framework, its classes and its container; their native dependencies go into the tree.
|
|
255
|
+
Optional dependencies that are not installed (the drivers of stores the application does not use: `peerDependenciesMeta`
|
|
256
|
+
optional, `optionalDependencies`) are left out: loading one throws at run time, as it would without the bundle.
|
|
257
|
+
|
|
258
|
+
The bundler does not follow the files that the application reads by path: the scripts it runs on their own (workers,
|
|
259
|
+
`new Worker()`, worker pools given a file; child processes, `fork()`; modules loaded by path,
|
|
260
|
+
`require(path.join(__dirname, 'x.js'))`) and its data (`fs.readFileSync(path.join(__dirname, 'defaults.json'))`, a
|
|
261
|
+
directory of schemas). Also, the bundle is not where the modules were: in a module of `build/config/`,
|
|
262
|
+
`path.resolve(__dirname, '../../schema')` is the `schema/` directory of the project, but no longer once bundled into
|
|
263
|
+
`dist/`. The tool finds every path to a file built from the location of its module, wherever it is written, in the
|
|
264
|
+
modules of the application and in those of its packages, and rewrites the expression to point to the file in the
|
|
265
|
+
native tree (`dist/<name>.native/.lakutata/files/`, with the directories as in the project, and the packages linked
|
|
266
|
+
from outside it under `node_modules/`):
|
|
227
267
|
|
|
228
268
|
| The path names | |
|
|
229
269
|
|---|---|
|
|
230
|
-
| a script (`.js`, `.cjs`) | bundled on its own with what it loads (a CommonJS file, whatever the type of the project) |
|
|
231
|
-
| another file | copied (a `package.json`
|
|
270
|
+
| a script (`.js`, `.cjs`) | bundled on its own with what it loads (as a CommonJS file, whatever the module type of the project) |
|
|
271
|
+
| another file | copied (a `package.json` gets the type CommonJS, like the scripts next to it) |
|
|
232
272
|
| a directory of data | its files copied |
|
|
233
|
-
| a directory holding the module (`path.join(__dirname, '..')`: the application, its packages) | not shipped,
|
|
234
|
-
| a directory holding scripts or packages (`package.json`, `node_modules`) | not shipped,
|
|
273
|
+
| a directory holding the module (`path.join(__dirname, '..')`: the application, its packages) | not shipped, with a warning: declare its files as resources (`lakutata.resources`, below) |
|
|
274
|
+
| a directory holding scripts or packages (`package.json`, `node_modules`) | not shipped, with a warning: its scripts would need their packages at run time |
|
|
235
275
|
| nothing yet (a directory the application creates) | left as it is |
|
|
236
276
|
|
|
237
|
-
The paths followed:
|
|
277
|
+
The paths that are followed:
|
|
238
278
|
|
|
239
279
|
| Path | |
|
|
240
280
|
|---|---|
|
|
241
|
-
| `new URL('./worker.js', import.meta.url)` | the URL of the module (as Vite); `pathToFileURL(__filename)`
|
|
242
|
-
| `import.meta.url + '/../worker.js'` |
|
|
243
|
-
| `path.join(__dirname, 'worker.js')`, `path.resolve(__dirname, …)` | `import.meta.dirname
|
|
281
|
+
| `new URL('./worker.js', import.meta.url)` | the URL of the module (as in Vite); also `pathToFileURL(__filename)` |
|
|
282
|
+
| `import.meta.url + '/../worker.js'` | the URL of the module as a string |
|
|
283
|
+
| `path.join(__dirname, 'worker.js')`, `path.resolve(__dirname, …)` | also with `import.meta.dirname` or `path.dirname(fileURLToPath(import.meta.url))` |
|
|
244
284
|
| `__dirname + '/worker.js'`, `` `${__dirname}/worker.js` `` | |
|
|
245
|
-
| `require.resolve('./worker')`, `require.resolve(path.resolve(__dirname, '../lib/worker'))` | the extension found as node finds it |
|
|
246
|
-
| `` path.join(__dirname, 'locales', `${lang}.json`) ``, `` new URL(`./jobs/${name}.js`, import.meta.url) `` | known
|
|
247
|
-
|
|
248
|
-
The code
|
|
249
|
-
|
|
250
|
-
(`worker_threads`) whose scripts cannot be followed
|
|
251
|
-
application (
|
|
252
|
-
(`new Worker(file)
|
|
253
|
-
to the current directory of the process (`new Worker('./worker.js')`, which node
|
|
254
|
-
their scripts
|
|
255
|
-
(`eval: true`) need nothing. The warnings name the modules of the application
|
|
285
|
+
| `require.resolve('./worker')`, `require.resolve(path.resolve(__dirname, '../lib/worker'))` | the extension is found as node finds it |
|
|
286
|
+
| `` path.join(__dirname, 'locales', `${lang}.json`) ``, `` new URL(`./jobs/${name}.js`, import.meta.url) `` | partly known: every file and directory its pattern matches (an expression matches part of a name), with the expression kept |
|
|
287
|
+
|
|
288
|
+
The code emitted by tsc (`(0, node_path_1.join)(__dirname, 'worker.js')`) is followed too. A script that the
|
|
289
|
+
application also imports gets a warning: it is bundled twice, with a separate copy of its module (its state, its
|
|
290
|
+
classes) in each. Node.js workers (`worker_threads`) whose scripts cannot be followed get a warning in the modules of
|
|
291
|
+
the application (packages start workers from the paths their users give): a path known only at run time
|
|
292
|
+
(`new Worker(file)`; a variable or a class property holding one of the paths above is followed), or a path relative
|
|
293
|
+
to the current directory of the process (`new Worker('./worker.js')`, which node resolves from there, not from the
|
|
294
|
+
module). Build the paths of their scripts from the directory of their module, or ship the scripts as resources.
|
|
295
|
+
Workers that run source code (`eval: true`) need nothing. The warnings name only the modules of the application,
|
|
296
|
+
with their file and line.
|
|
256
297
|
|
|
257
298
|
The resources of the application, the files it reads at run time (the built pages of a web application, templates,
|
|
258
|
-
data), are declared
|
|
299
|
+
data), are declared in the `lakutata.resources` of its `package.json`, as a list of `{from, to}` objects (like the
|
|
300
|
+
`extraResources` of electron-builder, but without its strings, globs or filters):
|
|
259
301
|
|
|
260
302
|
```json
|
|
261
303
|
"lakutata": {"resources": [{"from": "../ui/dist", "to": "ui"}]}
|
|
262
304
|
```
|
|
263
305
|
|
|
264
|
-
`from` is a file or a directory of the project, `to` its path
|
|
265
|
-
with the bundle. The application finds them
|
|
266
|
-
`isPackaged()` tells
|
|
306
|
+
`from` is a file or a directory of the project, and `to` its path among the resources, in `dist/<name>.resources/`,
|
|
307
|
+
which is distributed with the bundle. The application finds them through `resourcesPath()` of lakutata (`undefined`
|
|
308
|
+
when it does not run packed, which `isPackaged()` tells).
|
|
267
309
|
|
|
268
310
|
### `lakutata package exe`
|
|
269
311
|
|
|
270
|
-
Make
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
With `--runtime bun`, the bundle
|
|
276
|
-
start)
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
312
|
+
Make an executable of the application for the platform it runs on, which runs without Node.js installed: `dist/<name>`
|
|
313
|
+
(`dist/<name>.exe` on Windows). The bundle is embedded, with its V8 code cache, in a copy of the Node.js binary running
|
|
314
|
+
the tool (a single executable application of Node.js), so the embedded Node.js is the version running the tool. In an
|
|
315
|
+
executable, `import.meta.url` is the URL of the executable itself.
|
|
316
|
+
|
|
317
|
+
With `--runtime bun`, Bun compiles the bundle instead (`bun build --compile --bytecode`: the code is compiled to
|
|
318
|
+
bytecode, so it is not parsed at start), using the Bun of the project (the `bun` package of npm,
|
|
319
|
+
`npm install --save-dev bun`), else the one of the system. Its executables are smaller, start faster and use less
|
|
320
|
+
memory; the runtime is then Bun (JavaScriptCore, with its implementation of the Node.js APIs). The native addons are
|
|
321
|
+
those of Node.js, not rebuilt for Bun. Bun loads the addons of Node-API, but may not load those built on the V8 API of
|
|
322
|
+
Node.js: the tool warns of them (with better-sqlite3, the executable builds, and fails when it loads the package). Like
|
|
323
|
+
the executables of Node.js, the executables of Bun do not load the `.env` or the `bunfig.toml` of the directory they run
|
|
324
|
+
in (an application that needs one loads it itself, or uses `LAKUTATA_ENV_FILE`), and the mode is that of the run: Bun
|
|
325
|
+
would replace `process.env.NODE_ENV` with the mode of its build, but the bundle reads it at run time.
|
|
326
|
+
|
|
327
|
+
Make the executables of other platforms on those platforms: the native addons of the application are built there for
|
|
328
|
+
them, and the executables can be tested there. A CI provides the machines (a matrix of Linux, macOS and Windows
|
|
329
|
+
runners); the Linux architectures can also be built in a container of the architecture
|
|
330
|
+
(`docker run --platform linux/arm64`, as the cross builds of the templates do).
|
|
287
331
|
|
|
288
332
|
| Option | |
|
|
289
333
|
|---|---|
|
|
290
334
|
| `--outdir <directory>` | the directory of the executable, `dist` by default |
|
|
291
|
-
| `--runtime <node\|bun>` | the runtime
|
|
292
|
-
| `--layout <file\|directory>` | one file (
|
|
293
|
-
| `--entry`, `--no-minify`, `--external` | as `lakutata package bundle` |
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
first run,
|
|
297
|
-
`%LOCALAPPDATA%\<name>\Cache` on Windows, or
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
for
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
335
|
+
| `--runtime <node\|bun>` | the embedded runtime: `node` (the default) or `bun` |
|
|
336
|
+
| `--layout <file\|directory>` | one file (the default), or a directory: `dist/<name>/` holds the executable, its native addons (`native/`) and its resources (`resources/`), loaded from there without extraction (for the installers and the images) |
|
|
337
|
+
| `--entry`, `--no-minify`, `--external` | as for `lakutata package bundle`: the external modules are loaded from a `node_modules` next to the executable |
|
|
338
|
+
|
|
339
|
+
With `--layout file`, the native addons, the files read by path and the resources are embedded in the executable. At its
|
|
340
|
+
first run, the executable extracts them into `native/<hash>`, a directory named after their content, in its cache
|
|
341
|
+
directory: `~/Library/Caches/<name>` on macOS, `%LOCALAPPDATA%\<name>\Cache` on Windows, `$XDG_CACHE_HOME/<name>` or
|
|
342
|
+
else `~/.cache/<name>` on Linux, or the directory given by `LAKUTATA_NATIVE_DIR`. When the cache directory cannot be
|
|
343
|
+
written, it uses `<name>` in the temporary directory (not when `LAKUTATA_NATIVE_DIR` is given). The next runs load them
|
|
344
|
+
from there, and different versions of the program do not share it. The addons need the system libraries they were built
|
|
345
|
+
for (the glibc version of the Linux prebuilt addons).
|
|
346
|
+
|
|
347
|
+
The child processes of an executable run the executable itself (`process.execPath`). In both layouts, an executable
|
|
348
|
+
started for one of its scripts (`fork(path.join(__dirname, 'child.js'))`, `spawn(process.execPath, [script])`) runs that
|
|
349
|
+
script with its arguments, not the application: with Node.js, `require.main` is that script, as with node; with Bun, it
|
|
350
|
+
is not.
|
|
351
|
+
|
|
352
|
+
The executables for macOS are signed ad hoc. Those for Windows made with Node.js keep the signature of `node.exe`,
|
|
353
|
+
which no longer matches: sign them before distributing them.
|
|
306
354
|
|
|
307
355
|
### `lakutata package installer`
|
|
308
356
|
|
|
309
|
-
Make the installers of the application for the platform it runs on (as electron-builder)
|
|
310
|
-
(`lakutata package exe --layout directory`)
|
|
311
|
-
|
|
312
|
-
They are configured by the `lakutata.installer` of the
|
|
357
|
+
Make the installers of the application for the platform it runs on (as electron-builder does). They install its
|
|
358
|
+
executable in the directory layout (`lakutata package exe --layout directory`) with its native addons and its
|
|
359
|
+
resources, put its program in the PATH and register its service. Make the installers of other platforms on those
|
|
360
|
+
platforms (the Linux ones can be made in a container). They are configured by the `lakutata.installer` of the
|
|
361
|
+
`package.json`:
|
|
313
362
|
|
|
314
363
|
```json
|
|
315
364
|
"lakutata": {
|
|
@@ -322,61 +371,68 @@ They are configured by the `lakutata.installer` of the `package.json`:
|
|
|
322
371
|
|
|
323
372
|
| Option | |
|
|
324
373
|
|---|---|
|
|
325
|
-
| `name` | the name of the package (lower case),
|
|
326
|
-
| `appId` | the identifier of the application (reverse DNS, `com.acme.app`), its name
|
|
327
|
-
| `productName` | the name shown to
|
|
328
|
-
| `description`, `maintainer`, `homepage`, `license
|
|
329
|
-
| `
|
|
330
|
-
| `
|
|
374
|
+
| `name` | the name of the package (lower case), by default that of the program (for an Electron application, the name of the package without its scope) |
|
|
375
|
+
| `appId` | the identifier of the application (reverse DNS, `com.acme.app`), by default its name: on macOS, the identifier of the package and the label of the service; on Windows, the key of its uninstaller and of its upgrades |
|
|
376
|
+
| `productName` | the name shown to users (in the installers, and in the list of programs on Windows), by default the `productName` of the `package.json`, else the name |
|
|
377
|
+
| `description`, `maintainer`, `homepage`, `license` | by default those of the `package.json` (the maintainer is its author) |
|
|
378
|
+
| `vendor` | its vendor, none by default (on Windows, the publisher is the vendor, else the maintainer) |
|
|
379
|
+
| `runtime` | the runtime of the executable: `node` (the default) or `bun`; `electron` for an Electron application (below) |
|
|
380
|
+
| `addToPath` | put the program in the PATH (`/usr/bin/<program>`, `/usr/local/bin/<program>` on macOS; on Windows, the PATH of the machine), `true` by default |
|
|
331
381
|
| `service` | `true` or the options of the service (below), none by default |
|
|
332
|
-
| `linux.targets` | `deb`, `rpm`, `archlinux`, `tar.gz` on
|
|
333
|
-
| `linux.depends`, `linux.recommends`, `linux.section`, `linux.priority` | the packages
|
|
382
|
+
| `linux.targets` | `deb`, `rpm`, `archlinux`, `tar.gz` on glibc systems (`deb`, `rpm`, `tar.gz` by default); `apk`, `tar.gz` on Alpine (musl) |
|
|
383
|
+
| `linux.depends`, `linux.recommends`, `linux.section`, `linux.priority` | the system packages it needs and recommends, its section and its priority (deb) |
|
|
334
384
|
| `mac.targets` | `pkg`, `tar.gz` (both by default) |
|
|
335
385
|
| `win.targets` | `nsis`, `msi`, `zip` (all by default) |
|
|
336
|
-
| `electron` | the
|
|
337
|
-
|
|
338
|
-
The
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
386
|
+
| `electron` | the electron-builder configuration of an Electron application, merged over the one made from these options |
|
|
387
|
+
|
|
388
|
+
The configuration is checked before anything is built, the options of the installers that are not made included.
|
|
389
|
+
|
|
390
|
+
The Linux packages are made by nFPM (downloaded once into the cache of lakutata, for x64 and arm64; `LAKUTATA_NFPM`
|
|
391
|
+
gives another copy, and one for the other architectures) in `dist/installer` (`--outdir`). They install the application
|
|
392
|
+
in `/opt/<name>`, with the C++ runtime library as a dependency. The executables link the C library of the system they
|
|
393
|
+
are made on, so make the packages for glibc systems on a glibc system, and the `apk` packages on Alpine, with Bun
|
|
394
|
+
(`"runtime": "bun"`) when the application has native addons: the executables of Node.js do not load them on musl.
|
|
395
|
+
|
|
396
|
+
The macOS installers are made with the tools of macOS (`pkgbuild`, `productbuild`). The `pkg` package installs the
|
|
397
|
+
application in `/usr/local/lib/<name>` and its program in `/usr/local/bin`, on the Macs of the architecture of the
|
|
398
|
+
program only. macOS does not remove packages: `sudo /usr/local/lib/<name>/uninstall` removes the application (its data,
|
|
399
|
+
its environment file, its user and its log are kept). The `pkg` package is not signed, and the executable it installs is
|
|
400
|
+
signed ad hoc only (the Developer ID signature and the notarization, which distribution outside the machines of the
|
|
401
|
+
organization needs, are not made yet).
|
|
402
|
+
|
|
403
|
+
The Windows installers are made on Windows: the NSIS installer (`<name>-<version>-<arch>-setup.exe`) and the Windows
|
|
404
|
+
Installer package (`.msi`, made by WiX, for deployment in organizations) install the application in
|
|
405
|
+
`C:\Program Files\<name>` and its data in `C:\ProgramData\<name>`; they are removed like other Windows programs. Their
|
|
406
|
+
tools are downloaded once into the cache of lakutata (NSIS 3, WiX 3, WinSW; `LAKUTATA_NSIS`, `LAKUTATA_WIX` and
|
|
407
|
+
`LAKUTATA_WINSW` give other copies). The executables made with Node.js (`"runtime": "node"`) keep the signature of
|
|
408
|
+
Node.js, which no longer matches: sign them (signtool) before distributing them.
|
|
409
|
+
|
|
410
|
+
The service runs the application when the system starts: systemd (`/usr/lib/systemd/system/<service>.service`), OpenRC
|
|
411
|
+
on Alpine (`/etc/init.d/<service>`), launchd on macOS (`/Library/LaunchDaemons/<appId>.plist`), or WinSW on Windows
|
|
412
|
+
(`<name>-service.exe` next to the application, registered as a Windows service: `Restart-Service <service>`). The
|
|
413
|
+
installation starts it, an upgrade restarts it, and the removal stops and disables it first.
|
|
360
414
|
|
|
361
415
|
| Service option | |
|
|
362
416
|
|---|---|
|
|
363
|
-
| `name`, `description` |
|
|
417
|
+
| `name`, `description` | those of the package by default |
|
|
364
418
|
| `args` | the arguments of the application |
|
|
365
|
-
| `env` | its environment (`MODE=production` by default), written to `/etc/<name>/<name>.env` (`/usr/local/etc/<name>/<name>.env` on macOS, `C:\ProgramData\<name>\<name>.env` on Windows), which
|
|
366
|
-
| `user` | its user: a system user named after the package
|
|
367
|
-
| `restart` | `on-failure` (
|
|
368
|
-
| `autoStart` | enabled and started by the installation, by default |
|
|
419
|
+
| `env` | its environment (`MODE=production` by default), written to `/etc/<name>/<name>.env` (`/usr/local/etc/<name>/<name>.env` on macOS, `C:\ProgramData\<name>\<name>.env` on Windows), which administrators may edit (upgrades keep it) |
|
|
420
|
+
| `user` | its user: by default a system user named after the package (`_<name>` on macOS, hidden), created by the installation, or `root`; on Windows, by default its virtual account (`NT SERVICE\<service>`), or `LocalService`, `NetworkService` or `LocalSystem` |
|
|
421
|
+
| `restart` | `on-failure` (the default), `always` or `no` (on Windows and with OpenRC, `on-failure` and `always` behave alike) |
|
|
422
|
+
| `autoStart` | enabled and started by the installation, `true` by default; otherwise the administrator enables and starts it (`systemctl enable --now <service>`; on macOS, `launchctl enable system/<appId>`, then `launchctl bootstrap system /Library/LaunchDaemons/<appId>.plist`) |
|
|
369
423
|
|
|
370
|
-
Its working directory is `/var/lib/<name>` (`/usr/local/var/lib/<name>`
|
|
371
|
-
`C:\ProgramData\<name>` on Windows, its logs in `logs`)
|
|
372
|
-
Windows, the
|
|
424
|
+
Its working directory, which holds its data and is owned by its user, is `/var/lib/<name>` (`/usr/local/var/lib/<name>`
|
|
425
|
+
on macOS, with its log in `/usr/local/var/log/<name>.log`; `C:\ProgramData\<name>` on Windows, with its logs in `logs`).
|
|
426
|
+
`SIGTERM` ends it gracefully (on Windows, stopping the service sends a Ctrl+C, which Node.js receives as `SIGINT`).
|
|
373
427
|
|
|
374
|
-
|
|
375
|
-
|
|
428
|
+
Every bundle and executable, and so every installed application, loads the environment file named by the
|
|
429
|
+
`LAKUTATA_ENV_FILE` environment variable before the application starts (the Windows service gets its environment this
|
|
430
|
+
way, as its wrapper has no environment file): lines `NAME=value` or `NAME="value"`, and comments (`#`). The values of
|
|
431
|
+
the file override the variables that are already set.
|
|
376
432
|
|
|
377
|
-
The installers run
|
|
378
|
-
platform, which its installers run
|
|
379
|
-
|
|
433
|
+
The installers run scripts of the application (files of the project), as with electron-builder: the scripts of a
|
|
434
|
+
platform, which all its installers run; the scripts of one installer, each replacing the platform's script for the
|
|
435
|
+
same moment; the native scripts of a Linux package; and an NSIS file included by the NSIS installer:
|
|
380
436
|
|
|
381
437
|
```json
|
|
382
438
|
"installer": {
|
|
@@ -392,123 +448,136 @@ Linux, the file of NSIS included by its installer:
|
|
|
392
448
|
|
|
393
449
|
| Script | |
|
|
394
450
|
|---|---|
|
|
395
|
-
| `preinstall` | before the files of the application are installed (
|
|
396
|
-
| `postinstall` | after they are installed, before the service
|
|
451
|
+
| `preinstall` | before the files of the application are installed (with Windows Installer, an upgrade has already removed the version it replaces) |
|
|
452
|
+
| `postinstall` | after they are installed, before the service starts (during an upgrade, the service of the version replaced may still run) |
|
|
397
453
|
| `preremove` | before the removal, once the service is stopped |
|
|
398
454
|
| `postremove` | after the files are removed |
|
|
399
455
|
|
|
400
|
-
|
|
401
|
-
`postremove`; an upgrade runs no removal script)
|
|
402
|
-
directory of the application
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
456
|
+
Their first argument (`$1`, `$args[0]` in PowerShell) tells what the installer does: `install` or `upgrade`
|
|
457
|
+
(`preinstall`, `postinstall`), or `remove` (`preremove`, `postremove`; an upgrade runs no removal script).
|
|
458
|
+
`LAKUTATA_INSTALL_DIR` gives the directory of the application. They run as root (on Windows, as an administrator with
|
|
459
|
+
NSIS and as the system account with Windows Installer). When a script fails, the installation (or the removal) fails.
|
|
460
|
+
Each package manager signals an upgrade in its own way (dpkg with `configure <version>`, rpm with the number of
|
|
461
|
+
installed versions, apk and pacman with their upgrade scripts): the installers translate them into these arguments.
|
|
462
|
+
|
|
463
|
+
- Linux (`linux.scripts`, `linux.<deb|rpm|apk|archlinux>.scripts`): scripts run by the interpreter named on their first
|
|
464
|
+
line (`#!/bin/sh` by default), embedded in the scripts of the packages. `linux.<package>.nativeScripts` are run the
|
|
465
|
+
way the package manager runs the scripts of the package, with its own arguments (`preinstall`, `postinstall`,
|
|
466
|
+
`preremove`, `postremove`; `preupgrade`, `postupgrade` for apk and archlinux).
|
|
467
|
+
- macOS (`mac.scripts`, `mac.pkg.scripts`): sh scripts, as on Linux; the `uninstall` script of the application runs
|
|
468
|
+
the removal scripts (macOS does not remove packages).
|
|
469
|
+
- Windows (`win.scripts`, `win.<nsis|msi>.scripts`): PowerShell scripts (`.ps1`, run by Windows PowerShell; Windows
|
|
470
|
+
Installer runs them through a command line, which each must fit in: about 23 KB). `win.nsis.include` is an NSIS file
|
|
471
|
+
(`.nsh`) included by the NSIS installer, which inserts its macros: `customHeader`, `customInit`, `customInstall` (at
|
|
415
472
|
the end of the installation), `customUnInit`, `customUnInstall` (at the start of the removal).
|
|
416
|
-
-
|
|
417
|
-
|
|
418
|
-
The installers of an Electron application (`"runtime": "electron"`) are made by electron-builder
|
|
419
|
-
project
|
|
420
|
-
native addons and
|
|
421
|
-
next to it, in the resources of Electron. Its installers are
|
|
422
|
-
macOS
|
|
423
|
-
description, maintainer, homepage and license are given to electron-builder, `electron` gives the rest (
|
|
424
|
-
file associations,
|
|
473
|
+
- Archives (`tar.gz`, `zip`) run no scripts.
|
|
474
|
+
|
|
475
|
+
The installers of an Electron application (`"runtime": "electron"`) are made by electron-builder, a dependency of the
|
|
476
|
+
project. Its main process is bundled with its dependencies (Electron left out) into the archive of the application, and
|
|
477
|
+
its native addons and resources (`lakutata.resources`: its renderer and its preload script, read from `resourcesPath()`)
|
|
478
|
+
go next to it, in the resources of Electron. Its installers are targets of electron-builder (by default `deb` on Linux,
|
|
479
|
+
`dmg` on macOS and `nsis` on Windows: `linux.targets`, `mac.targets`, `win.targets`). `name`, `appId`, `productName`,
|
|
480
|
+
the description, maintainer, homepage and license are given to electron-builder, and `electron` gives the rest (icons,
|
|
481
|
+
file associations, signature, updates…); `addToPath` and the `linux` options other than `targets` and the scripts are
|
|
482
|
+
not used, and `vendor` is used on Linux only. Its native addons are copied as they are installed (electron-builder does
|
|
483
|
+
not rebuild them): the addons of Node-API run in Electron as they are; install the Electron builds of the others before
|
|
484
|
+
packing (`electron-rebuild`). An Electron application is not a service. Its scripts are run by:
|
|
425
485
|
|
|
426
486
|
| Installer | Scripts |
|
|
427
487
|
|---|---|
|
|
428
|
-
| `deb`, `rpm` (
|
|
429
|
-
| `pkg` (macOS) | `preinstall`, `postinstall` (
|
|
430
|
-
| `nsis` (Windows) | `preinstall`, `postinstall`, `preremove` (its uninstaller ends
|
|
488
|
+
| `deb`, `rpm` (packages made by fpm) | all (`postinstall` and `postremove` after the scripts of electron-builder) |
|
|
489
|
+
| `pkg` (macOS) | `preinstall`, `postinstall` (a macOS application is removed by its user) |
|
|
490
|
+
| `nsis` (Windows) | `preinstall`, `postinstall`, `preremove` (its uninstaller ends by removing the files); the NSIS file of `win.nsis.include` defines the other macros |
|
|
431
491
|
| the others (`AppImage`, `dmg`, `portable`, `msi`…) | none |
|
|
432
492
|
|
|
433
|
-
|
|
434
|
-
electron-builder downloads is
|
|
435
|
-
filter (`ELECTRON_BUILDER_7Z_FILTER`)
|
|
493
|
+
On Linux arm64, the fpm packages need the fpm of the system (`gem install fpm`, `USE_SYSTEM_FPM=true`), because the
|
|
494
|
+
one electron-builder downloads is built for x64. On Windows arm64, the NSIS installers compress the executables with
|
|
495
|
+
the BCJ filter (`ELECTRON_BUILDER_7Z_FILTER`), because they cannot extract files compressed with the ARM64 filter,
|
|
496
|
+
which 7-Zip would choose.
|
|
436
497
|
|
|
437
498
|
| Command option | |
|
|
438
499
|
|---|---|
|
|
439
|
-
| `--target <targets...>` | the installers
|
|
500
|
+
| `--target <targets...>` | the installers to make, by default those of the configuration |
|
|
440
501
|
| `--outdir <directory>` | the directory of the installers, `dist/installer` by default |
|
|
441
|
-
| `--entry`, `--no-minify`, `--external` | as `lakutata package
|
|
502
|
+
| `--entry`, `--no-minify`, `--external` | as for `lakutata package exe` |
|
|
442
503
|
|
|
443
504
|
## Migrations
|
|
444
505
|
|
|
445
506
|
### `lakutata migration <action>`
|
|
446
507
|
|
|
447
|
-
|
|
448
|
-
and `show` run the script
|
|
449
|
-
variable (`MIGRATION_GENERATE`, `MIGRATION_RUN`, `MIGRATION_REVERT`,
|
|
450
|
-
|
|
451
|
-
|
|
508
|
+
Manage the migrations of the databases of the application (its Database components and providers). `generate`, `run`,
|
|
509
|
+
`revert` and `show` run the package script that builds and starts the application (`dev` by default, run by the package
|
|
510
|
+
manager of the project) with an environment variable (`MIGRATION_GENERATE`, `MIGRATION_RUN`, `MIGRATION_REVERT`,
|
|
511
|
+
`MIGRATION_SHOW`). The application then connects to its databases with their options, without synchronizing their
|
|
512
|
+
schemas or running their migrations, runs the command, reports what it did and exits, without starting its components or
|
|
513
|
+
its entrypoints. `create` only writes a file.
|
|
452
514
|
|
|
453
515
|
| Action | |
|
|
454
516
|
|---|---|
|
|
455
|
-
| `generate` |
|
|
456
|
-
| `create <name>` | an empty migration
|
|
457
|
-
| `show` | the migrations
|
|
517
|
+
| `generate` | migrations for the changes of the entities: the application compares the entities with its databases and writes the migrations into the directory, one file `<timestamp>-<database name>.ts` per changed database (what `cross-env MIGRATION_GENERATE=./src/migrations npm run dev` did in lakutata 2.x); when nothing changed, nothing is generated and the command fails |
|
|
518
|
+
| `create <name>` | an empty migration to write by hand (`up` and `down`): `<timestamp>-<name>.ts`, with the class `<Name><timestamp>` |
|
|
519
|
+
| `show` | the migrations in the options of the databases, run (`[X]`) or pending (`[ ]`) |
|
|
458
520
|
| `run` | the pending migrations (`up`) |
|
|
459
|
-
| `revert` | the last migration run (`down`), one at a time; the application
|
|
521
|
+
| `revert` | the last migration run (`down`), one at a time; when the application has several databases, `--database` is required |
|
|
460
522
|
|
|
461
523
|
| Option | |
|
|
462
524
|
|---|---|
|
|
463
525
|
| `--dir <directory>` | the directory of the migrations, relative to the package, `src/migrations` by default (`generate`, `create`) |
|
|
464
|
-
| `--script <script>` | the script
|
|
465
|
-
| `--package <name>` | the package of the
|
|
466
|
-
| `--database <name>` | the database: the name of its Database component or provider, all by default (`MIGRATION_DATABASE`) |
|
|
467
|
-
| `--transaction <mode>` | the transactions of the migrations run or reverted: `all` (one
|
|
526
|
+
| `--script <script>` | the script that builds and starts the application, `dev` by default |
|
|
527
|
+
| `--package <name>` | the package of the application in the workspace, when the command runs from elsewhere in the workspace (by default, the package in the current directory) |
|
|
528
|
+
| `--database <name>` | the database: the name of its Database component or provider, all of them by default (`MIGRATION_DATABASE`) |
|
|
529
|
+
| `--transaction <mode>` | the transactions of the migrations run or reverted: `all` (one for all), `each` or `none`; by default the `migrationsTransactionMode` of the database, else `all` (`MIGRATION_TRANSACTION`) |
|
|
468
530
|
| `--fake` | mark the migrations as run or reverted without executing them (`MIGRATION_FAKE`) |
|
|
469
531
|
|
|
470
|
-
The migrations are compiled with the application and
|
|
471
|
-
run when it connects with `migrationsRun: true`). The commands fail (exit code 1) when the application has no
|
|
472
|
-
(
|
|
473
|
-
fails.
|
|
532
|
+
The migrations are compiled with the application and listed in the options of their database (`migrations: [...]`;
|
|
533
|
+
they run when it connects with `migrationsRun: true`). The commands fail (exit code 1) when the application has no
|
|
534
|
+
database (except `generate`, which then generates nothing), when the given database is not one of the application,
|
|
535
|
+
and when a migration fails.
|
|
474
536
|
|
|
475
537
|
## Languages
|
|
476
538
|
|
|
477
539
|
### `lakutata i18n <action> [locale]`
|
|
478
540
|
|
|
479
|
-
|
|
480
|
-
default; several separated by commas)
|
|
481
|
-
|
|
482
|
-
- `lakutata i18n check`: checks the messages of
|
|
483
|
-
`en` by default), and fails on
|
|
484
|
-
- errors:
|
|
485
|
-
message does not have (missing when the message is formatted), a validation message
|
|
486
|
-
variables of another code;
|
|
487
|
-
- warnings: a message
|
|
488
|
-
message
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
541
|
+
Manage the messages of the languages of the application (`lakutata/com/i18n`), kept in a directory (`--dir`, `locales`
|
|
542
|
+
by default; several separated by commas) with one file (`zh-CN.json`) or one directory (`zh-CN/`) per language.
|
|
543
|
+
|
|
544
|
+
- `lakutata i18n check`: checks the messages of each language against those of the default language (`--default`,
|
|
545
|
+
`en` by default), and fails on errors:
|
|
546
|
+
- errors: an ICU MessageFormat syntax error, a key the default language does not have, an argument the default
|
|
547
|
+
message does not have (missing when the message is formatted), a validation message with an unknown code or with
|
|
548
|
+
the variables of another code;
|
|
549
|
+
- warnings: a missing message (the message of a fallback language is given instead), an argument of the default
|
|
550
|
+
message that is not used, a message identical to the default one (not translated yet). `--strict` fails on
|
|
551
|
+
warnings too, for CI.
|
|
552
|
+
- `lakutata i18n types`: declares the message keys of the default language and their arguments (`--out`,
|
|
553
|
+
`src/i18n.d.ts` by default), so that a misspelled key or a missing argument is a compile error.
|
|
554
|
+
`--module @lakutata/i18n` declares them for applications that import `@lakutata/i18n` rather than
|
|
492
555
|
`lakutata/com/i18n`.
|
|
493
|
-
- `lakutata i18n add <locale>`: adds a language
|
|
494
|
-
|
|
495
|
-
|
|
556
|
+
- `lakutata i18n add <locale>`: adds a language as a copy of the messages of the default language, in a file or a
|
|
557
|
+
directory like the default language (without its validation messages: the language has built-in ones). Translate
|
|
558
|
+
them; `check` reports the ones that are not translated yet.
|
|
496
559
|
|
|
497
560
|
## The language of the tool
|
|
498
561
|
|
|
499
|
-
The help of the tool (the descriptions of its commands and
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
562
|
+
The help of the tool (the descriptions of its commands and options), its prompts, the validation errors of the
|
|
563
|
+
options and a few results (the plan of `lakutata version`, a declined confirmation) are in English, Simplified Chinese
|
|
564
|
+
(`zh-CN`) or Traditional Chinese (`zh-TW`). The language comes from `LAKUTATA_LANG` (`LAKUTATA_LANG=zh-CN`), then from
|
|
565
|
+
the environment (`LANGUAGE`, `LC_ALL`, `LC_MESSAGES`, `LANG`), then from the system; English is used when none of them
|
|
566
|
+
matches. The names of the commands and options, and the other results and errors, are in English.
|
|
503
567
|
|
|
504
568
|
## Environment
|
|
505
569
|
|
|
506
570
|
| Variable | |
|
|
507
571
|
|---|---|
|
|
508
|
-
| `LAKUTATA_NPM_REGISTRY` | the npm registry of the templates (`npm_config_registry`,
|
|
509
|
-
| `LAKUTATA_GITHUB_DOWNLOAD` | a mirror
|
|
510
|
-
| `LAKUTATA_CACHE_DIR` | the directory
|
|
511
|
-
| `LAKUTATA_LANG` | the language of the
|
|
572
|
+
| `LAKUTATA_NPM_REGISTRY` | the npm registry of the templates (by default `npm_config_registry`, else `https://registry.npmjs.org`) |
|
|
573
|
+
| `LAKUTATA_GITHUB_DOWNLOAD` | a GitHub mirror for the `github:` templates (`https://github.com` by default) |
|
|
574
|
+
| `LAKUTATA_CACHE_DIR` | the cache directory (by default `$XDG_CACHE_HOME/lakutata`, else `~/.cache/lakutata`) |
|
|
575
|
+
| `LAKUTATA_LANG` | the language of the tool (`zh-CN`, `zh-TW`, `en`), by default that of the environment |
|
|
576
|
+
|
|
577
|
+
The tool is itself a lakutata application: its commands are the CLI actions of its controllers, served by the
|
|
578
|
+
commander adapter of the entrypoint.
|
|
579
|
+
|
|
580
|
+
## See also
|
|
512
581
|
|
|
513
|
-
The
|
|
514
|
-
|
|
582
|
+
- The guides on the website: [Command Line Tool](https://lakutata.com/guide/Command) and
|
|
583
|
+
[Workspaces](https://lakutata.com/guide/Workspaces).
|