cj-tauri 2.0.0 → 2.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.
Files changed (158) hide show
  1. package/README.md +113 -99
  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 +632 -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 +526 -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 +3740 -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/prebuilt/linux-x64/cj-tauri +0 -0
  77. package/src/api_system.cj +67 -67
  78. package/src/app.cj +325 -969
  79. package/src/app_events.cj +166 -0
  80. package/src/app_host_ops.cj +287 -0
  81. package/src/app_run.cj +283 -0
  82. package/src/app_spec.cj +76 -76
  83. package/src/arkweb_menu.cj +216 -0
  84. package/src/arkweb_script.cj +142 -142
  85. package/src/capability.cj +409 -409
  86. package/src/clipboard_bridge.cj +178 -0
  87. package/src/dialog_spec.cj +79 -0
  88. package/src/dragdrop.cj +26 -26
  89. package/src/embedded_assets.cj +98 -98
  90. package/src/host.cj +752 -607
  91. package/src/host_arkweb.cj +924 -778
  92. package/src/host_webkit.cj +663 -570
  93. package/src/host_webview2.cj +663 -570
  94. package/src/hotkey.cj +66 -66
  95. package/src/ipc_hub.cj +337 -337
  96. package/src/ipc_message.cj +286 -286
  97. package/src/launch.cj +62 -62
  98. package/src/logging.cj +127 -127
  99. package/src/menu.cj +197 -197
  100. package/src/platform/platform_app_context.cj +77 -77
  101. package/src/platform/platform_assets.cj +33 -33
  102. package/src/platform/platform_discover.cj +176 -176
  103. package/src/platform/platform_env.cj +29 -29
  104. package/src/platform/platform_feature.cj +31 -31
  105. package/src/platform/platform_page_source.cj +87 -87
  106. package/src/platform/platform_target_info.cj +32 -32
  107. package/src/platform_host_provider.cj +87 -87
  108. package/src/plugin.cj +333 -333
  109. package/src/plugins/clipboard/plugin_clipboard.cj +152 -152
  110. package/src/plugins/dialog/plugin_dialog.cj +209 -209
  111. package/src/plugins/fs/plugin_fs.cj +105 -1
  112. package/src/plugins/http/http_backend.cj +131 -0
  113. package/src/plugins/http/http_desktop.cj +195 -0
  114. package/src/plugins/http/http_ohos.cj +204 -0
  115. package/src/plugins/http/plugin_http.cj +310 -459
  116. package/src/plugins/log/plugin_log.cj +105 -105
  117. package/src/plugins/menu/plugin_menu.cj +158 -158
  118. package/src/plugins/notification/plugin_notification.cj +154 -154
  119. package/src/plugins/serial/plugin_serial.cj +458 -454
  120. package/src/plugins/serial/serial_bridge.cj +194 -194
  121. package/src/plugins/serial/serial_manager_ohos.cj +92 -0
  122. package/src/plugins/serial/serial_ohos.cj +529 -0
  123. package/src/plugins/shell/plugin_shell.cj +258 -258
  124. package/src/plugins/sqlite/plugin_sqlite.cj +705 -710
  125. package/src/plugins/sqlite/sqlite_ffi.cj +206 -211
  126. package/src/plugins/ws/plugin_ws.cj +488 -470
  127. package/src/process_hidden.cj +174 -174
  128. package/src/scope.cj +391 -391
  129. package/src/shell_event.cj +69 -69
  130. package/src/tests/app_spec_test.cj +126 -127
  131. package/src/tests/capability_test.cj +243 -243
  132. package/src/tests/dialog_spec_test.cj +73 -0
  133. package/src/tests/fake_host.cj +201 -201
  134. package/src/tests/ipc_hub_test.cj +487 -487
  135. package/src/tests/logging_test.cj +62 -62
  136. package/src/tests/platform_contract_test.cj +251 -251
  137. package/src/tests/plugin_clipboard_test.cj +222 -222
  138. package/src/tests/plugin_dialog_test.cj +237 -237
  139. package/src/tests/plugin_fs_test.cj +207 -0
  140. package/src/tests/plugin_http_test.cj +124 -124
  141. package/src/tests/plugin_notification_test.cj +205 -205
  142. package/src/tests/plugin_serial_test.cj +48 -0
  143. package/src/tests/plugin_test.cj +605 -585
  144. package/src/tests/plugin_ws_test.cj +40 -40
  145. package/src/tests/process_hidden_test.cj +129 -129
  146. package/src/tests/scope_test.cj +350 -350
  147. package/src/tests/system_host_test.cj +99 -81
  148. package/src/tests/urlutil_test.cj +53 -53
  149. package/src/tests/version_test.cj +75 -75
  150. package/src/tests/window_registry_test.cj +123 -123
  151. package/src/tray.cj +90 -90
  152. package/src/urlutil.cj +159 -159
  153. package/src/version.cj +44 -44
  154. package/src/window.cj +51 -51
  155. package/src/window_registry.cj +116 -116
  156. package/prebuilt/win32-x64/cj-tauri.exe +0 -0
  157. package/src/plugins/serial/serial_ohos_stub.cj +0 -61
  158. package/src/plugins/sqlite/sqlite_ohos_stub.cj +0 -91
@@ -1,154 +1,154 @@
1
- package cjTauri.plugins.notification
2
-
3
- import cjTauri.*
4
-
5
- import std.collection.*
6
- import stdx.encoding.json.*
7
-
8
- /**
9
- * 官方插件 notification:系统通知(对标 Tauri 的 notification 插件,RFC-003 第 3 期)
10
- *
11
- * 命令:notification:notify
12
- * 权限:**不自动放行**,应用要在 capabilities 里显式声明:
13
- * "commands": ["notification:notify"]
14
- * "permissions": ["notification:default"]
15
- * 前端:window.__CJ_TAURI__.notification.notify({ title, body })
16
- *
17
- * 实现落 C 桥 `cj_bridge_notification_notify`:Linux 走 freedesktop Notifications
18
- * (会话总线);**Windows 桩阶段返回 -4 未实现**——命令如实报失败,`system:host` 的能力位
19
- * 同口径不置 CJ_CAP_NOTIFICATION,不假装成功(AGENTS §1 的如实交付口径)。
20
- *
21
- * 「发后即忘」:提交即返回,通知显示与否不回传(freedesktop 协议本就没有同步回执)。
22
- */
23
- public class NotificationPlugin <: Plugin {
24
-
25
- /** 自描述:原生桥仅桌面两端实现(ohos 侧按 P-1 落桩,批次 3-PR3) */
26
- public func describe(): PluginManifest {
27
- let hosts = ArrayList<String>()
28
- hosts.add("webkitgtk")
29
- hosts.add("webview2")
30
- return PluginManifest(hosts, ArrayList<String>())
31
- }
32
- private let handler: NotificationCommands = NotificationCommands()
33
-
34
- public init() {}
35
-
36
- public func name(): String {
37
- return "notification"
38
- }
39
-
40
- public func commands(): HashMap<String, CommandHandler> {
41
- let m = HashMap<String, CommandHandler>()
42
- m.add("notify", this.handler)
43
- return m
44
- }
45
-
46
- /**
47
- * 命名权限集(v1.1):只有一条命令,default 与明文等价——保留集名是为了
48
- * 应用清单写法统一(全部走 permissions 数组)。
49
- */
50
- public func permissions(): HashMap<String, ArrayList<String>> {
51
- let m = HashMap<String, ArrayList<String>>()
52
- let all = ArrayList<String>()
53
- all.add("notify")
54
- m.add("default", all)
55
- return m
56
- }
57
-
58
- /**
59
- * 前端 shim:往桥对象上挂一个 notification 命名空间(与 dialog 同款)
60
- */
61
- public func jsShim(): String {
62
- return "(function () { var t = window.__CJ_TAURI__ || (window.__CJ_TAURI__ = {});" +
63
- " t.notification = {" +
64
- " notify: function (o) { return window.__CJ_TAURI__.invoke('notification:notify', o || {}); }" +
65
- " }; })();\n"
66
- }
67
-
68
- public func setup(app: TauriApp): Unit {
69
- // 多窗口按报文里的 label 解析宿主(与 dialog 插件同一口径):固定 `app.webviewHost()`
70
- // 会让第二扇窗的通知全部落到默认窗那一个宿主上(2026-10-20 dialog 实机取证同款)。
71
- this.handler.attachHostResolver({ label => app.hostOf(label) })
72
- }
73
- }
74
-
75
- /**
76
- * 通知命令处理器:notify 收 { title, body? }。body 省略 / null 都合法。
77
- */
78
- public class NotificationCommands <: CommandHandler {
79
- private var host: Option<WebViewHost> = None
80
-
81
- /* 按 label 解析宿主(多窗口的正路):单槽 `host` 只记着装配时那一个宿主,
82
- 多窗口下用它就是「所有窗的通知都发给默认窗那一个宿主」。 */
83
- private var hostByWindow: Option<(String) -> Option<WebViewHost>> = None
84
-
85
- public init() {}
86
-
87
- /** 由 NotificationPlugin.setup() 调用(单窗口 / 单测用;这个槽不带窗口身份) */
88
- public func attachHost(h: WebViewHost): Unit {
89
- this.host = Some(h)
90
- }
91
-
92
- /** 装配「label → 宿主」解析器;由 NotificationPlugin.setup() 传入 `app.hostOf` */
93
- public func attachHostResolver(resolve: (String) -> Option<WebViewHost>): Unit {
94
- this.hostByWindow = Some(resolve)
95
- }
96
-
97
- public func handle(cmd: String, args: JsonObject, ipc: IpcContext): JsonValue {
98
- match (cmd) {
99
- case "notification:notify" =>
100
- let title = this.requireString(args, "title")
101
- let body = this.optionalString(args, "body")
102
- if (this.requireHost(ipc).notify(title, body)) {
103
- return JsonNull()
104
- }
105
- throw CommandException(
106
- "notification: 发送失败(宿主未就绪 / 本平台未实现 / 桌面环境不可用)")
107
- case _ => throw CommandException("unknown notification command: ${cmd}")
108
- }
109
- }
110
-
111
- /**
112
- * 取**发起这条命令的窗口**的宿主
113
- *
114
- * 多窗口下必须按 `ipc.window` 解析:用装配时那一个宿主,第二扇窗的通知会落到默认窗的宿主上。
115
- * 解析器在场而窗口没登记时**如实报错**,不回落到单槽(与 dialog 插件同一口径)。
116
- */
117
- private func requireHost(ipc: IpcContext): WebViewHost {
118
- match (this.hostByWindow) {
119
- case Some(resolve) => match (resolve(ipc.window)) {
120
- case Some(h) => return h
121
- case None => throw CommandException(
122
- "notification: 窗口 \"${ipc.window}\" 没有登记宿主(addWindow(); 默认窗在 run() 之前也可用)")
123
- }
124
- case None => ()
125
- }
126
- match (this.host) {
127
- case Some(h) => h
128
- case None => throw CommandException(
129
- "notification: 宿主未装配(用 .plugin(NotificationPlugin()) 装配插件后才可用)")
130
- }
131
- }
132
-
133
- private func requireString(args: JsonObject, key: String): String {
134
- match (args.get(key)) {
135
- case Some(v) => match (v.kind()) {
136
- case JsonKind.JsString => return v.asString().getValue()
137
- case _ => throw CommandException("notification: argument \"${key}\" must be a string")
138
- }
139
- case None => throw CommandException("notification: missing argument \"${key}\"")
140
- }
141
- }
142
-
143
- /** 可选字符串参数:缺失 / null 都按空串(body 可省) */
144
- private func optionalString(args: JsonObject, key: String): String {
145
- match (args.get(key)) {
146
- case Some(v) => match (v.kind()) {
147
- case JsonKind.JsString => return v.asString().getValue()
148
- case JsonKind.JsNull => return ""
149
- case _ => throw CommandException("notification: argument \"${key}\" must be a string")
150
- }
151
- case None => return ""
152
- }
153
- }
154
- }
1
+ package cjTauri.plugins.notification
2
+
3
+ import cjTauri.*
4
+
5
+ import std.collection.*
6
+ import stdx.encoding.json.*
7
+
8
+ /**
9
+ * 官方插件 notification:系统通知(对标 Tauri 的 notification 插件,RFC-003 第 3 期)
10
+ *
11
+ * 命令:notification:notify
12
+ * 权限:**不自动放行**,应用要在 capabilities 里显式声明:
13
+ * "commands": ["notification:notify"]
14
+ * "permissions": ["notification:default"]
15
+ * 前端:window.__CJ_TAURI__.notification.notify({ title, body })
16
+ *
17
+ * 实现落 C 桥 `cj_bridge_notification_notify`:Linux 走 freedesktop Notifications
18
+ * (会话总线);**Windows 桩阶段返回 -4 未实现**——命令如实报失败,`system:host` 的能力位
19
+ * 同口径不置 CJ_CAP_NOTIFICATION,不假装成功(AGENTS §1 的如实交付口径)。
20
+ *
21
+ * 「发后即忘」:提交即返回,通知显示与否不回传(freedesktop 协议本就没有同步回执)。
22
+ */
23
+ public class NotificationPlugin <: Plugin {
24
+
25
+ /** 自描述:原生桥仅桌面两端实现(ohos 侧按 P-1 落桩,批次 3-PR3) */
26
+ public func describe(): PluginManifest {
27
+ let hosts = ArrayList<String>()
28
+ hosts.add("webkitgtk")
29
+ hosts.add("webview2")
30
+ return PluginManifest(hosts, ArrayList<String>())
31
+ }
32
+ private let handler: NotificationCommands = NotificationCommands()
33
+
34
+ public init() {}
35
+
36
+ public func name(): String {
37
+ return "notification"
38
+ }
39
+
40
+ public func commands(): HashMap<String, CommandHandler> {
41
+ let m = HashMap<String, CommandHandler>()
42
+ m.add("notify", this.handler)
43
+ return m
44
+ }
45
+
46
+ /**
47
+ * 命名权限集(v1.1):只有一条命令,default 与明文等价——保留集名是为了
48
+ * 应用清单写法统一(全部走 permissions 数组)。
49
+ */
50
+ public func permissions(): HashMap<String, ArrayList<String>> {
51
+ let m = HashMap<String, ArrayList<String>>()
52
+ let all = ArrayList<String>()
53
+ all.add("notify")
54
+ m.add("default", all)
55
+ return m
56
+ }
57
+
58
+ /**
59
+ * 前端 shim:往桥对象上挂一个 notification 命名空间(与 dialog 同款)
60
+ */
61
+ public func jsShim(): String {
62
+ return "(function () { var t = window.__CJ_TAURI__ || (window.__CJ_TAURI__ = {});" +
63
+ " t.notification = {" +
64
+ " notify: function (o) { return window.__CJ_TAURI__.invoke('notification:notify', o || {}); }" +
65
+ " }; })();\n"
66
+ }
67
+
68
+ public func setup(app: TauriApp): Unit {
69
+ // 多窗口按报文里的 label 解析宿主(与 dialog 插件同一口径):固定 `app.webviewHost()`
70
+ // 会让第二扇窗的通知全部落到默认窗那一个宿主上(2026-10-20 dialog 实机取证同款)。
71
+ this.handler.attachHostResolver({ label => app.hostOf(label) })
72
+ }
73
+ }
74
+
75
+ /**
76
+ * 通知命令处理器:notify 收 { title, body? }。body 省略 / null 都合法。
77
+ */
78
+ public class NotificationCommands <: CommandHandler {
79
+ private var host: Option<WebViewHost> = None
80
+
81
+ /* 按 label 解析宿主(多窗口的正路):单槽 `host` 只记着装配时那一个宿主,
82
+ 多窗口下用它就是「所有窗的通知都发给默认窗那一个宿主」。 */
83
+ private var hostByWindow: Option<(String) -> Option<WebViewHost>> = None
84
+
85
+ public init() {}
86
+
87
+ /** 由 NotificationPlugin.setup() 调用(单窗口 / 单测用;这个槽不带窗口身份) */
88
+ public func attachHost(h: WebViewHost): Unit {
89
+ this.host = Some(h)
90
+ }
91
+
92
+ /** 装配「label → 宿主」解析器;由 NotificationPlugin.setup() 传入 `app.hostOf` */
93
+ public func attachHostResolver(resolve: (String) -> Option<WebViewHost>): Unit {
94
+ this.hostByWindow = Some(resolve)
95
+ }
96
+
97
+ public func handle(cmd: String, args: JsonObject, ipc: IpcContext): JsonValue {
98
+ match (cmd) {
99
+ case "notification:notify" =>
100
+ let title = this.requireString(args, "title")
101
+ let body = this.optionalString(args, "body")
102
+ if (this.requireHost(ipc).notify(title, body)) {
103
+ return JsonNull()
104
+ }
105
+ throw CommandException(
106
+ "notification: 发送失败(宿主未就绪 / 本平台未实现 / 桌面环境不可用)")
107
+ case _ => throw CommandException("unknown notification command: ${cmd}")
108
+ }
109
+ }
110
+
111
+ /**
112
+ * 取**发起这条命令的窗口**的宿主
113
+ *
114
+ * 多窗口下必须按 `ipc.window` 解析:用装配时那一个宿主,第二扇窗的通知会落到默认窗的宿主上。
115
+ * 解析器在场而窗口没登记时**如实报错**,不回落到单槽(与 dialog 插件同一口径)。
116
+ */
117
+ private func requireHost(ipc: IpcContext): WebViewHost {
118
+ match (this.hostByWindow) {
119
+ case Some(resolve) => match (resolve(ipc.window)) {
120
+ case Some(h) => return h
121
+ case None => throw CommandException(
122
+ "notification: 窗口 \"${ipc.window}\" 没有登记宿主(addWindow(); 默认窗在 run() 之前也可用)")
123
+ }
124
+ case None => ()
125
+ }
126
+ match (this.host) {
127
+ case Some(h) => h
128
+ case None => throw CommandException(
129
+ "notification: 宿主未装配(用 .plugin(NotificationPlugin()) 装配插件后才可用)")
130
+ }
131
+ }
132
+
133
+ private func requireString(args: JsonObject, key: String): String {
134
+ match (args.get(key)) {
135
+ case Some(v) => match (v.kind()) {
136
+ case JsonKind.JsString => return v.asString().getValue()
137
+ case _ => throw CommandException("notification: argument \"${key}\" must be a string")
138
+ }
139
+ case None => throw CommandException("notification: missing argument \"${key}\"")
140
+ }
141
+ }
142
+
143
+ /** 可选字符串参数:缺失 / null 都按空串(body 可省) */
144
+ private func optionalString(args: JsonObject, key: String): String {
145
+ match (args.get(key)) {
146
+ case Some(v) => match (v.kind()) {
147
+ case JsonKind.JsString => return v.asString().getValue()
148
+ case JsonKind.JsNull => return ""
149
+ case _ => throw CommandException("notification: argument \"${key}\" must be a string")
150
+ }
151
+ case None => return ""
152
+ }
153
+ }
154
+ }