cj-tauri 2.0.0 → 2.1.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 (157) hide show
  1. package/README.md +206 -139
  2. package/bin/cj-tauri.js +287 -287
  3. package/cjpm.toml +63 -52
  4. package/cli/cjpm.toml +22 -22
  5. package/cli/src/doctor.cj +308 -306
  6. package/cli/src/main.cj +129 -129
  7. package/cli/src/manifest.cj +643 -558
  8. package/cli/src/manifest_test.cj +87 -0
  9. package/cli/src/project.cj +770 -770
  10. package/cli/src/resolve.cj +348 -348
  11. package/cli/src/scaffold.cj +369 -369
  12. package/cli/src/sync.cj +638 -526
  13. package/cli/src/util.cj +168 -168
  14. package/cli/templates/app/README.md +51 -48
  15. package/cli/templates/app/assets/capabilities/default.json +7 -7
  16. package/cli/templates/app/assets/ui/index.html +120 -118
  17. package/cli/templates/app/cj-tauri.toml +32 -22
  18. package/cli/templates/app/cjpm.toml +34 -34
  19. package/cli/templates/app/src/main.cj +101 -90
  20. package/cli/templates/app-react/README.md +56 -56
  21. package/cli/templates/app-react/assets/capabilities/default.json +7 -7
  22. package/cli/templates/app-react/assets/ui/index.html +25 -25
  23. package/cli/templates/app-react/assets/ui/package.json +19 -19
  24. package/cli/templates/app-react/assets/ui/src/App.css +67 -67
  25. package/cli/templates/app-react/assets/ui/src/App.jsx +124 -124
  26. package/cli/templates/app-react/assets/ui/src/main.jsx +6 -6
  27. package/cli/templates/app-react/assets/ui/vite.config.js +24 -24
  28. package/cli/templates/app-react/cj-tauri.toml +33 -23
  29. package/cli/templates/app-react/cjpm.toml +34 -34
  30. package/cli/templates/app-react/src/main.cj +91 -91
  31. package/cli/templates/app-vue/README.md +56 -56
  32. package/cli/templates/app-vue/assets/capabilities/default.json +7 -7
  33. package/cli/templates/app-vue/assets/ui/index.html +25 -25
  34. package/cli/templates/app-vue/assets/ui/package.json +18 -18
  35. package/cli/templates/app-vue/assets/ui/src/App.vue +176 -176
  36. package/cli/templates/app-vue/assets/ui/src/main.js +4 -4
  37. package/cli/templates/app-vue/assets/ui/vite.config.js +24 -24
  38. package/cli/templates/app-vue/cj-tauri.toml +33 -23
  39. package/cli/templates/app-vue/cjpm.toml +34 -34
  40. package/cli/templates/app-vue/src/main.cj +91 -91
  41. package/cli/templates/ohos-skeleton/AppScope/app.json5 +13 -13
  42. package/cli/templates/ohos-skeleton/AppScope/resources/base/element/string.json +8 -8
  43. package/cli/templates/ohos-skeleton/AppScope/resources/base/media/layered_image.json +6 -6
  44. package/cli/templates/ohos-skeleton/README.md +84 -79
  45. package/cli/templates/ohos-skeleton/build-hap.sh +15 -0
  46. package/cli/templates/ohos-skeleton/build-profile.json5 +46 -46
  47. package/cli/templates/ohos-skeleton/entry/build-profile.json5 +26 -26
  48. package/cli/templates/ohos-skeleton/entry/cjpm.toml +51 -43
  49. package/cli/templates/ohos-skeleton/entry/hvigorfile.ts +6 -6
  50. package/cli/templates/ohos-skeleton/entry/oh-package.json5 +9 -9
  51. package/cli/templates/ohos-skeleton/entry/src/main/cangjie/ability_stage.cj +17 -17
  52. package/cli/templates/ohos-skeleton/entry/src/main/cangjie/app_host.cj +94 -94
  53. package/cli/templates/ohos-skeleton/entry/src/main/cangjie/dialog_host.cj +217 -0
  54. package/cli/templates/ohos-skeleton/entry/src/main/cangjie/index.cj +527 -167
  55. package/cli/templates/ohos-skeleton/entry/src/main/cangjie/main_ability.cj +139 -139
  56. package/cli/templates/ohos-skeleton/entry/src/main/module.json5 +57 -49
  57. package/cli/templates/ohos-skeleton/entry/src/main/resources/base/element/color.json +8 -8
  58. package/cli/templates/ohos-skeleton/entry/src/main/resources/base/element/string.json +16 -16
  59. package/cli/templates/ohos-skeleton/entry/src/main/resources/base/media/layered_image.json +6 -6
  60. package/cli/templates/ohos-skeleton/entry/src/main/resources/base/profile/main_pages.json +2 -2
  61. package/cli/templates/ohos-skeleton/entry/src/main/resources/rawfile/capabilities.json +6 -6
  62. package/cli/templates/ohos-skeleton/entry/src/main/resources/rawfile/index.html +92 -92
  63. package/cli/templates/ohos-skeleton/hvigor/hvigor-config.json5 +5 -5
  64. package/cli/templates/ohos-skeleton/hvigorfile.ts +6 -6
  65. package/cli/templates/ohos-skeleton/oh-package.json5 +10 -10
  66. package/native/build_win.bat +62 -62
  67. package/native/core/bridge_core.c +1681 -1626
  68. package/native/core/bridge_core.h +675 -618
  69. package/native/core/bridge_js.h +108 -108
  70. package/native/platforms/harmonyos/README.md +115 -6
  71. package/native/platforms/linux/bridge_linux.c +2787 -2485
  72. package/native/platforms/windows/bridge_win.c +3745 -3248
  73. package/native/tests/gtk_threading_probe.c +143 -143
  74. package/native/tests/test_bridge_core.c +1339 -1228
  75. package/package.json +53 -53
  76. package/src/api_system.cj +67 -67
  77. package/src/app.cj +335 -969
  78. package/src/app_events.cj +166 -0
  79. package/src/app_host_ops.cj +287 -0
  80. package/src/app_run.cj +283 -0
  81. package/src/app_spec.cj +76 -76
  82. package/src/arkweb_menu.cj +216 -0
  83. package/src/arkweb_script.cj +142 -142
  84. package/src/capability.cj +409 -409
  85. package/src/clipboard_bridge.cj +178 -0
  86. package/src/dialog_spec.cj +79 -0
  87. package/src/dragdrop.cj +26 -26
  88. package/src/embedded_assets.cj +98 -98
  89. package/src/host.cj +752 -607
  90. package/src/host_arkweb.cj +924 -778
  91. package/src/host_webkit.cj +663 -570
  92. package/src/host_webview2.cj +663 -570
  93. package/src/hotkey.cj +66 -66
  94. package/src/ipc_hub.cj +401 -337
  95. package/src/ipc_message.cj +286 -286
  96. package/src/launch.cj +62 -62
  97. package/src/logging.cj +127 -127
  98. package/src/menu.cj +197 -197
  99. package/src/platform/platform_app_context.cj +77 -77
  100. package/src/platform/platform_assets.cj +33 -33
  101. package/src/platform/platform_discover.cj +176 -176
  102. package/src/platform/platform_env.cj +29 -29
  103. package/src/platform/platform_feature.cj +31 -31
  104. package/src/platform/platform_page_source.cj +87 -87
  105. package/src/platform/platform_target_info.cj +32 -32
  106. package/src/platform_host_provider.cj +87 -87
  107. package/src/plugin.cj +333 -333
  108. package/src/plugins/clipboard/plugin_clipboard.cj +152 -152
  109. package/src/plugins/dialog/plugin_dialog.cj +209 -209
  110. package/src/plugins/fs/plugin_fs.cj +105 -1
  111. package/src/plugins/http/http_backend.cj +131 -0
  112. package/src/plugins/http/http_desktop.cj +195 -0
  113. package/src/plugins/http/http_ohos.cj +204 -0
  114. package/src/plugins/http/plugin_http.cj +310 -459
  115. package/src/plugins/log/plugin_log.cj +105 -105
  116. package/src/plugins/menu/plugin_menu.cj +158 -158
  117. package/src/plugins/notification/plugin_notification.cj +154 -154
  118. package/src/plugins/serial/plugin_serial.cj +458 -454
  119. package/src/plugins/serial/serial_bridge.cj +194 -194
  120. package/src/plugins/serial/serial_manager_ohos.cj +92 -0
  121. package/src/plugins/serial/serial_ohos.cj +529 -0
  122. package/src/plugins/shell/plugin_shell.cj +258 -258
  123. package/src/plugins/sqlite/plugin_sqlite.cj +705 -710
  124. package/src/plugins/sqlite/sqlite_ffi.cj +206 -211
  125. package/src/plugins/ws/plugin_ws.cj +488 -470
  126. package/src/process_hidden.cj +174 -174
  127. package/src/scope.cj +391 -391
  128. package/src/shell_event.cj +69 -69
  129. package/src/tests/app_spec_test.cj +130 -127
  130. package/src/tests/capability_test.cj +243 -243
  131. package/src/tests/dialog_spec_test.cj +73 -0
  132. package/src/tests/fake_host.cj +201 -201
  133. package/src/tests/ipc_hub_test.cj +563 -487
  134. package/src/tests/logging_test.cj +62 -62
  135. package/src/tests/platform_contract_test.cj +264 -251
  136. package/src/tests/plugin_clipboard_test.cj +222 -222
  137. package/src/tests/plugin_dialog_test.cj +237 -237
  138. package/src/tests/plugin_fs_test.cj +207 -0
  139. package/src/tests/plugin_http_test.cj +124 -124
  140. package/src/tests/plugin_notification_test.cj +205 -205
  141. package/src/tests/plugin_serial_test.cj +48 -0
  142. package/src/tests/plugin_test.cj +605 -585
  143. package/src/tests/plugin_ws_test.cj +40 -40
  144. package/src/tests/process_hidden_test.cj +129 -129
  145. package/src/tests/scope_test.cj +350 -350
  146. package/src/tests/system_host_test.cj +99 -81
  147. package/src/tests/urlutil_test.cj +53 -53
  148. package/src/tests/version_test.cj +75 -75
  149. package/src/tests/window_registry_test.cj +123 -123
  150. package/src/tray.cj +90 -90
  151. package/src/urlutil.cj +159 -159
  152. package/src/version.cj +44 -44
  153. package/src/window.cj +51 -51
  154. package/src/window_registry.cj +116 -116
  155. package/prebuilt/win32-x64/cj-tauri.exe +0 -0
  156. package/src/plugins/serial/serial_ohos_stub.cj +0 -61
  157. package/src/plugins/sqlite/sqlite_ohos_stub.cj +0 -91
package/cli/src/util.cj CHANGED
@@ -1,168 +1,168 @@
1
- /**
2
- * cj-tauri CLI:通用工具层
3
- *
4
- * 路径与字符串处理统一按 UTF-8 字节做 ASCII 分隔符扫描,切分点都在 ASCII 边界上,
5
- * 对含中文的路径安全(仓颉迭代 String 得到的是码点,这里显式走字节以避免码点/字节混淆)。
6
- */
7
- package cli
8
-
9
- import std.fs.*
10
-
11
- // ===== 字节级字符判定 =====
12
-
13
- func isPathSep(b: UInt8): Bool {
14
- return b == 0x2F || b == 0x5C // '/' or '\'
15
- }
16
-
17
- func isSpaceByte(b: UInt8): Bool {
18
- return b == 0x20 || b == 0x09 || b == 0x0D || b == 0x0A
19
- }
20
-
21
- func isAsciiDigit(b: UInt8): Bool {
22
- return b >= 0x30 && b <= 0x39
23
- }
24
-
25
- func isAsciiAlpha(b: UInt8): Bool {
26
- return (b >= 0x41 && b <= 0x5A) || (b >= 0x61 && b <= 0x7A)
27
- }
28
-
29
- func toUpperByte(b: UInt8): UInt8 {
30
- if (b >= 0x61 && b <= 0x7A) {
31
- return b - 0x20
32
- }
33
- return b
34
- }
35
-
36
- func toLowerByte(b: UInt8): UInt8 {
37
- if (b >= 0x41 && b <= 0x5A) {
38
- return b + 0x20
39
- }
40
- return b
41
- }
42
-
43
- // ===== 路径 =====
44
-
45
- /** 拼接路径(统一用 '/',Windows 亦兼容) */
46
- func joinPath(a: String, b: String): String {
47
- let ab = a.toArray()
48
- if (ab.size == 0) {
49
- return b
50
- }
51
- if (isPathSep(ab[ab.size - 1])) {
52
- return a + b
53
- }
54
- return a + "/" + b
55
- }
56
-
57
- /** 去掉末尾的路径分隔符 */
58
- func stripTrailingSep(p: String): String {
59
- let b = p.toArray()
60
- var n = b.size
61
- while (n > 1 && isPathSep(b[n - 1])) {
62
- n--
63
- }
64
- return String.fromUtf8(b[0..n])
65
- }
66
-
67
- /** 父目录;已到根或无法解析时返回 None */
68
- func parentDir(p: String): Option<String> {
69
- let s = stripTrailingSep(p)
70
- let b = s.toArray()
71
- var i = b.size
72
- while (i > 0) {
73
- i--
74
- if (isPathSep(b[i])) {
75
- if (i == 0) {
76
- return Some(String.fromUtf8(b[0..1])) // "/"
77
- }
78
- // Windows 盘符根 "C:/"
79
- if (i == 2 && b[1] == 0x3A) {
80
- return Some(String.fromUtf8(b[0..3]))
81
- }
82
- return Some(String.fromUtf8(b[0..i]))
83
- }
84
- }
85
- return None
86
- }
87
-
88
- /** 最后一段(文件/目录名) */
89
- func baseName(p: String): String {
90
- let s = stripTrailingSep(p)
91
- let b = s.toArray()
92
- var i = b.size
93
- while (i > 0) {
94
- i--
95
- if (isPathSep(b[i])) {
96
- return String.fromUtf8(b[i + 1..b.size])
97
- }
98
- }
99
- return s
100
- }
101
-
102
- /** 去掉首尾 ASCII 空白(含 \r) */
103
- func trimAscii(s: String): String {
104
- let b = s.toArray()
105
- var start = 0
106
- var end = b.size
107
- while (start < end && isSpaceByte(b[start])) {
108
- start++
109
- }
110
- while (end > start && isSpaceByte(b[end - 1])) {
111
- end--
112
- }
113
- if (start == 0 && end == b.size) {
114
- return s
115
- }
116
- return String.fromUtf8(b[start..end])
117
- }
118
-
119
- /** 路径含空格时给出告警(cjpm 的 link-option 以空格分隔,无法转义) */
120
- func warnIfSpacey(label: String, p: String): Unit {
121
- let b = p.toArray()
122
- for (x in b) {
123
- if (x == 0x20) {
124
- eprintln("[cj-tauri] 告警: ${label} 路径含空格,cjpm 的 link-option 可能解析失败: ${p}")
125
- return
126
- }
127
- }
128
- }
129
-
130
- // ===== 文件 =====
131
-
132
- func readText(p: String): String {
133
- return String.fromUtf8(File.readFrom(p))
134
- }
135
-
136
- /** 覆盖写(File.create 对已存在文件会抛异常,故先删) */
137
- func writeText(p: String, content: String): Unit {
138
- if (exists(p)) {
139
- remove(p)
140
- }
141
- let f = File.create(p)
142
- f.write(content.toArray())
143
- f.close()
144
- }
145
-
146
- func ensureDir(p: String): Unit {
147
- if (!exists(p)) {
148
- Directory.create(p, recursive: true)
149
- }
150
- }
151
-
152
- func listDir(p: String): Array<FileInfo> {
153
- return Directory.readFrom(p)
154
- }
155
-
156
- /** TOML 基本字符串转义:反斜杠与双引号 */
157
- func escapeTomlString(p: String): String {
158
- return p.replace("\\", "\\\\").replace("\"", "\\\"")
159
- }
160
-
161
- /**
162
- * 写进生成 TOML 的路径一律转正斜杠。
163
- * 为什么:Windows 的 `E:\a\b` 在 TOML 基本字符串里是转义序列,`\a` / `\t` 会让 cjpm 解析期直接
164
- * `errLexEscape` 失败(AGENTS §4「生成 toml 的脚本用正斜杠」);正斜杠 cjpm 与 gcc/ld 都认。
165
- */
166
- func toTomlPath(p: String): String {
167
- return p.replace("\\", "/")
168
- }
1
+ /**
2
+ * cj-tauri CLI:通用工具层
3
+ *
4
+ * 路径与字符串处理统一按 UTF-8 字节做 ASCII 分隔符扫描,切分点都在 ASCII 边界上,
5
+ * 对含中文的路径安全(仓颉迭代 String 得到的是码点,这里显式走字节以避免码点/字节混淆)。
6
+ */
7
+ package cli
8
+
9
+ import std.fs.*
10
+
11
+ // ===== 字节级字符判定 =====
12
+
13
+ func isPathSep(b: UInt8): Bool {
14
+ return b == 0x2F || b == 0x5C // '/' or '\'
15
+ }
16
+
17
+ func isSpaceByte(b: UInt8): Bool {
18
+ return b == 0x20 || b == 0x09 || b == 0x0D || b == 0x0A
19
+ }
20
+
21
+ func isAsciiDigit(b: UInt8): Bool {
22
+ return b >= 0x30 && b <= 0x39
23
+ }
24
+
25
+ func isAsciiAlpha(b: UInt8): Bool {
26
+ return (b >= 0x41 && b <= 0x5A) || (b >= 0x61 && b <= 0x7A)
27
+ }
28
+
29
+ func toUpperByte(b: UInt8): UInt8 {
30
+ if (b >= 0x61 && b <= 0x7A) {
31
+ return b - 0x20
32
+ }
33
+ return b
34
+ }
35
+
36
+ func toLowerByte(b: UInt8): UInt8 {
37
+ if (b >= 0x41 && b <= 0x5A) {
38
+ return b + 0x20
39
+ }
40
+ return b
41
+ }
42
+
43
+ // ===== 路径 =====
44
+
45
+ /** 拼接路径(统一用 '/',Windows 亦兼容) */
46
+ func joinPath(a: String, b: String): String {
47
+ let ab = a.toArray()
48
+ if (ab.size == 0) {
49
+ return b
50
+ }
51
+ if (isPathSep(ab[ab.size - 1])) {
52
+ return a + b
53
+ }
54
+ return a + "/" + b
55
+ }
56
+
57
+ /** 去掉末尾的路径分隔符 */
58
+ func stripTrailingSep(p: String): String {
59
+ let b = p.toArray()
60
+ var n = b.size
61
+ while (n > 1 && isPathSep(b[n - 1])) {
62
+ n--
63
+ }
64
+ return String.fromUtf8(b[0..n])
65
+ }
66
+
67
+ /** 父目录;已到根或无法解析时返回 None */
68
+ func parentDir(p: String): Option<String> {
69
+ let s = stripTrailingSep(p)
70
+ let b = s.toArray()
71
+ var i = b.size
72
+ while (i > 0) {
73
+ i--
74
+ if (isPathSep(b[i])) {
75
+ if (i == 0) {
76
+ return Some(String.fromUtf8(b[0..1])) // "/"
77
+ }
78
+ // Windows 盘符根 "C:/"
79
+ if (i == 2 && b[1] == 0x3A) {
80
+ return Some(String.fromUtf8(b[0..3]))
81
+ }
82
+ return Some(String.fromUtf8(b[0..i]))
83
+ }
84
+ }
85
+ return None
86
+ }
87
+
88
+ /** 最后一段(文件/目录名) */
89
+ func baseName(p: String): String {
90
+ let s = stripTrailingSep(p)
91
+ let b = s.toArray()
92
+ var i = b.size
93
+ while (i > 0) {
94
+ i--
95
+ if (isPathSep(b[i])) {
96
+ return String.fromUtf8(b[i + 1..b.size])
97
+ }
98
+ }
99
+ return s
100
+ }
101
+
102
+ /** 去掉首尾 ASCII 空白(含 \r) */
103
+ func trimAscii(s: String): String {
104
+ let b = s.toArray()
105
+ var start = 0
106
+ var end = b.size
107
+ while (start < end && isSpaceByte(b[start])) {
108
+ start++
109
+ }
110
+ while (end > start && isSpaceByte(b[end - 1])) {
111
+ end--
112
+ }
113
+ if (start == 0 && end == b.size) {
114
+ return s
115
+ }
116
+ return String.fromUtf8(b[start..end])
117
+ }
118
+
119
+ /** 路径含空格时给出告警(cjpm 的 link-option 以空格分隔,无法转义) */
120
+ func warnIfSpacey(label: String, p: String): Unit {
121
+ let b = p.toArray()
122
+ for (x in b) {
123
+ if (x == 0x20) {
124
+ eprintln("[cj-tauri] 告警: ${label} 路径含空格,cjpm 的 link-option 可能解析失败: ${p}")
125
+ return
126
+ }
127
+ }
128
+ }
129
+
130
+ // ===== 文件 =====
131
+
132
+ func readText(p: String): String {
133
+ return String.fromUtf8(File.readFrom(p))
134
+ }
135
+
136
+ /** 覆盖写(File.create 对已存在文件会抛异常,故先删) */
137
+ func writeText(p: String, content: String): Unit {
138
+ if (exists(p)) {
139
+ remove(p)
140
+ }
141
+ let f = File.create(p)
142
+ f.write(content.toArray())
143
+ f.close()
144
+ }
145
+
146
+ func ensureDir(p: String): Unit {
147
+ if (!exists(p)) {
148
+ Directory.create(p, recursive: true)
149
+ }
150
+ }
151
+
152
+ func listDir(p: String): Array<FileInfo> {
153
+ return Directory.readFrom(p)
154
+ }
155
+
156
+ /** TOML 基本字符串转义:反斜杠与双引号 */
157
+ func escapeTomlString(p: String): String {
158
+ return p.replace("\\", "\\\\").replace("\"", "\\\"")
159
+ }
160
+
161
+ /**
162
+ * 写进生成 TOML 的路径一律转正斜杠。
163
+ * 为什么:Windows 的 `E:\a\b` 在 TOML 基本字符串里是转义序列,`\a` / `\t` 会让 cjpm 解析期直接
164
+ * `errLexEscape` 失败(AGENTS §4「生成 toml 的脚本用正斜杠」);正斜杠 cjpm 与 gcc/ld 都认。
165
+ */
166
+ func toTomlPath(p: String): String {
167
+ return p.replace("\\", "/")
168
+ }
@@ -1,48 +1,51 @@
1
- # {{PROJECT_NAME}}
2
-
3
- 基于 [cj-tauri]({{FRAMEWORK_ROOT}})(仓颉版 Tauri)的应用:**仓颉后端 + 系统 WebView 前端**,
4
- 通过 `window.__CJ_TAURI__` 做 invoke/listen 双向 IPC,并由 capabilities 清单做最小权限管控。
5
-
6
- ## 目录结构(一份业务代码,骨架按目标派生)
7
-
8
- ```
9
- {{PROJECT_NAME}}/
10
- ├── cj-tauri.toml # 应用清单——单一真相(id/version/窗口/资产/能力目录)
11
- ├── cjpm.toml # 业务包(static 库;骨架以 path 依赖引用)
12
- ├── src/main.cj # 业务装配点 build(): AppSpec(零平台知识)
13
- ├── assets/
14
- │ ├── ui/index.html # 前端页面(任意 Web 技术栈)
15
- │ └── capabilities/default.json # 能力白名单(命令 / 事件 / 权限集)
16
- └── targets/ # cj-tauri sync 生成的骨架(勿手改;check 判漂移)
17
- ├── desktop/ # 桌面可执行(launcher 调 build())
18
- └── ohos/ # 鸿蒙 hap 工程(DevEco + build-hap.sh)
19
- ```
20
-
21
- ## 运行
22
-
23
- ```bash
24
- cj-tauri sync # 派生 targets/ 骨架(首次;重跑幂等)
25
- cj-tauri dev # 构建 C 桥 + 编译 + 启动窗口
26
- cj-tauri build # 仅构建
27
- cj-tauri run # 运行已构建产物
28
- cj-tauri check # 清单校验 + 骨架漂移 + 插件三方比对
29
- ```
30
-
31
- ## 鸿蒙端(PC / 2in1)
32
-
33
- ```bash
34
- export CANGJIE_STDX_OHOS=<鸿蒙版 stdx>/linux_ohos_aarch64_cjnative/dynamic/stdx
35
- cd targets/ohos && bash build-hap.sh # 编 hap
36
- cd targets/ohos && bash build-hap.sh --install # 编完装到设备并拉起
37
- ```
38
-
39
- 提示:模板不带签名证书——首次在 DevEco 里 File → Project Structure → Signing Configs
40
- 勾「Automatically generate signature」(要登录华为账号);不签名只能编出
41
- *-unsigned.hap,装不进设备。
42
-
43
- ## 命令与能力
44
-
45
- 命令在 `src/main.cj`(`greet` / `timer` + 演示菜单),白名单在 `assets/capabilities/default.json`——
46
- 两边必须对齐:`cj-tauri check` 的三方比对会交叉核对「能力声明 × 插件自描述 × 实际装配」。
47
- 插件在某端没有实现时(如 shell/sqlite 在鸿蒙端),骨架照样编得过,运行期调用得到
48
- 可照做的「端不支持」错误(RFC-002 §4.6.4 的 P-1 桩)。
1
+ # {{PROJECT_NAME}}
2
+
3
+ 基于 [cj-tauri]({{FRAMEWORK_ROOT}})(仓颉版 Tauri)的应用:**仓颉后端 + 系统 WebView 前端**,
4
+ 通过 `window.__CJ_TAURI__` 做 invoke/listen 双向 IPC,并由 capabilities 清单做最小权限管控。
5
+
6
+ ## 目录结构(一份业务代码,骨架按目标派生)
7
+
8
+ ```
9
+ {{PROJECT_NAME}}/
10
+ ├── cj-tauri.toml # 应用清单——单一真相(id/version/窗口/资产/能力目录)
11
+ ├── cjpm.toml # 业务包(static 库;骨架以 path 依赖引用)
12
+ ├── src/main.cj # 业务装配点 build(): AppSpec(零平台知识)
13
+ ├── assets/
14
+ │ ├── ui/index.html # 前端页面(任意 Web 技术栈)
15
+ │ └── capabilities/default.json # 能力白名单(命令 / 事件 / 权限集)
16
+ └── targets/ # cj-tauri sync 生成的骨架(勿手改;check 判漂移)
17
+ ├── desktop/ # 桌面可执行(launcher 调 build())
18
+ └── ohos/ # 鸿蒙 hap 工程(DevEco + build-hap.sh)
19
+ ```
20
+
21
+ ## 运行
22
+
23
+ ```bash
24
+ cj-tauri sync # 派生 targets/ 骨架(首次;重跑幂等)
25
+ cj-tauri dev # 构建 C 桥 + 编译 + 启动窗口
26
+ cj-tauri build # 仅构建
27
+ cj-tauri run # 运行已构建产物
28
+ cj-tauri check # 清单校验 + 骨架漂移 + 插件三方比对
29
+ ```
30
+
31
+ ## 鸿蒙端(PC / 2in1)
32
+
33
+ ```bash
34
+ export CANGJIE_STDX_OHOS=<鸿蒙版 stdx>/linux_ohos_aarch64_cjnative/dynamic/stdx
35
+ cd targets/ohos && bash build-hap.sh # 编 hap
36
+ cd targets/ohos && bash build-hap.sh --install # 编完装到设备并拉起
37
+ ```
38
+
39
+ 提示:模板不带签名证书——首次在 DevEco 里 File → Project Structure → Signing Configs
40
+ 勾「Automatically generate signature」(要登录华为账号);不签名只能编出
41
+ *-unsigned.hap,装不进设备。
42
+
43
+ ## 命令与能力
44
+
45
+ **把骨架变成你的应用,改三处**:① `src/main.cj` 照 `GreetCommand` 写命令并在 `build()` 里 register;
46
+ ② `assets/capabilities/default.json` 的 `commands` 里放行;③ `assets/ui/index.html` 里 `tauri.invoke`。
47
+
48
+ 命令在 `src/main.cj`(`greet` / `timer` + 演示菜单),白名单在 `assets/capabilities/default.json`——
49
+ 两边必须对齐:`cj-tauri check` 的三方比对会交叉核对「能力声明 × 插件自描述 × 实际装配」。
50
+ 插件在某端没有实现时(如 shell/sqlite 在鸿蒙端),骨架照样编得过,运行期调用得到
51
+ 可照做的「端不支持」错误(RFC-002 §4.6.4 的 P-1 桩)。
@@ -1,7 +1,7 @@
1
- {
2
- "identifier": "default",
3
- "windows": ["main"],
4
- "commands": ["greet", "timer", "system:version", "system:ping", "system:echo", "system:devtools"],
5
- "permissions": ["menu:state"],
6
- "events": ["tick", "menu:click"]
7
- }
1
+ {
2
+ "identifier": "default",
3
+ "windows": ["main"],
4
+ "commands": ["greet", "timer", "system:version", "system:ping", "system:echo", "system:devtools"],
5
+ "permissions": ["menu:state"],
6
+ "events": ["tick", "menu:click"]
7
+ }