@lakutata/cli 3.1.5 → 3.1.6

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.
@@ -70,7 +70,7 @@ export class NwjsController extends Controller {
70
70
  done(`NW.js ${release.version}: Node.js ${release.node}, Chromium ${release.chromium}`);
71
71
  step(`Runs on ${systemsOf(release)}`);
72
72
  if (input.download) {
73
- const runtime = await downloadNwjs({ version: release.version, flavor: 'sdk' });
73
+ const runtime = await downloadNwjs({ version: release.version, flavor: 'sdk', progress: (line) => step(`Downloading ${line}`) });
74
74
  done(`Downloaded NW.js ${runtime.version} (sdk, ${runtime.platform})`);
75
75
  }
76
76
  return undefined;
@@ -82,7 +82,7 @@ export class NwjsController extends Controller {
82
82
  step(`Native addons built for NW.js ${stage.release.version} (${stage.platform}): ${stage.addons.rebuilt.join(', ')}`);
83
83
  if (stage.addons.renamed.length)
84
84
  step(`Native addons loading the Node.js of NW.js (node.dll): ${stage.addons.renamed.join(', ')}`);
85
- const runtime = await downloadNwjs({ version: stage.release.version, flavor: input.flavor });
85
+ const runtime = await downloadNwjs({ version: stage.release.version, flavor: input.flavor, progress: (line) => step(`Downloading ${line}`) });
86
86
  step(`NW.js ${runtime.version} (${runtime.flavor}, ${runtime.platform}): Node.js ${runtime.node}, Chromium ${runtime.chromium.split('.')[0]}`);
87
87
  const code = await new Promise((resolve, reject) => {
88
88
  const child = spawn(runtime.executable, [stage.directory, ...input.args ?? []], { stdio: 'inherit' });
@@ -68,7 +68,7 @@ export class PackController extends Controller {
68
68
  }
69
69
  async installer(input) {
70
70
  const { buildInstaller } = await loadBuilder(process.cwd());
71
- const result = await buildInstaller({ project: process.cwd(), targets: input.target, outdir: input.outdir, entry: input.entry, minify: input.minify, external: input.external, nodeProgram: input.nodeProgram, arch: input.arch });
71
+ const result = await buildInstaller({ project: process.cwd(), targets: input.target, outdir: input.outdir, entry: input.entry, minify: input.minify, external: input.external, nodeProgram: input.nodeProgram, arch: input.arch, progress: (line) => step(`Downloading ${line}`) });
72
72
  if (result.nwjs) {
73
73
  step(`NW.js ${result.nwjs.runtime.version} (${result.nwjs.runtime.platform}): ${path.basename(result.nwjs.directory)}`);
74
74
  if (result.nwjs.stage.addons.rebuilt.length)
@@ -19,6 +19,10 @@ __decorate([
19
19
  Expect(DTO.String().optional().pattern(/^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/).description('The ID of the application (a package name), its name in lower case by default')),
20
20
  __metadata("design:type", String)
21
21
  ], CreateProjectDTO.prototype, "id", void 0);
22
+ __decorate([
23
+ Expect(DTO.String().optional().pattern(/^[a-zA-Z][a-zA-Z0-9_]*(\.[a-zA-Z][a-zA-Z0-9_]*)+$/).description('The id of the application on the mobile systems (reverse domain name: com.acme.shop), for the mobile templates: com.example.<name> by default, which the stores refuse')),
24
+ __metadata("design:type", String)
25
+ ], CreateProjectDTO.prototype, "bundleId", void 0);
22
26
  __decorate([
23
27
  Expect(DTO.String().optional().default('default').description('The template: the name of an official template (lakutata templates lists them), npm:<package>, github:<owner>/<repo> or a directory')),
24
28
  __metadata("design:type", String)
@@ -0,0 +1,25 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { DTO } from 'lakutata';
11
+ import { Expect } from 'lakutata/decorator/dto';
12
+ export class MobileDeployDTO extends DTO {
13
+ }
14
+ __decorate([
15
+ Expect(DTO.String().valid('android', 'ios', 'harmony').required().description('The system: android (an emulator or a device, the debug build of the application), ios (a simulator) or harmony (an emulator or a device, the debug build of the application)')),
16
+ __metadata("design:type", String)
17
+ ], MobileDeployDTO.prototype, "platform", void 0);
18
+ __decorate([
19
+ Expect(DTO.String().optional().description('The emulator or the device of Android (its serial, adb devices) or of HarmonyOS (its target, hdc list targets), the simulator of iOS (its UDID or its name, xcrun simctl list); the one running by default')),
20
+ __metadata("design:type", String)
21
+ ], MobileDeployDTO.prototype, "device", void 0);
22
+ __decorate([
23
+ Expect(DTO.Boolean().optional().default(false).description('Watch the files of the application: when they change, run its build script (npm run build) and deploy it again, until Ctrl+C')),
24
+ __metadata("design:type", Boolean)
25
+ ], MobileDeployDTO.prototype, "watch", void 0);
@@ -0,0 +1,21 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { DTO } from 'lakutata';
11
+ import { Expect } from 'lakutata/decorator/dto';
12
+ export class MobileNodeDTO extends DTO {
13
+ }
14
+ __decorate([
15
+ Expect(DTO.String().valid('android', 'ios', 'harmony').required().description('The system the libnode is downloaded for: android, ios or harmony')),
16
+ __metadata("design:type", String)
17
+ ], MobileNodeDTO.prototype, "platform", void 0);
18
+ __decorate([
19
+ Expect(DTO.String().optional().description('The architectures of Android downloaded for, separated by commas (arm64-v8a,armeabi-v7a,x86_64); arm64-v8a,x86_64 by default')),
20
+ __metadata("design:type", String)
21
+ ], MobileNodeDTO.prototype, "abis", void 0);
@@ -0,0 +1,21 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { DTO } from 'lakutata';
11
+ import { Expect } from 'lakutata/decorator/dto';
12
+ export class MobileRunDTO extends DTO {
13
+ }
14
+ __decorate([
15
+ Expect(DTO.String().valid('android', 'ios', 'harmony').required().description('The system: android (an emulator or a device), ios (a simulator) or harmony (an emulator or a device)')),
16
+ __metadata("design:type", String)
17
+ ], MobileRunDTO.prototype, "platform", void 0);
18
+ __decorate([
19
+ Expect(DTO.String().optional().description('The emulator or the device of Android (its serial, adb devices) or of HarmonyOS (its target, hdc list targets), the simulator of iOS (its UDID or its name, xcrun simctl list devices); the one running by default, else the newest iPhone for iOS')),
20
+ __metadata("design:type", String)
21
+ ], MobileRunDTO.prototype, "device", void 0);
@@ -0,0 +1,25 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { DTO } from 'lakutata';
11
+ import { Expect } from 'lakutata/decorator/dto';
12
+ export class MobileStageDTO extends DTO {
13
+ }
14
+ __decorate([
15
+ Expect(DTO.String().valid('android', 'ios', 'harmony').required().description('The system the Node.js project is made for: android, ios or harmony')),
16
+ __metadata("design:type", String)
17
+ ], MobileStageDTO.prototype, "platform", void 0);
18
+ __decorate([
19
+ Expect(DTO.Boolean().optional().default(true).description('Minify the bundle (true by default)')),
20
+ __metadata("design:type", Boolean)
21
+ ], MobileStageDTO.prototype, "minify", void 0);
22
+ __decorate([
23
+ Expect(DTO.String().optional().description('The architectures of Android the native addons are built for, separated by commas (arm64-v8a,x86_64); those of the libnode by default')),
24
+ __metadata("design:type", String)
25
+ ], MobileStageDTO.prototype, "abis", void 0);
@@ -119,6 +119,23 @@ let ProjectCreator = class ProjectCreator extends Component {
119
119
  await writeFile(target, filled);
120
120
  }
121
121
  }
122
+ /**
123
+ * Whether a template (its files, those of its features) holds a field ({$APP_BUNDLE_ID}…)
124
+ * @param template
125
+ * @param field
126
+ */
127
+ async uses(template, field) {
128
+ for (const root of [template.root, template.featuresDirectory]) {
129
+ if (!root || !existsSync(root))
130
+ continue;
131
+ for (const file of await listFiles(root)) {
132
+ const content = await readFile(path.join(root, file));
133
+ if (isText(content) && content.toString('utf8').includes(field))
134
+ return true;
135
+ }
136
+ }
137
+ return false;
138
+ }
122
139
  /**
123
140
  * Get the files of a template
124
141
  * @param source
@@ -151,6 +168,7 @@ let ProjectCreator = class ProjectCreator extends Component {
151
168
  await this.fill(plan.directory, files, {
152
169
  $APP_NAME: plan.name,
153
170
  $APP_ID: plan.id,
171
+ $APP_BUNDLE_ID: plan.bundleId,
154
172
  $APP_DESC: plan.description,
155
173
  $APP_AUTHOR: plan.author,
156
174
  $APP_LICENSE: plan.license,
@@ -34,7 +34,8 @@ export const BUILTIN_TEMPLATES = [
34
34
  { name: 'electron-react', description: 'A desktop application: Electron, its main process serving a React renderer over IPC', package: '@lakutata/template-electron-react', features: ['i18n'] },
35
35
  { name: 'electron-vue', description: 'A desktop application: Electron, its main process serving a Vue renderer over IPC', package: '@lakutata/template-electron-vue', features: ['i18n'] },
36
36
  { name: 'nwjs-react', description: 'A desktop application: NW.js, its background script serving a React user interface isolated in a webview', package: '@lakutata/template-nwjs-react', features: ['i18n', 'win7'] },
37
- { name: 'nwjs-vue', description: 'A desktop application: NW.js, its background script serving a Vue user interface isolated in a webview', package: '@lakutata/template-nwjs-vue', features: ['i18n', 'win7'] }
37
+ { name: 'nwjs-vue', description: 'A desktop application: NW.js, its background script serving a Vue user interface isolated in a webview', package: '@lakutata/template-nwjs-vue', features: ['i18n', 'win7'] },
38
+ { name: 'mobile-react', description: 'A mobile application (Android, iOS, HarmonyOS): React Native, the Node.js of the application serving its user interface', package: '@lakutata/template-mobile-react', features: ['i18n'] }
38
39
  ];
39
40
  /**
40
41
  * How long the catalog is kept, 1 day
@@ -7,6 +7,7 @@
7
7
  "options": {
8
8
  "name": "应用的名称",
9
9
  "id": "应用的 ID(包名),默认是名称的小写形式",
10
+ "bundleId": "应用在手机系统上的标识(反向域名:com.acme.shop),用于手机模板:默认是 com.example.<名称>,应用商店不接受",
10
11
  "template": "模板:官方模板的名称(lakutata templates 会列出)、npm:<包名>、github:<所有者>/<仓库> 或一个目录",
11
12
  "path": "在哪个目录下创建项目目录",
12
13
  "init": "直接在该目录中创建项目,目录可以已存在且非空",
@@ -184,6 +185,47 @@
184
185
  }
185
186
  }
186
187
  },
188
+ "mobile": {
189
+ "description": "React Native 手机应用(Android、iOS、鸿蒙):下载它的 libnode,生成它的 Node.js 项目,在模拟器上运行应用,开发时部署到已安装的应用里",
190
+ "node": {
191
+ "description": "从 lakutata/libnode 的 Release 下载一个系统(android、ios、harmony)的 libnode(LAKUTATA_LIBNODE_MIRROR 指定镜像),只下载一次:保存在 lakutata 的缓存中,放到 packages/ipc/native/node/out/<platform>",
192
+ "arguments": {
193
+ "platform": "libnode 面向的系统:android、ios 或 harmony"
194
+ },
195
+ "options": {
196
+ "abis": "Android 的架构,用逗号分隔(arm64-v8a,armeabi-v7a,x86_64);默认是 arm64-v8a,x86_64"
197
+ }
198
+ },
199
+ "stage": {
200
+ "description": "为一个系统(android、ios、harmony)生成手机应用(packages/app)的 Node.js 项目,放到系统的原生工程读取它的位置,并用这个系统的 libnode 编译原生插件",
201
+ "arguments": {
202
+ "platform": "Node.js 项目面向的系统:android、ios 或 harmony"
203
+ },
204
+ "options": {
205
+ "minify": "压缩单文件包(默认为 true)",
206
+ "abis": "为哪些 Android 架构编译原生插件,用逗号分隔(arm64-v8a,x86_64);默认是 libnode 的那些架构"
207
+ }
208
+ },
209
+ "run": {
210
+ "description": "用原生工程构建一个系统(android、ios、harmony)的调试版应用,安装到模拟器或设备上并启动,界面由 Metro(npm start)提供",
211
+ "arguments": {
212
+ "platform": "系统:android(模拟器或设备)、ios(模拟器)或 harmony(模拟器或设备)"
213
+ },
214
+ "options": {
215
+ "device": "Android 的模拟器或设备(序列号,见 adb devices)、鸿蒙的模拟器或设备(见 hdc list targets)、iOS 的模拟器(UDID 或名称,见 xcrun simctl list devices);默认是正在运行的那个,iOS 没有时用最新的 iPhone"
216
+ }
217
+ },
218
+ "deploy": {
219
+ "description": "生成手机应用的 Node.js 项目,放进一个系统(android、ios、harmony)的模拟器或设备上已安装的调试版应用,再重新启动应用(开发时不用重新安装)",
220
+ "arguments": {
221
+ "platform": "系统:android(模拟器或设备,应用的调试版)、ios(模拟器)或 harmony(模拟器或设备,应用的调试版)"
222
+ },
223
+ "options": {
224
+ "device": "Android 的模拟器或设备(序列号,见 adb devices)、鸿蒙的模拟器或设备(见 hdc list targets)、iOS 的模拟器(UDID 或名称,见 xcrun simctl list);默认是正在运行的那个",
225
+ "watch": "监视应用的文件:有变化就执行它的 build 脚本(npm run build)并重新部署,直到按 Ctrl+C"
226
+ }
227
+ }
228
+ },
187
229
  "i18n": {
188
230
  "description": "检查各语言的翻译、声明键名的类型,或添加一种语言",
189
231
  "arguments": {
@@ -227,6 +269,7 @@
227
269
  "title": "项目",
228
270
  "name": "名称",
229
271
  "id": "ID",
272
+ "bundleId": "应用标识(Bundle ID)",
230
273
  "description": "描述",
231
274
  "author": "作者",
232
275
  "license": "许可证",
@@ -7,6 +7,7 @@
7
7
  "options": {
8
8
  "name": "應用程式的名稱",
9
9
  "id": "應用程式的 ID(套件名稱),預設為名稱的小寫形式",
10
+ "bundleId": "應用程式在手機系統上的識別碼(反向網域名稱:com.acme.shop),用於手機範本:預設是 com.example.<名稱>,應用程式商店不接受",
10
11
  "template": "範本:官方範本的名稱(lakutata templates 會列出)、npm:<套件名稱>、github:<擁有者>/<儲存庫> 或一個目錄",
11
12
  "path": "在哪個目錄下建立專案目錄",
12
13
  "init": "直接在該目錄中建立專案,目錄可以已存在且非空",
@@ -184,6 +185,47 @@
184
185
  }
185
186
  }
186
187
  },
188
+ "mobile": {
189
+ "description": "React Native 手機應用程式(Android、iOS、鴻蒙):下載它的 libnode,產生它的 Node.js 專案,在模擬器上執行應用程式,開發時部署到已安裝的應用程式裡",
190
+ "node": {
191
+ "description": "從 lakutata/libnode 的 Release 下載一個系統(android、ios、harmony)的 libnode(LAKUTATA_LIBNODE_MIRROR 指定鏡像),只下載一次:保存在 lakutata 的快取中,放到 packages/ipc/native/node/out/<platform>",
192
+ "arguments": {
193
+ "platform": "libnode 對應的系統:android、ios 或 harmony"
194
+ },
195
+ "options": {
196
+ "abis": "Android 的架構,以逗號分隔(arm64-v8a,armeabi-v7a,x86_64);預設是 arm64-v8a,x86_64"
197
+ }
198
+ },
199
+ "stage": {
200
+ "description": "為一個系統(android、ios、harmony)產生手機應用程式(packages/app)的 Node.js 專案,放到系統的原生專案讀取它的位置,並用這個系統的 libnode 編譯原生外掛",
201
+ "arguments": {
202
+ "platform": "Node.js 專案對應的系統:android、ios 或 harmony"
203
+ },
204
+ "options": {
205
+ "minify": "壓縮單一檔案包(預設為 true)",
206
+ "abis": "為哪些 Android 架構編譯原生外掛,以逗號分隔(arm64-v8a,x86_64);預設是 libnode 的那些架構"
207
+ }
208
+ },
209
+ "run": {
210
+ "description": "用原生專案建置一個系統(android、ios、harmony)的除錯版應用程式,安裝到模擬器或裝置上並啟動,介面由 Metro(npm start)提供",
211
+ "arguments": {
212
+ "platform": "系統:android(模擬器或裝置)、ios(模擬器)或 harmony(模擬器或裝置)"
213
+ },
214
+ "options": {
215
+ "device": "Android 的模擬器或裝置(序號,見 adb devices)、鴻蒙的模擬器或裝置(見 hdc list targets)、iOS 的模擬器(UDID 或名稱,見 xcrun simctl list devices);預設是正在執行的那個,iOS 沒有時用最新的 iPhone"
216
+ }
217
+ },
218
+ "deploy": {
219
+ "description": "產生手機應用程式的 Node.js 專案,放進一個系統(android、ios、harmony)的模擬器或裝置上已安裝的除錯版應用程式,再重新啟動應用程式(開發時不用重新安裝)",
220
+ "arguments": {
221
+ "platform": "系統:android(模擬器或裝置,應用程式的除錯版)、ios(模擬器)或 harmony(模擬器或裝置,應用程式的除錯版)"
222
+ },
223
+ "options": {
224
+ "device": "Android 的模擬器或裝置(序號,見 adb devices)、鴻蒙的模擬器或裝置(見 hdc list targets)、iOS 的模擬器(UDID 或名稱,見 xcrun simctl list);預設是正在執行的那個",
225
+ "watch": "監看應用程式的檔案:有變更就執行它的 build 腳本(npm run build)並重新部署,直到按下 Ctrl+C"
226
+ }
227
+ }
228
+ },
187
229
  "i18n": {
188
230
  "description": "檢查各語言的翻譯、宣告鍵名的型別,或新增一種語言",
189
231
  "arguments": {
@@ -227,6 +269,7 @@
227
269
  "title": "專案",
228
270
  "name": "名稱",
229
271
  "id": "ID",
272
+ "bundleId": "應用程式識別碼(Bundle ID)",
230
273
  "description": "描述",
231
274
  "author": "作者",
232
275
  "license": "授權條款",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lakutata/cli",
3
- "version": "3.1.5",
3
+ "version": "3.1.6",
4
4
  "description": "The command line tool of the lakutata framework: create the projects from the templates, run and version the packages of the workspaces, bundle the applications and make their executables (with @lakutata/builder).",
5
5
  "keywords": [
6
6
  "lakutata",
@@ -39,11 +39,11 @@
39
39
  "dependencies": {
40
40
  "@inquirer/prompts": "^7.10.1",
41
41
  "commander": "^13.1.0",
42
- "lakutata": "3.1.5"
42
+ "lakutata": "3.1.6"
43
43
  },
44
44
  "peerDependencies": {
45
- "@lakutata/builder": "~3.1.5",
46
- "@lakutata/ffi": "~3.1.5"
45
+ "@lakutata/builder": "~3.1.6",
46
+ "@lakutata/ffi": "~3.1.6"
47
47
  },
48
48
  "peerDependenciesMeta": {
49
49
  "@lakutata/builder": {
@@ -54,8 +54,8 @@
54
54
  }
55
55
  },
56
56
  "devDependencies": {
57
- "@lakutata/builder": "~3.1.5",
58
- "@lakutata/ffi": "~3.1.5"
57
+ "@lakutata/builder": "~3.1.6",
58
+ "@lakutata/ffi": "~3.1.6"
59
59
  },
60
60
  "engines": {
61
61
  "node": ">=18.10.0"