@lakutata/cli 2.17.1 → 3.0.0-beta.1

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.
Files changed (101) hide show
  1. package/README.md +455 -28
  2. package/dist/esm/CLIApp.js +6 -0
  3. package/dist/esm/Config.js +53 -0
  4. package/dist/esm/controllers/CommandLineController.js +180 -0
  5. package/dist/esm/controllers/I18nController.js +67 -0
  6. package/dist/esm/controllers/MigrationController.js +66 -0
  7. package/dist/esm/controllers/NativeController.js +41 -0
  8. package/dist/esm/controllers/PackController.js +88 -0
  9. package/dist/esm/controllers/WorkspaceController.js +91 -0
  10. package/dist/esm/dtos/AddPackageDTO.js +25 -0
  11. package/dist/esm/dtos/BundleDTO.js +29 -0
  12. package/dist/esm/dtos/CleanDTO.js +17 -0
  13. package/dist/esm/dtos/CreateProjectDTO.js +61 -0
  14. package/dist/esm/dtos/ExecutableDTO.js +37 -0
  15. package/dist/esm/dtos/I18nDTO.js +41 -0
  16. package/dist/esm/dtos/InstallerDTO.js +33 -0
  17. package/dist/{options/ListTemplatesOptions.js → esm/dtos/ListTemplatesDTO.js} +5 -14
  18. package/dist/esm/dtos/MigrationDTO.js +45 -0
  19. package/dist/esm/dtos/NativeDTO.js +41 -0
  20. package/dist/esm/dtos/RunScriptDTO.js +33 -0
  21. package/dist/esm/dtos/VersionDTO.js +29 -0
  22. package/dist/esm/lib/AddPackage.js +487 -0
  23. package/dist/esm/lib/Builder.js +21 -0
  24. package/dist/esm/lib/Clean.js +146 -0
  25. package/dist/esm/lib/Environment.js +11 -0
  26. package/dist/esm/lib/I18n.js +67 -0
  27. package/dist/esm/lib/Language.js +24 -0
  28. package/dist/esm/lib/Migration.js +94 -0
  29. package/dist/esm/lib/Output.js +40 -0
  30. package/dist/esm/lib/Processes.js +54 -0
  31. package/dist/esm/lib/ProjectCreator.js +191 -0
  32. package/dist/esm/lib/Registry.js +152 -0
  33. package/dist/esm/lib/Settings.js +25 -0
  34. package/dist/esm/lib/Tar.js +145 -0
  35. package/dist/esm/lib/TemplateCatalog.js +195 -0
  36. package/dist/esm/lib/TemplateFeatures.js +141 -0
  37. package/dist/esm/lib/Versions.js +58 -0
  38. package/dist/esm/lib/native/CMake.js +357 -0
  39. package/dist/esm/lib/native/Gyp.js +398 -0
  40. package/dist/esm/lib/native/NativeProject.js +370 -0
  41. package/dist/esm/lib/native/TextEdits.js +68 -0
  42. package/dist/esm/lib/native/Toml.js +325 -0
  43. package/dist/esm/lib/workspace/Run.js +111 -0
  44. package/dist/esm/lib/workspace/Version.js +144 -0
  45. package/dist/esm/lib/workspace/Workspace.js +231 -0
  46. package/dist/esm/locales/zh-CN.json +194 -0
  47. package/dist/esm/locales/zh-TW.json +194 -0
  48. package/dist/esm/types/ProcessResult.js +1 -0
  49. package/package.json +32 -43
  50. package/CHANGELOG.md +0 -460
  51. package/dist/CLIApp.d.ts +0 -3
  52. package/dist/CLIApp.d.ts.map +0 -1
  53. package/dist/CLIApp.js +0 -45
  54. package/dist/config/Config.d.ts +0 -3
  55. package/dist/config/Config.d.ts.map +0 -1
  56. package/dist/config/Config.js +0 -63
  57. package/dist/config/SetupCLIEntrypoint.d.ts +0 -3
  58. package/dist/config/SetupCLIEntrypoint.d.ts.map +0 -1
  59. package/dist/config/SetupCLIEntrypoint.js +0 -31
  60. package/dist/controllers/CommandLineController.d.ts +0 -25
  61. package/dist/controllers/CommandLineController.d.ts.map +0 -1
  62. package/dist/controllers/CommandLineController.js +0 -78
  63. package/dist/lib/ConvertDTO2Inquirer.d.ts +0 -3
  64. package/dist/lib/ConvertDTO2Inquirer.d.ts.map +0 -1
  65. package/dist/lib/ConvertDTO2Inquirer.js +0 -61
  66. package/dist/lib/GetDataDirectory.d.ts +0 -2
  67. package/dist/lib/GetDataDirectory.d.ts.map +0 -1
  68. package/dist/lib/GetDataDirectory.js +0 -11
  69. package/dist/lib/GetLocalDataFilename.d.ts +0 -2
  70. package/dist/lib/GetLocalDataFilename.d.ts.map +0 -1
  71. package/dist/lib/GetLocalDataFilename.js +0 -12
  72. package/dist/lib/ListTemplateNames.d.ts +0 -2
  73. package/dist/lib/ListTemplateNames.d.ts.map +0 -1
  74. package/dist/lib/ListTemplateNames.js +0 -44
  75. package/dist/lib/SpecialChar.d.ts +0 -9
  76. package/dist/lib/SpecialChar.d.ts.map +0 -1
  77. package/dist/lib/SpecialChar.js +0 -11
  78. package/dist/lib/components/DeGitPuller.d.ts +0 -19
  79. package/dist/lib/components/DeGitPuller.d.ts.map +0 -1
  80. package/dist/lib/components/DeGitPuller.js +0 -65
  81. package/dist/lib/components/Spinner.d.ts +0 -23
  82. package/dist/lib/components/Spinner.d.ts.map +0 -1
  83. package/dist/lib/components/Spinner.js +0 -61
  84. package/dist/lib/providers/Creator.d.ts +0 -46
  85. package/dist/lib/providers/Creator.d.ts.map +0 -1
  86. package/dist/lib/providers/Creator.js +0 -179
  87. package/dist/lib/providers/Information.d.ts +0 -91
  88. package/dist/lib/providers/Information.d.ts.map +0 -1
  89. package/dist/lib/providers/Information.js +0 -225
  90. package/dist/lib/providers/OnlineLatestVersion.d.ts +0 -14
  91. package/dist/lib/providers/OnlineLatestVersion.d.ts.map +0 -1
  92. package/dist/lib/providers/OnlineLatestVersion.js +0 -47
  93. package/dist/lib/providers/TemplateManager.d.ts +0 -36
  94. package/dist/lib/providers/TemplateManager.d.ts.map +0 -1
  95. package/dist/lib/providers/TemplateManager.js +0 -164
  96. package/dist/options/CreateProjectOptions.d.ts +0 -15
  97. package/dist/options/CreateProjectOptions.d.ts.map +0 -1
  98. package/dist/options/CreateProjectOptions.js +0 -94
  99. package/dist/options/ListTemplatesOptions.d.ts +0 -5
  100. package/dist/options/ListTemplatesOptions.d.ts.map +0 -1
  101. package/tsconfig.json +0 -7
package/README.md CHANGED
@@ -1,42 +1,469 @@
1
- <div align="center">
1
+ # @lakutata/cli
2
2
 
3
- ![lakutata](https://socialify.git.ci/lakutata/lakutata/image?description=1&descriptionEditable=An%20IoC-based%20universal%20application%20framework&font=Source%20Code%20Pro&forks=1&language=1&logo=https%3A%2F%2Fraw.githubusercontent.com%2Flakutata%2Flakutata%2Fmain%2Fassets%2Flogo.svg&name=1&pattern=Circuit%20Board&stargazers=1&theme=Auto)
3
+ The command line tool of the [lakutata](https://github.com/lakutata/lakutata) framework.
4
4
 
5
- </div>
5
+ ```bash
6
+ npx @lakutata/cli create --name my-app
7
+ # or installed: npm install -g @lakutata/cli
8
+ lakutata create --name my-app
9
+ ```
10
+
11
+ ## Commands
12
+
13
+ ### `lakutata create`
14
+
15
+ Create a project from a template. The options are given on the command line; in a terminal, the missing ones are asked,
16
+ and the project is created once it is confirmed (`--yes` skips the confirmation).
17
+
18
+ | Option | |
19
+ |---|---|
20
+ | `--name <name>` | the name of the application (required) |
21
+ | `--id <id>` | the ID of the application (a package name), its name in lower case by default |
22
+ | `--template <template>` | the template, `default` by default: an official template (`lakutata templates` lists them), `npm:<package>[@<version>]`, `github:<owner>/<repo>[#<ref>]` or a directory |
23
+ | `--path <directory>` | the directory the project directory is created in, the current one by default |
24
+ | `--init` | create the project in the directory itself (it may exist and not be empty) |
25
+ | `--description`, `--author`, `--license` | the information of the application |
26
+ | `--with <features>` | the optional features of the template enabled, separated by commas (`lakutata templates` lists them): `i18n`. In a terminal without `--with`, they are chosen |
27
+ | `--package-manager <npm\|pnpm\|yarn\|none>` | the package manager installing the dependencies, the one running the tool by default |
28
+ | `--no-git` | do not initialize a git repository |
29
+ | `--yes` | create the project without confirmation |
30
+
31
+ ```bash
32
+ lakutata create --name my-service --template service --package-manager pnpm --yes
33
+ lakutata create --name my-service --template service --with i18n --yes
34
+ ```
35
+
36
+ The official templates have the feature `i18n`: the messages of the application in several languages
37
+ (`lakutata/com/i18n`), in `src/locales` (`en.json`, `zh-CN.json`), bundled with the code; each request answered in its
38
+ language (the language of the environment for the command line tools and the Electron applications), its validation
39
+ errors too; the scripts `i18n:check` and `i18n:types`.
40
+
41
+ ### `lakutata templates`
42
+
43
+ List the official templates. They are npm packages (`@lakutata/template-<name>`) listed by the catalog package
44
+ `@lakutata/templates`, downloaded from the npm registry of the user (a mirror such as npmmirror works as it does for the
45
+ dependencies): no access to GitHub is needed. The catalog is kept for a day (`--refresh` fetches it again).
46
+
47
+ The version of an official template is the newest one of the major version of the tool. The downloaded templates are
48
+ kept: when the registry cannot be reached, the kept ones are used.
49
+
50
+ A template package has its files in its `template/` directory. The npm packages cannot hold some files under their
51
+ name: `_gitignore`, `_npmrc`… are renamed `.gitignore`, `.npmrc`… when the project is created. The text files are filled
52
+ with the information of the project: `{$APP_NAME}`, `{$APP_ID}`, `{$APP_DESC}`, `{$APP_AUTHOR}`, `{$APP_LICENSE}` and
53
+ `{$LAKUTATA_VERSION}` (the version of the framework).
54
+
55
+ A template has optional features, which `lakutata create --with <features>` enables (or the user chooses in a terminal):
56
+
57
+ - they are declared by the `package.json` of the template package, their names and their descriptions:
58
+ `"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): they are added to the project when the feature is enabled; a JSON file the project has is merged into its
61
+ one (the scripts of `package.json`, the options of `tsconfig.json`);
62
+ - the files of the template have the blocks of the features, the lines between `//@if <feature>` and `//@end` (or
63
+ `//@else`; `//@if !<feature>` when the feature is not enabled), kept when the feature is enabled and removed
64
+ otherwise; the lines of the markers are removed. The markers are comments of their languages: `//@if i18n`,
65
+ `#@if i18n`, `<!--@if i18n-->`, `/*@if i18n*/`.
66
+
67
+ ### `lakutata info`
68
+
69
+ Show the versions of the tool, of the framework (and their latest versions), of Node.js, and of the framework of the
70
+ project of the current directory.
71
+
72
+ ### `lakutata clean [paths...]`
73
+
74
+ Remove paths of the package of the current directory, on every platform (as `rm -rf`, without `shx` or `rimraf`):
75
+ `lakutata clean build dist`. Without paths, the output directories of its `tsconfig.json` are removed (`outDir`, and
76
+ `declarationDir` when it has one, read through the configurations it extends): `"clean": "lakutata clean"`. A missing
77
+ path is skipped; the paths outside of the package, the package itself, `src`, `node_modules`, `.git` and `package.json`
78
+ are never removed. In a workspace, `lakutata run clean` runs the `clean` script of each package.
79
+
80
+ ## Workspaces
81
+
82
+ The projects made of several packages (`app`, `ui`, `proxy`…) are npm workspaces (the `workspaces` of the root
83
+ `package.json`, or a `pnpm-workspace.yaml`). The tool builds and versions their packages; it is the part of lerna the
84
+ projects use, without lerna.
85
+
86
+ ### `lakutata run <script>`
6
87
 
7
- <div align="center">
88
+ Run a script in the packages having it, in the order of their dependencies (a package runs once the packages it depends
89
+ on ran); the packages independent of each other run at the same time. The output is prefixed by the name of the package.
8
90
 
9
- ![node-lts](https://img.shields.io/node/v-lts/lakutata?style=for-the-badge&logo=nodedotjs&color=rgb(128%2C189%2C65))
10
- ![npm](https://img.shields.io/npm/v/lakutata?style=for-the-badge&logo=npm&color=rgb(128%2C189%2C65))
11
- ![npm](https://img.shields.io/npm/dm/lakutata?style=for-the-badge&logo=npm&color=rgb(128%2C189%2C65))
12
- ![NPM](https://img.shields.io/npm/l/lakutata?style=for-the-badge&logo=github&color=rgb(128%2C189%2C65))
13
- ![Codacy grade](https://img.shields.io/codacy/grade/0f16d1c355494415ad7733f8f22f7d36?style=for-the-badge&logo=codacy)
91
+ | Option | |
92
+ |---|---|
93
+ | `--concurrency <n>` | how many packages run at a time, the number of the processors by default |
94
+ | `--parallel` | run all the packages at once, without waiting for their dependencies: the long-running scripts (`lakutata run dev --parallel`) |
95
+ | `--no-bail` | do not stop at the first failure: the packages which do not depend on the failed ones run |
96
+ | `--scope <names...>` | the packages run, by name (`*` wildcards) |
14
97
 
15
- </div>
98
+ ### `lakutata version <bump>`
16
99
 
17
- ## 💫 Description
100
+ Give all the packages the next version (`major`, `minor`, `patch`, `premajor`, `preminor`, `prepatch`, `prerelease`
101
+ with `--preid <id>`, or a version), update the dependencies between them (`^0.0.16` becomes `^0.0.17`: with the `0.x`
102
+ versions a range matches its version only) and the lock file (`npm ci` fails otherwise). The version of the workspace is
103
+ the one of `lerna.json` when there is one, of the root `package.json` otherwise. `--git` commits the changes and tags
104
+ them `v<version>`; `--yes` gives the version without confirmation.
18
105
 
19
- Lakutata is a generic development framework written in TypeScript and designed with IoC principles. Its main objective
20
- is to provide a universal, efficient, and stable development framework. The design goals of Lakutata are not limited to
21
- web application development; it aims to serve as a foundational framework for desktop applications, embedded systems
22
- applications, and web applications. The framework primarily adopts an OOP (Object-Oriented Programming) approach and
23
- encapsulates functionalities such as subprocesses, threads, permission management, and database ORM, enabling the
24
- framework to be used out of the box.
106
+ ### `lakutata add <name>`
25
107
 
26
- In addition, Lakutata also supports the integration of third-party libraries into the application, allowing developers
27
- to freely encapsulate and call third-party modules using Lakutata's dependency injection.
108
+ Add a package to the workspace: `packages/<name>` (without its scope), of the version of the workspace, with its
109
+ `clean`, `build`, `rebuild` and `test` scripts and a test; `--to <package>` makes a package of the workspace depend on it.
110
+ Then `npm install` links it.
28
111
 
29
- ## ✨ Getting started
112
+ - `lakutata add greeting`: a TypeScript package (`src/index.ts` compiled into `build`, its declarations emitted).
113
+ - `lakutata add @acme/capture --native [gyp|cmake|rust]`: a native addon, by its build system:
114
+ - `gyp` (by default): C++ with [node-addon-api](https://github.com/nodejs/node-addon-api), built by node-gyp from
115
+ `binding.gyp`;
116
+ - `cmake`: C++ with node-addon-api, built by [cmake-js](https://github.com/cmake-js/cmake-js) from `CMakeLists.txt`;
117
+ - `rust`: Rust with [napi-rs](https://napi.rs), built by cargo (`Cargo.toml`, `build.rs`, `rust/lib.rs`).
30
118
 
31
- - Install lakutata cli tool
32
- ```shell
33
- npm install -g @lakutata/cli
119
+ Node-API is stable across the versions of Node.js and Electron: the same addon runs in both without being rebuilt.
120
+ The addon is built into `build/Release` (`npm run build:native`, and when the package is installed), loaded by
121
+ node-gyp-build from `src/index.ts`, compiled into `dist`; the C++ ones are built for the Macs with Intel and with Apple
122
+ silicon in one file. `lakutata native` links their libraries; `binding.gyp` and `CMakeLists.txt` also show in their
123
+ comments how the libraries and the options of the build are given: the libraries of the system, pkg-config, the
124
+ static libraries of the package, the dynamic libraries shipped with the addon (copied next to it, found there by its
125
+ rpath), the standard of C++, the options of each platform; a library built by its own Makefile is built before by a
126
+ script (`build:deps`).
127
+ `lakutata package bundle` and `lakutata package exe` ship the addon with the application, its dynamic libraries too. Building
128
+ it needs a C++ toolchain (with CMake for `cmake`), or Rust for `rust`.
129
+
130
+ ### `lakutata native <action> <value>`
131
+
132
+ Change the build of the native addon of the current directory, found by its build file (`binding.gyp`,
133
+ `CMakeLists.txt`, `Cargo.toml`): its text is edited in place, its comments and its layout kept; the sources of the
134
+ addon are not changed. A change already made changes nothing.
135
+
136
+ - `lakutata native link <library>`: link a library:
137
+ - a library of the system: `lakutata native link pcap` (`ws2_32` with `--platform win`);
138
+ - `--pkg-config`: a library found by pkg-config (`lakutata native link libpcap --pkg-config`; not on Windows);
139
+ - `--framework`: a framework of macOS (`lakutata native link CoreFoundation --framework`);
140
+ - a file of the package: a static library (`deps/lib/libfoo.a`; `foo.lib` on Windows) is linked into the addon; a
141
+ dynamic one (`deps/lib/libfoo.dylib`, `libfoo.so`, `foo.dll` with its import library `foo.lib`) is copied next to
142
+ the addon and found there at run time by its rpath (`@loader_path` on macOS, `$ORIGIN` on Linux). On macOS, its
143
+ install name must be `@rpath/libfoo.dylib` (`install_name_tool -id`): the command tells it otherwise;
144
+ - `--crate`: a crate of a Rust addon (`cargo add`).
145
+ - `lakutata native include <directory>`: a directory of headers (C++).
146
+ - `lakutata native define <NAME[=value]>`: a definition of the preprocessor (C++).
147
+
148
+ `--platform mac|linux|win` makes the change for one platform (the files of the libraries give theirs: `.dylib` macOS,
149
+ `.so` Linux, `.dll` and `.lib` Windows, `.a` every platform but Windows); `--target <name>` names the target changed
150
+ when the build file has several. What is written, by build system:
151
+
152
+ | | gyp | CMake | Rust |
153
+ |---|---|---|---|
154
+ | File | `binding.gyp`, or the `.gypi` it includes declaring the target | `CMakeLists.txt` | `.cargo/config.toml` (`[env]`), read by `build.rs` |
155
+ | Library | `libraries` | `target_link_libraries` | `rustc-link-lib` |
156
+ | pkg-config | `<!@(pkg-config ...)` | `pkg_check_modules(... IMPORTED_TARGET ...)` | the `-sys` crates |
157
+ | Framework | `xcode_settings.OTHER_LDFLAGS` | `-framework` in `if(APPLE)` | `rustc-link-lib=framework=` |
158
+ | Dynamic library | `copies`, the rpath | `BUILD_RPATH`, a `POST_BUILD` copy | `rustc-cdylib-link-arg`, a `postbuild:native` copy |
159
+ | 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` |
161
+
162
+ The Rust libraries are given to `build.rs` (by `lakutata add --native rust`), which gives them to cargo for the addon
163
+ only: the flags of rustc would be given to every crate it builds.
164
+
165
+ ### `lakutata list`
166
+
167
+ List the packages, their versions and the packages they depend on.
168
+
169
+ ### From lerna
170
+
171
+ | lerna | lakutata |
172
+ |---|---|
173
+ | `lerna run rebuild` | `lakutata run rebuild` |
174
+ | `lerna version patch --no-git-tag-version --no-push -y` | `lakutata version patch --yes` |
175
+ | `lerna version patch` | `lakutata version patch --git` (the tag is not pushed) |
176
+
177
+ The publication stays `npm publish -w <package>`. The tool does not bump the packages independently, does not write
178
+ changelogs from the commits and does not cache the builds: the workspaces needing it keep lerna (or nx, turborepo) next
179
+ to it.
180
+
181
+ ## Bundles and executables
182
+
183
+ The application of the current directory, compiled (`tsc`, which emits the metadata of the decorators), is packed by
184
+ `@lakutata/builder`: the one installed in the project (`npm install --save-dev @lakutata/builder`, as the templates
185
+ packing their applications do), else the one installed with the tool. Its functions (`bundleProject`,
186
+ `buildExecutable`) pack the applications from the scripts too.
187
+
188
+ ### `lakutata package bundle`
189
+
190
+ Bundle the application and its dependencies into one CommonJS file (esbuild), run by node without `node_modules`:
191
+ `dist/<name>.cjs`, the name being the first `bin` of the `package.json`, or its name without its scope. The entry is the
192
+ `main` of the `package.json` (`--entry` changes it), the bundle is minified with the names of the classes kept
193
+ (`--no-minify`), `import.meta.url` is the URL of the bundle.
194
+
195
+ | Option | |
196
+ |---|---|
197
+ | `--entry <file>` | the compiled entry, the `main` of the `package.json` by default |
198
+ | `--outfile <file>` | the bundle, `dist/<name>.cjs` by default |
199
+ | `--no-minify` | do not minify the bundle |
200
+ | `--external <modules...>` | the modules left out of the bundle, loaded at run time from a `node_modules` next to it |
201
+
202
+ The bundles are CommonJS modules (the executables of Node.js run them): the ES modules of the application are converted,
203
+ without top-level `await` (await in an async function).
204
+
205
+ The native addons (`.node` files) cannot be bundled: their packages are found while the application is bundled (the
206
+ packages holding addons, and the packages loading them with computed paths, such as sharp) and left out of the bundle,
207
+ with what they load at run time (the JavaScript they require, the packages of the shared libraries linked with their
208
+ addons, such as libvips), laid out as in `node_modules`: `dist/<name>.native/`, distributed with the bundle. The tree
209
+ holds the files loaded at run time: the packages of the addons and of the shared libraries have all their files, the
210
+ other packages the JavaScript they load (traced) and their other files (the data they read), the packages loading their
211
+ files by paths which cannot be followed (`require(path.join(__dirname, name))`) all their files; the types, the source
212
+ maps, the TypeScript sources and the documentation of the packages are left out. The addons of
213
+ the application itself (`require('./x.node')`, `createRequire(import.meta.url)('./x.node')`) are there too.
214
+
215
+ The resources of the application, the files it reads at run time (the built pages of a web application, templates,
216
+ data), are declared by the `lakutata.resources` of its `package.json`, as the `extraResources` of electron-builder:
217
+
218
+ ```json
219
+ "lakutata": {"resources": [{"from": "../ui/dist", "to": "ui"}]}
34
220
  ```
35
- - Show available commands
36
- ```shell
37
- lakutata --help
221
+
222
+ `from` is a file or a directory of the project, `to` its path in the resources: `dist/<name>.resources/`, distributed
223
+ with the bundle. The application finds them by `resourcesPath()` of lakutata (`undefined` when it does not run packed,
224
+ `isPackaged()` tells it).
225
+
226
+ ### `lakutata package exe`
227
+
228
+ Make the executable of the application for the platform it runs on, which runs without Node.js installed: the bundle
229
+ embedded in the Node.js binary running the tool (the single executable applications of Node.js), `dist/<name>`
230
+ (`dist/<name>.exe` on Windows), with the code cache of the bundle (V8). The Node.js embedded is the version running the
231
+ tool.
232
+
233
+ With `--runtime bun`, the bundle is compiled by Bun (`bun build --compile --bytecode`, its bytecode is not parsed at
234
+ start) instead: the Bun of the project (the `bun`
235
+ package of npm, `npm install --save-dev bun`), else the one of the system. Its executables are smaller, start faster and
236
+ use less memory; the runtime is Bun's (JavaScriptCore, its implementation of the APIs of Node.js). The bundle and its
237
+ native addons are the ones of the executables of Node.js, which do not change for it. As them, the executables of Bun do
238
+ not load the `.env` and the `bunfig.toml` of the directory they run in (the application loads its `.env`), and the
239
+ mode is the one of their run: Bun replaces `process.env.NODE_ENV` with the mode of its build, the bundle reads it.
240
+
241
+ The executables of the other platforms are made on them, as the applications are built there: their native addons are
242
+ built for them, and they are tried there. The CI gives the machines of the platforms (a matrix of the Linux, macOS and
243
+ Windows runners); the Linux architectures are also made in a container of the architecture (`docker run --platform
244
+ linux/arm64`, as the cross builds of the templates).
245
+
246
+ | Option | |
247
+ |---|---|
248
+ | `--outdir <directory>` | the directory of the executable, `dist` by default |
249
+ | `--runtime <node\|bun>` | the runtime embedded: `node` (by default) or `bun` |
250
+ | `--layout <file\|directory>` | one file (by default), or a directory: `dist/<name>/` holding the executable, its native addons (`native/`) and its resources (`resources/`), loaded from there without extraction (the installers, the images) |
251
+ | `--entry`, `--no-minify`, `--external` | as `lakutata package bundle` |
252
+
253
+ The native addons and the resources are embedded in the executable (`--layout file`): at its first run, it extracts them
254
+ into its cache directory (`~/.cache/<name>`, `~/Library/Caches/<name>` on macOS, `%LOCALAPPDATA%\<name>\Cache` on Windows,
255
+ or `LAKUTATA_NATIVE_DIR`; the temporary directory when it cannot be written), in a directory named after their content:
256
+ the next runs load them from there, the versions of the program do not share it. The addons need the system libraries they were built for (the
257
+ glibc version of the Linux prebuilt addons).
258
+
259
+ The executables of macOS are signed ad hoc. The ones of Windows made by Node.js keep the signature of `node.exe`, which
260
+ does not match anymore: sign them before distributing them.
261
+
262
+ ### `lakutata package installer`
263
+
264
+ Make the installers of the application for the platform it runs on (as electron-builder): its executable in a directory
265
+ (`lakutata package exe --layout directory`) installed with its native addons and its resources, its program in the PATH,
266
+ its service registered. The installers of the other platforms are made on them (the ones of Linux in a container).
267
+ They are configured by the `lakutata.installer` of the `package.json`:
268
+
269
+ ```json
270
+ "lakutata": {
271
+ "installer": {
272
+ "service": {"env": {"PORT": "8080"}},
273
+ "linux": {"targets": ["deb", "rpm", "tar.gz"], "depends": []}
274
+ }
275
+ }
276
+ ```
277
+
278
+ | Option | |
279
+ |---|---|
280
+ | `name` | the name of the package (lower case), the one of the program by default |
281
+ | `appId` | the identifier of the application (reverse DNS, `com.acme.app`), its name by default: the identifier of the package of macOS and the label of its service, the key of its uninstaller and of its upgrades on Windows |
282
+ | `productName` | the name shown to the users (the installers, the programs of Windows), its name by default |
283
+ | `description`, `maintainer`, `homepage`, `license`, `vendor` | the ones of the `package.json` by default (the maintainer is its author) |
284
+ | `runtime` | the runtime of the executable: `node` (by default) or `bun`; `electron` for an Electron application (below) |
285
+ | `addToPath` | the program in the PATH (`/usr/bin/<program>`, the PATH of the machine on Windows), by default |
286
+ | `service` | `true` or the options of the service (below), none by default |
287
+ | `linux.targets` | `deb`, `rpm`, `archlinux`, `tar.gz` on the systems of the glibc (`deb`, `rpm`, `tar.gz` by default), `apk`, `tar.gz` on Alpine (musl) |
288
+ | `linux.depends`, `linux.recommends`, `linux.section`, `linux.priority` | the packages of the system it needs, recommends, its section and priority (deb) |
289
+ | `mac.targets` | `pkg`, `tar.gz` (both by default) |
290
+ | `win.targets` | `nsis`, `msi`, `zip` (all by default) |
291
+ | `electron` | the configuration of electron-builder of an Electron application, merged over the one made from these options |
292
+
293
+ The packages of Linux are made by nFPM (downloaded once into the cache of lakutata, `LAKUTATA_NFPM` gives another one),
294
+ in `dist/installer` (`--outdir`): the application is installed in `/opt/<name>`, the C++ library of the runtime is a
295
+ dependency. The executables link the C library of the system they are made on: the packages of the systems of the glibc
296
+ are made on one of them, the `apk` packages on Alpine, with Bun (`"runtime": "bun"`) when the application has native
297
+ addons: the executables of Node.js do not load them on musl.
298
+
299
+ The installers of macOS are made by its tools (`pkgbuild`, `productbuild`): the `pkg` package installs the application in
300
+ `/usr/local/lib/<name>`, its program in `/usr/local/bin`; the packages of macOS are not removed by the system:
301
+ `sudo /usr/local/lib/<name>/uninstall` removes it. They are signed ad hoc (the Developer ID signature and the
302
+ notarization, which the distribution out of the machines of the organization needs, are not made yet).
303
+
304
+ The installers of Windows are made on Windows: the installer of NSIS (`<name>-<version>-<arch>-setup.exe`) and the
305
+ package of Windows Installer (`.msi`, made by WiX, for the deployments of the organizations) install the application in
306
+ `C:\Program Files\<name>`, its data in `C:\ProgramData\<name>`; they are removed as the programs of Windows. Their tools
307
+ are downloaded once into the cache of lakutata (NSIS 3, WiX 3, WinSW; `LAKUTATA_NSIS`, `LAKUTATA_WIX`, `LAKUTATA_WINSW`
308
+ give other ones). The executables keep the signature of Node.js, which does not match anymore: sign them (signtool)
309
+ before distributing them.
310
+
311
+ The service runs the application at the start of the system: systemd (`/usr/lib/systemd/system/<service>.service`),
312
+ OpenRC on Alpine (`/etc/init.d/<service>`), launchd on macOS (`/Library/LaunchDaemons/<appId>.plist`), or WinSW on Windows
313
+ (`<name>-service.exe` next to the application, a service of Windows: `Restart-Service <service>`). It is started by the
314
+ installation, restarted by the upgrades, stopped and disabled before the removal.
315
+
316
+ | Service option | |
317
+ |---|---|
318
+ | `name`, `description` | the ones of the package by default |
319
+ | `args` | the arguments of the application |
320
+ | `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 the administrators change (kept by the upgrades) |
321
+ | `user` | its user: a system user named after the package by default (`_<name>` on macOS, hidden), created by the installation, or `root`; on Windows its virtual account by default (`NT SERVICE\<service>`), `LocalService`, `NetworkService` or `LocalSystem` |
322
+ | `restart` | `on-failure` (by default), `always` or `no` |
323
+ | `autoStart` | enabled and started by the installation, by default |
324
+
325
+ Its working directory is `/var/lib/<name>` (`/usr/local/var/lib/<name>` on macOS, its log `/usr/local/var/log/<name>.log`;
326
+ `C:\ProgramData\<name>` on Windows, its logs in `logs`), owned by its user (its data). `SIGTERM` ends it gracefully (on
327
+ Windows, the stop of the service: Ctrl+C, `SIGINT` for Node.js).
328
+
329
+ The executables load the environment file given by the `LAKUTATA_ENV_FILE` environment variable before the application
330
+ starts (the service of Windows, whose wrapper has none): its lines `NAME=value` or `NAME="value"`, its comments (`#`).
331
+
332
+ The installers run the scripts of the application (files of the project), as the ones of electron-builder: the ones of a
333
+ platform, which its installers run, replaced by the ones of an installer (a moment each), the native ones of a package of
334
+ Linux, the file of NSIS included by its installer:
335
+
336
+ ```json
337
+ "installer": {
338
+ "linux": {
339
+ "scripts": {"preinstall": "build/linux/preinstall.sh", "postinstall": "build/linux/postinstall.sh", "preremove": "build/linux/preremove.sh", "postremove": "build/linux/postremove.sh"},
340
+ "rpm": {"scripts": {"postinstall": "build/linux/rpm-postinstall.sh"}},
341
+ "deb": {"nativeScripts": {"postinstall": "build/linux/postinst.sh"}}
342
+ },
343
+ "mac": {"scripts": {"postinstall": "build/mac/postinstall.sh"}},
344
+ "win": {"scripts": {"postinstall": "build/win/postinstall.ps1"}, "nsis": {"include": "build/win/installer.nsh"}}
345
+ }
38
346
  ```
39
347
 
40
- ## 🌎 License
348
+ | Script | |
349
+ |---|---|
350
+ | `preinstall` | before the files of the application are installed (on Windows Installer, an upgrade has removed the version it replaces) |
351
+ | `postinstall` | after they are installed, before the service is started (on an upgrade, the one of the version replaced may still run) |
352
+ | `preremove` | before the removal, once the service is stopped |
353
+ | `postremove` | after the files are removed |
354
+
355
+ They are given what the installer does: `install` or `upgrade` (`preinstall`, `postinstall`), `remove` (`preremove`,
356
+ `postremove`; an upgrade runs no removal script), as their first argument (`$1`, `$args[0]` in PowerShell), and the
357
+ directory of the application (`LAKUTATA_INSTALL_DIR`). They run as root (as the system on Windows). Their failure is the
358
+ one of the installation (or of the removal). Each package manager tells it in its own way (dpkg `configure <version>`,
359
+ rpm the number of the versions, apk and pacman their upgrade scripts): the installers translate them.
360
+
361
+ - Linux (`linux.scripts`, `linux.<deb|rpm|apk|archlinux>.scripts`): scripts run by the interpreter of their first line
362
+ (`#!/bin/sh` by default), embedded in the scripts of the packages. `linux.<package>.nativeScripts` are run as the
363
+ package manager runs the scripts of the package, with its own arguments (`preinstall`, `postinstall`, `preremove`,
364
+ `postremove`; `preupgrade`, `postupgrade` for apk and archlinux).
365
+ - macOS (`mac.scripts`, `mac.pkg.scripts`): sh scripts as on Linux; the removal ones are run by the `uninstall` script of
366
+ the application (the packages of macOS are not removed by the system).
367
+ - Windows (`win.scripts`, `win.<nsis|msi>.scripts`): scripts of PowerShell (`.ps1`, run by Windows PowerShell; Windows
368
+ Installer runs them by a command line, which they must fit in: about 23 KB each). `win.nsis.include` is a file of NSIS
369
+ (`.nsh`) included by the installer of NSIS, whose macros are inserted: `customHeader`, `customInit`, `customInstall` (at
370
+ the end of the installation), `customUnInit`, `customUnInstall` (at the start of the removal).
371
+ - The archives (`tar.gz`, `zip`) run none.
372
+
373
+ The installers of an Electron application (`"runtime": "electron"`) are made by electron-builder (a dependency of the
374
+ project): its main process bundled with its dependencies (Electron left out) in the archive of the application, its
375
+ native addons and its resources (`lakutata.resources`: its renderer, its preload script, read from `resourcesPath()`)
376
+ next to it, in the resources of Electron. Its installers are the targets of electron-builder (`deb` on Linux, `dmg` on
377
+ macOS, `nsis` on Windows by default: `linux.targets`, `mac.targets`, `win.targets`); `name`, `appId`, `productName`, its
378
+ description, maintainer, homepage and license are given to electron-builder, `electron` gives the rest (its icons, its
379
+ file associations, its signature, its updates…). It is not a service. Its scripts are run by:
380
+
381
+ | Installer | Scripts |
382
+ |---|---|
383
+ | `deb`, `rpm` (the packages of fpm) | all (embedded after the scripts of electron-builder) |
384
+ | `pkg` (macOS) | `preinstall`, `postinstall` (an application of macOS is removed by its user) |
385
+ | `nsis` (Windows) | `preinstall`, `postinstall`, `preremove` (its uninstaller ends with the removal of the files); the file of NSIS of `win.nsis.include` defines the other macros |
386
+ | the others (`AppImage`, `dmg`, `portable`, `msi`…) | none |
387
+
388
+ The packages of fpm made on Linux arm64 need the fpm of the system (`gem install fpm`, `USE_SYSTEM_FPM=true`): the one
389
+ electron-builder downloads is the one of x64. On Windows arm64, the installers of NSIS filter the executables by the BCJ
390
+ filter (`ELECTRON_BUILDER_7Z_FILTER`): the ARM64 one, which 7-Zip chooses, is not extracted by them.
391
+
392
+ | Command option | |
393
+ |---|---|
394
+ | `--target <targets...>` | the installers made, the ones of the configuration by default |
395
+ | `--outdir <directory>` | the directory of the installers, `dist/installer` by default |
396
+ | `--entry`, `--no-minify`, `--external` | as `lakutata package bundle` |
397
+
398
+ ## Migrations
399
+
400
+ ### `lakutata migration <action>`
401
+
402
+ The migrations of the databases of the application (its Database components and providers): `generate`, `run`, `revert`
403
+ and `show` run the script of the package building and starting the application (`dev` by default) with an environment
404
+ variable (`MIGRATION_GENERATE`, `MIGRATION_RUN`, `MIGRATION_REVERT`, `MIGRATION_SHOW`): the application connects its
405
+ databases with their options, without synchronizing their schemas nor running their migrations, does the command,
406
+ tells what it did and exits, without starting its components nor its entrypoints. `create` writes a file.
407
+
408
+ | Action | |
409
+ |---|---|
410
+ | `generate` | the migrations of the changes of the entities: the application compares them with its databases and writes the migrations into the directory, one file `<timestamp>-<name of the database>.ts` per database changed (`cross-env MIGRATION_GENERATE=./src/migrations npm run dev` of lakutata 2.x); without change, nothing is generated and the command fails |
411
+ | `create <name>` | an empty migration, written by hand (`up` and `down`): `<timestamp>-<name>.ts`, its class `<Name><timestamp>` |
412
+ | `show` | the migrations of the options of the databases, run `[X]` or pending `[ ]` |
413
+ | `run` | the pending migrations (`up`) |
414
+ | `revert` | the last migration run (`down`), one at a time; the application having several databases, `--database` is required |
415
+
416
+ | Option | |
417
+ |---|---|
418
+ | `--dir <directory>` | the directory of the migrations, relative to the package, `src/migrations` by default (`generate`, `create`) |
419
+ | `--script <script>` | the script building and starting the application, `dev` by default |
420
+ | `--package <name>` | the package of the workspace of the application, run from the workspace (the current directory by default) |
421
+ | `--database <name>` | the database: the name of its Database component or provider, all by default (`MIGRATION_DATABASE`) |
422
+ | `--transaction <mode>` | the transactions of the migrations run or reverted: `all` (one, by default), `each` or `none` (`MIGRATION_TRANSACTION`) |
423
+ | `--fake` | mark the migrations as run or reverted without executing them (`MIGRATION_FAKE`) |
424
+
425
+ The migrations are compiled with the application and given to the options of their database (`migrations: [...]`,
426
+ run when it connects with `migrationsRun: true`). The commands fail (exit code 1) when the application has no database
427
+ (but `generate`, which generates nothing), when the database given is not one of the application, and when a migration
428
+ fails.
429
+
430
+ ## Languages
431
+
432
+ ### `lakutata i18n <action> [locale]`
433
+
434
+ The messages of the languages of the application (`lakutata/com/i18n`), in a directory (`--dir`, `locales` by
435
+ default; several separated by commas): a file by language (`zh-CN.json`) or a directory by language (`zh-CN/`).
436
+
437
+ - `lakutata i18n check`: checks the messages of the languages against the ones of the default language (`--default`,
438
+ `en` by default), and fails on their errors:
439
+ - errors: a syntax error of ICU MessageFormat, a key the default language does not have, an argument the default
440
+ message does not have (missing when the message is formatted), a validation message of an unknown code or with the
441
+ variables of another code;
442
+ - warnings: a message missing (the one of a fallback is given), an argument of the default message not used, a
443
+ message the same as the default one (not translated yet). `--strict` fails on them too, for the CI.
444
+ - `lakutata i18n types`: declares the keys of the messages of the default language and their arguments
445
+ (`--out`, `src/i18n.d.ts` by default): a key misspelled or an argument missing is then an error of the compilation.
446
+ `--module @lakutata/i18n` declares them for the applications importing `@lakutata/i18n` rather than
447
+ `lakutata/com/i18n`.
448
+ - `lakutata i18n add <locale>`: adds a language, made of the messages of the default language, as a file or a directory
449
+ as the default language has (its validation messages left: the language has its built-in ones). They are to be
450
+ translated; `check` tells the ones which are not.
451
+
452
+ ## The language of the tool
453
+
454
+ The help of the tool (the descriptions of its commands and of their options) and its prompts are in English, Chinese
455
+ (Simplified, `zh-CN`) or Chinese (Traditional, `zh-TW`): the language of `LAKUTATA_LANG` (`LAKUTATA_LANG=zh-CN`), then
456
+ of the environment (`LC_ALL`, `LC_MESSAGES`, `LANG`), then of the system; English otherwise. The names of the commands
457
+ and of the options, the results and the errors are in English.
458
+
459
+ ## Environment
460
+
461
+ | Variable | |
462
+ |---|---|
463
+ | `LAKUTATA_NPM_REGISTRY` | the npm registry of the templates (`npm_config_registry`, or `https://registry.npmjs.org`) |
464
+ | `LAKUTATA_GITHUB_DOWNLOAD` | a mirror of GitHub for the `github:` templates (`https://github.com`) |
465
+ | `LAKUTATA_CACHE_DIR` | the directory of the cache (`$XDG_CACHE_HOME/lakutata`, or `~/.cache/lakutata`) |
466
+ | `LAKUTATA_LANG` | the language of the help and of the prompts of the tool (`zh-CN`, `zh-TW`, `en`), the one of the environment by default |
41
467
 
42
- Lakutata is [MIT licensed](LICENSE).
468
+ The tool is itself a lakutata application: its commands are the CLI actions of a controller, served by the commander
469
+ adapter of the entrypoint.
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ //Before the application changes the environment
3
+ import './lib/Environment.js';
4
+ import { Application } from 'lakutata';
5
+ import { config } from './Config.js';
6
+ Application.run(config());
@@ -0,0 +1,53 @@
1
+ import { buildEntrypoints } from 'lakutata/com/entrypoint';
2
+ import { commanderCLIEntrypoint } from 'lakutata/adapter/commander';
3
+ import { buildI18nOptions, commanderTranslator } from 'lakutata/com/i18n';
4
+ import zhCN from './locales/zh-CN.json' with { type: 'json' };
5
+ import zhTW from './locales/zh-TW.json' with { type: 'json' };
6
+ import { CommandLineController } from './controllers/CommandLineController.js';
7
+ import { WorkspaceController } from './controllers/WorkspaceController.js';
8
+ import { PackController } from './controllers/PackController.js';
9
+ import { MigrationController } from './controllers/MigrationController.js';
10
+ import { NativeController } from './controllers/NativeController.js';
11
+ import { I18nController } from './controllers/I18nController.js';
12
+ import { LANGUAGE_VARIABLE, LanguageMiddleware } from './lib/Language.js';
13
+ import { toolPackage } from './lib/Versions.js';
14
+ /**
15
+ * The controllers of the commands of the tool
16
+ */
17
+ export const CONTROLLERS = [CommandLineController, WorkspaceController, PackController, MigrationController, NativeController, I18nController];
18
+ /**
19
+ * The messages of the tool in the languages besides English (its texts in the code): its help, its prompts
20
+ */
21
+ /**
22
+ * The groups of commands: lakutata package --help lists the commands of the group package
23
+ */
24
+ export const COMMAND_GROUPS = {
25
+ package: 'Package the compiled application: into one JavaScript file, an executable or its installers'
26
+ };
27
+ export const MESSAGES = { 'zh-CN': zhCN, 'zh-TW': zhTW };
28
+ /**
29
+ * The application of the tool
30
+ */
31
+ export function config() {
32
+ const tool = toolPackage();
33
+ return {
34
+ id: 'cli.lakutata.app',
35
+ name: 'lakutata-cli',
36
+ components: {
37
+ //The help and the prompts in the language of the user (LAKUTATA_LANG, LC_ALL, LANG)
38
+ i18n: buildI18nOptions({ messages: MESSAGES }),
39
+ entrypoint: buildEntrypoints({
40
+ controllers: CONTROLLERS,
41
+ middlewares: [LanguageMiddleware],
42
+ cli: commanderCLIEntrypoint({
43
+ bin: 'lakutata',
44
+ description: tool.description,
45
+ version: tool.version,
46
+ groups: COMMAND_GROUPS,
47
+ translate: commanderTranslator({ environment: LANGUAGE_VARIABLE })
48
+ })
49
+ })
50
+ },
51
+ bootstrap: ['entrypoint']
52
+ };
53
+ }