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.
- package/README.md +113 -99
- package/bin/cj-tauri.js +287 -287
- package/cjpm.toml +63 -52
- package/cli/cjpm.toml +22 -22
- package/cli/src/doctor.cj +308 -306
- package/cli/src/main.cj +129 -129
- package/cli/src/manifest.cj +632 -558
- package/cli/src/manifest_test.cj +87 -0
- package/cli/src/project.cj +770 -770
- package/cli/src/resolve.cj +348 -348
- package/cli/src/scaffold.cj +369 -369
- package/cli/src/sync.cj +526 -526
- package/cli/src/util.cj +168 -168
- package/cli/templates/app/README.md +51 -48
- package/cli/templates/app/assets/capabilities/default.json +7 -7
- package/cli/templates/app/assets/ui/index.html +120 -118
- package/cli/templates/app/cj-tauri.toml +32 -22
- package/cli/templates/app/cjpm.toml +34 -34
- package/cli/templates/app/src/main.cj +101 -90
- package/cli/templates/app-react/README.md +56 -56
- package/cli/templates/app-react/assets/capabilities/default.json +7 -7
- package/cli/templates/app-react/assets/ui/index.html +25 -25
- package/cli/templates/app-react/assets/ui/package.json +19 -19
- package/cli/templates/app-react/assets/ui/src/App.css +67 -67
- package/cli/templates/app-react/assets/ui/src/App.jsx +124 -124
- package/cli/templates/app-react/assets/ui/src/main.jsx +6 -6
- package/cli/templates/app-react/assets/ui/vite.config.js +24 -24
- package/cli/templates/app-react/cj-tauri.toml +33 -23
- package/cli/templates/app-react/cjpm.toml +34 -34
- package/cli/templates/app-react/src/main.cj +91 -91
- package/cli/templates/app-vue/README.md +56 -56
- package/cli/templates/app-vue/assets/capabilities/default.json +7 -7
- package/cli/templates/app-vue/assets/ui/index.html +25 -25
- package/cli/templates/app-vue/assets/ui/package.json +18 -18
- package/cli/templates/app-vue/assets/ui/src/App.vue +176 -176
- package/cli/templates/app-vue/assets/ui/src/main.js +4 -4
- package/cli/templates/app-vue/assets/ui/vite.config.js +24 -24
- package/cli/templates/app-vue/cj-tauri.toml +33 -23
- package/cli/templates/app-vue/cjpm.toml +34 -34
- package/cli/templates/app-vue/src/main.cj +91 -91
- package/cli/templates/ohos-skeleton/AppScope/app.json5 +13 -13
- package/cli/templates/ohos-skeleton/AppScope/resources/base/element/string.json +8 -8
- package/cli/templates/ohos-skeleton/AppScope/resources/base/media/layered_image.json +6 -6
- package/cli/templates/ohos-skeleton/README.md +84 -79
- package/cli/templates/ohos-skeleton/build-hap.sh +15 -0
- package/cli/templates/ohos-skeleton/build-profile.json5 +46 -46
- package/cli/templates/ohos-skeleton/entry/build-profile.json5 +26 -26
- package/cli/templates/ohos-skeleton/entry/cjpm.toml +51 -43
- package/cli/templates/ohos-skeleton/entry/hvigorfile.ts +6 -6
- package/cli/templates/ohos-skeleton/entry/oh-package.json5 +9 -9
- package/cli/templates/ohos-skeleton/entry/src/main/cangjie/ability_stage.cj +17 -17
- package/cli/templates/ohos-skeleton/entry/src/main/cangjie/app_host.cj +94 -94
- package/cli/templates/ohos-skeleton/entry/src/main/cangjie/dialog_host.cj +217 -0
- package/cli/templates/ohos-skeleton/entry/src/main/cangjie/index.cj +527 -167
- package/cli/templates/ohos-skeleton/entry/src/main/cangjie/main_ability.cj +139 -139
- package/cli/templates/ohos-skeleton/entry/src/main/module.json5 +57 -49
- package/cli/templates/ohos-skeleton/entry/src/main/resources/base/element/color.json +8 -8
- package/cli/templates/ohos-skeleton/entry/src/main/resources/base/element/string.json +16 -16
- package/cli/templates/ohos-skeleton/entry/src/main/resources/base/media/layered_image.json +6 -6
- package/cli/templates/ohos-skeleton/entry/src/main/resources/base/profile/main_pages.json +2 -2
- package/cli/templates/ohos-skeleton/entry/src/main/resources/rawfile/capabilities.json +6 -6
- package/cli/templates/ohos-skeleton/entry/src/main/resources/rawfile/index.html +92 -92
- package/cli/templates/ohos-skeleton/hvigor/hvigor-config.json5 +5 -5
- package/cli/templates/ohos-skeleton/hvigorfile.ts +6 -6
- package/cli/templates/ohos-skeleton/oh-package.json5 +10 -10
- package/native/build_win.bat +62 -62
- package/native/core/bridge_core.c +1681 -1626
- package/native/core/bridge_core.h +675 -618
- package/native/core/bridge_js.h +108 -108
- package/native/platforms/harmonyos/README.md +115 -6
- package/native/platforms/linux/bridge_linux.c +2787 -2485
- package/native/platforms/windows/bridge_win.c +3740 -3248
- package/native/tests/gtk_threading_probe.c +143 -143
- package/native/tests/test_bridge_core.c +1339 -1228
- package/package.json +53 -53
- package/prebuilt/linux-x64/cj-tauri +0 -0
- package/src/api_system.cj +67 -67
- package/src/app.cj +325 -969
- package/src/app_events.cj +166 -0
- package/src/app_host_ops.cj +287 -0
- package/src/app_run.cj +283 -0
- package/src/app_spec.cj +76 -76
- package/src/arkweb_menu.cj +216 -0
- package/src/arkweb_script.cj +142 -142
- package/src/capability.cj +409 -409
- package/src/clipboard_bridge.cj +178 -0
- package/src/dialog_spec.cj +79 -0
- package/src/dragdrop.cj +26 -26
- package/src/embedded_assets.cj +98 -98
- package/src/host.cj +752 -607
- package/src/host_arkweb.cj +924 -778
- package/src/host_webkit.cj +663 -570
- package/src/host_webview2.cj +663 -570
- package/src/hotkey.cj +66 -66
- package/src/ipc_hub.cj +337 -337
- package/src/ipc_message.cj +286 -286
- package/src/launch.cj +62 -62
- package/src/logging.cj +127 -127
- package/src/menu.cj +197 -197
- package/src/platform/platform_app_context.cj +77 -77
- package/src/platform/platform_assets.cj +33 -33
- package/src/platform/platform_discover.cj +176 -176
- package/src/platform/platform_env.cj +29 -29
- package/src/platform/platform_feature.cj +31 -31
- package/src/platform/platform_page_source.cj +87 -87
- package/src/platform/platform_target_info.cj +32 -32
- package/src/platform_host_provider.cj +87 -87
- package/src/plugin.cj +333 -333
- package/src/plugins/clipboard/plugin_clipboard.cj +152 -152
- package/src/plugins/dialog/plugin_dialog.cj +209 -209
- package/src/plugins/fs/plugin_fs.cj +105 -1
- package/src/plugins/http/http_backend.cj +131 -0
- package/src/plugins/http/http_desktop.cj +195 -0
- package/src/plugins/http/http_ohos.cj +204 -0
- package/src/plugins/http/plugin_http.cj +310 -459
- package/src/plugins/log/plugin_log.cj +105 -105
- package/src/plugins/menu/plugin_menu.cj +158 -158
- package/src/plugins/notification/plugin_notification.cj +154 -154
- package/src/plugins/serial/plugin_serial.cj +458 -454
- package/src/plugins/serial/serial_bridge.cj +194 -194
- package/src/plugins/serial/serial_manager_ohos.cj +92 -0
- package/src/plugins/serial/serial_ohos.cj +529 -0
- package/src/plugins/shell/plugin_shell.cj +258 -258
- package/src/plugins/sqlite/plugin_sqlite.cj +705 -710
- package/src/plugins/sqlite/sqlite_ffi.cj +206 -211
- package/src/plugins/ws/plugin_ws.cj +488 -470
- package/src/process_hidden.cj +174 -174
- package/src/scope.cj +391 -391
- package/src/shell_event.cj +69 -69
- package/src/tests/app_spec_test.cj +126 -127
- package/src/tests/capability_test.cj +243 -243
- package/src/tests/dialog_spec_test.cj +73 -0
- package/src/tests/fake_host.cj +201 -201
- package/src/tests/ipc_hub_test.cj +487 -487
- package/src/tests/logging_test.cj +62 -62
- package/src/tests/platform_contract_test.cj +251 -251
- package/src/tests/plugin_clipboard_test.cj +222 -222
- package/src/tests/plugin_dialog_test.cj +237 -237
- package/src/tests/plugin_fs_test.cj +207 -0
- package/src/tests/plugin_http_test.cj +124 -124
- package/src/tests/plugin_notification_test.cj +205 -205
- package/src/tests/plugin_serial_test.cj +48 -0
- package/src/tests/plugin_test.cj +605 -585
- package/src/tests/plugin_ws_test.cj +40 -40
- package/src/tests/process_hidden_test.cj +129 -129
- package/src/tests/scope_test.cj +350 -350
- package/src/tests/system_host_test.cj +99 -81
- package/src/tests/urlutil_test.cj +53 -53
- package/src/tests/version_test.cj +75 -75
- package/src/tests/window_registry_test.cj +123 -123
- package/src/tray.cj +90 -90
- package/src/urlutil.cj +159 -159
- package/src/version.cj +44 -44
- package/src/window.cj +51 -51
- package/src/window_registry.cj +116 -116
- package/prebuilt/win32-x64/cj-tauri.exe +0 -0
- package/src/plugins/serial/serial_ohos_stub.cj +0 -61
- package/src/plugins/sqlite/sqlite_ohos_stub.cj +0 -91
|
@@ -1,211 +1,206 @@
|
|
|
1
|
-
package cjTauri.plugins.sqlite
|
|
2
|
-
|
|
3
|
-
import cjTauri.*
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* SQLite C API 的 FFI 声明与最小包装(`sqlite` 插件的地基)
|
|
7
|
-
*
|
|
8
|
-
* **为什么直连系统库而不进 C 桥**(docs/设计决策记录.md D-018 第 2 条):现有 `cj_bridge_*` 之所以存在,
|
|
9
|
-
* 是因为平台差异集中在 C 桥里;SQLite 相反——三平台同一套 C API、没有平台分支,再包一层只是多一份要
|
|
10
|
-
* 维护的转发代码。代价是「链接谁」从「桥提供」变成「消费方各自提供」:Linux 链发行版系统库
|
|
11
|
-
* (`-lsqlite3`,本机 3.45.1),Windows 侧未落地(见 D-018 第 8 条)。
|
|
12
|
-
*
|
|
13
|
-
* **FFI 语法是实测出来的**(三条都进 AGENTS §4):
|
|
14
|
-
* 1. 仓颉**没有** `&x` 取地址(写它会报 `expected expression after ','`);C 出参在**调用处**写
|
|
15
|
-
* `inout <var>`,自动取址成 `CPointer<T>`——修饰对象只能是 `var`,且指针仅在本次调用期间有效。
|
|
16
|
-
* 2. 「可选传 NULL 的 C 字符串」(这里的 `zVfs`)声明成 `CPointer<UInt8>` 并传 `CPointer<UInt8>()`;
|
|
17
|
-
* 传空 `CString` 会被 SQLite 当成「名字为空的 VFS」,报的是 `no such vfs`(实测踩过)。
|
|
18
|
-
* 3. C 回调声明成 `CFunc<(...) -> 返回类型>`,回调本体是顶层 `@C func`(本仓 `cj_bridge_init` 先例)。
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
/** SQLite 返回码(sqlite3.h 的子集,只列我们判过的) */
|
|
22
|
-
let SQLITE_OK: Int32 = 0
|
|
23
|
-
let SQLITE_ROW: Int32 = 100
|
|
24
|
-
let SQLITE_DONE: Int32 = 101
|
|
25
|
-
/** sqlite3_exec 在授权回调拒绝时给的是 SQLITE_AUTH(列出来便于断言时看明白) */
|
|
26
|
-
let SQLITE_AUTH: Int32 = 23
|
|
27
|
-
|
|
28
|
-
/** 列类型(sqlite3_column_type):界面要能说清「这格是数字还是文本」,所以逐格判 */
|
|
29
|
-
let SQLITE_INTEGER: Int32 = 1
|
|
30
|
-
let SQLITE_FLOAT: Int32 = 2
|
|
31
|
-
let SQLITE_TEXT: Int32 = 3
|
|
32
|
-
let SQLITE_BLOB: Int32 = 4
|
|
33
|
-
let SQLITE_NULL: Int32 = 5
|
|
34
|
-
|
|
35
|
-
/** 打开标志(sqlite3_open_v2):只读走 READONLY,写路径要显式给 READWRITE */
|
|
36
|
-
let SQLITE_OPEN_READONLY: Int32 = 1
|
|
37
|
-
let SQLITE_OPEN_READWRITE: Int32 = 2
|
|
38
|
-
let SQLITE_OPEN_CREATE: Int32 = 4
|
|
39
|
-
|
|
40
|
-
/** 授权动作码(sqlite3_set_authorizer):只列我们要拒的三类 */
|
|
41
|
-
let SQLITE_ATTACH: Int32 = 24
|
|
42
|
-
let SQLITE_DETACH: Int32 = 25
|
|
43
|
-
let SQLITE_FUNCTION: Int32 = 31
|
|
44
|
-
|
|
45
|
-
/** 授权回调返回值 */
|
|
46
|
-
let SQLITE_DENY: Int32 = 1
|
|
47
|
-
|
|
48
|
-
/** busy 等待上限(毫秒):另一个进程正写这个库时等着,而不是当场报 SQLITE_BUSY */
|
|
49
|
-
let SQLITE_BUSY_TIMEOUT_MS: Int32 = 3000
|
|
50
|
-
|
|
51
|
-
@C
|
|
52
|
-
foreign func sqlite3_libversion(): CString
|
|
53
|
-
|
|
54
|
-
@C
|
|
55
|
-
foreign func sqlite3_open_v2(filename: CString, ppDb: CPointer<CPointer<Unit>>, flags: Int32,
|
|
56
|
-
zVfs: CPointer<UInt8>): Int32
|
|
57
|
-
|
|
58
|
-
@C
|
|
59
|
-
foreign func sqlite3_close(db: CPointer<Unit>): Int32
|
|
60
|
-
|
|
61
|
-
@C
|
|
62
|
-
foreign func sqlite3_errmsg(db: CPointer<Unit>): CString
|
|
63
|
-
|
|
64
|
-
@C
|
|
65
|
-
foreign func sqlite3_exec(db: CPointer<Unit>, sql: CString, cb: CPointer<Unit>, arg: CPointer<Unit>,
|
|
66
|
-
errmsg: CPointer<Unit>): Int32
|
|
67
|
-
|
|
68
|
-
@C
|
|
69
|
-
foreign func sqlite3_changes(db: CPointer<Unit>): Int32
|
|
70
|
-
|
|
71
|
-
@C
|
|
72
|
-
foreign func sqlite3_last_insert_rowid(db: CPointer<Unit>): Int64
|
|
73
|
-
|
|
74
|
-
@C
|
|
75
|
-
foreign func sqlite3_busy_timeout(db: CPointer<Unit>, ms: Int32): Int32
|
|
76
|
-
|
|
77
|
-
@C
|
|
78
|
-
foreign func sqlite3_prepare_v2(db: CPointer<Unit>, sql: CString, nByte: Int32,
|
|
79
|
-
ppStmt: CPointer<CPointer<Unit>>, pzTail: CPointer<Unit>): Int32
|
|
80
|
-
|
|
81
|
-
@C
|
|
82
|
-
foreign func sqlite3_step(stmt: CPointer<Unit>): Int32
|
|
83
|
-
|
|
84
|
-
@C
|
|
85
|
-
foreign func sqlite3_finalize(stmt: CPointer<Unit>): Int32
|
|
86
|
-
|
|
87
|
-
@C
|
|
88
|
-
foreign func sqlite3_column_count(stmt: CPointer<Unit>): Int32
|
|
89
|
-
|
|
90
|
-
@C
|
|
91
|
-
foreign func sqlite3_column_name(stmt: CPointer<Unit>, i: Int32): CString
|
|
92
|
-
|
|
93
|
-
@C
|
|
94
|
-
foreign func sqlite3_column_type(stmt: CPointer<Unit>, i: Int32): Int32
|
|
95
|
-
|
|
96
|
-
@C
|
|
97
|
-
foreign func sqlite3_column_int64(stmt: CPointer<Unit>, i: Int32): Int64
|
|
98
|
-
|
|
99
|
-
@C
|
|
100
|
-
foreign func sqlite3_column_double(stmt: CPointer<Unit>, i: Int32): Float64
|
|
101
|
-
|
|
102
|
-
@C
|
|
103
|
-
foreign func sqlite3_column_text(stmt: CPointer<Unit>, i: Int32): CString
|
|
104
|
-
|
|
105
|
-
@C
|
|
106
|
-
foreign func sqlite3_column_bytes(stmt: CPointer<Unit>, i: Int32): Int32
|
|
107
|
-
|
|
108
|
-
@C
|
|
109
|
-
foreign func sqlite3_set_authorizer(
|
|
110
|
-
db: CPointer<Unit>,
|
|
111
|
-
cb: CFunc<(CPointer<Unit>, Int32, CString, CString, CString, CString) -> Int32>,
|
|
112
|
-
userdata: CPointer<Unit>): Int32
|
|
113
|
-
|
|
114
|
-
@C
|
|
115
|
-
foreign func sqlite3_enable_load_extension(db: CPointer<Unit>, onoff: Int32): Int32
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* 授权回调:拒掉「跑到别的文件去」的动作——`ATTACH` / `DETACH` 换库文件、
|
|
119
|
-
* `load_extension()` 加载任意原生库。**必须按语句判**:路径 scope 只管得住本次命令收到的那个路径,
|
|
120
|
-
* 管不住 SQL 里写死的另一个路径(D-018 第 4 条)。被拒时留一行 stderr,取证时能对上账。
|
|
121
|
-
*/
|
|
122
|
-
@
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
let _ =
|
|
127
|
-
let _ =
|
|
128
|
-
let _ =
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/** 本机链接的 SQLite 版本(`sqlite:info` 回投给页面,对账时也用它) */
|
|
208
|
-
@When[env != "ohos"]
|
|
209
|
-
func sqliteLibVersion(): String {
|
|
210
|
-
return sqliteCString(unsafe { sqlite3_libversion() })
|
|
211
|
-
}
|
|
1
|
+
package cjTauri.plugins.sqlite
|
|
2
|
+
|
|
3
|
+
import cjTauri.*
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* SQLite C API 的 FFI 声明与最小包装(`sqlite` 插件的地基)
|
|
7
|
+
*
|
|
8
|
+
* **为什么直连系统库而不进 C 桥**(docs/设计决策记录.md D-018 第 2 条):现有 `cj_bridge_*` 之所以存在,
|
|
9
|
+
* 是因为平台差异集中在 C 桥里;SQLite 相反——三平台同一套 C API、没有平台分支,再包一层只是多一份要
|
|
10
|
+
* 维护的转发代码。代价是「链接谁」从「桥提供」变成「消费方各自提供」:Linux 链发行版系统库
|
|
11
|
+
* (`-lsqlite3`,本机 3.45.1),Windows 侧未落地(见 D-018 第 8 条)。
|
|
12
|
+
*
|
|
13
|
+
* **FFI 语法是实测出来的**(三条都进 AGENTS §4):
|
|
14
|
+
* 1. 仓颉**没有** `&x` 取地址(写它会报 `expected expression after ','`);C 出参在**调用处**写
|
|
15
|
+
* `inout <var>`,自动取址成 `CPointer<T>`——修饰对象只能是 `var`,且指针仅在本次调用期间有效。
|
|
16
|
+
* 2. 「可选传 NULL 的 C 字符串」(这里的 `zVfs`)声明成 `CPointer<UInt8>` 并传 `CPointer<UInt8>()`;
|
|
17
|
+
* 传空 `CString` 会被 SQLite 当成「名字为空的 VFS」,报的是 `no such vfs`(实测踩过)。
|
|
18
|
+
* 3. C 回调声明成 `CFunc<(...) -> 返回类型>`,回调本体是顶层 `@C func`(本仓 `cj_bridge_init` 先例)。
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/** SQLite 返回码(sqlite3.h 的子集,只列我们判过的) */
|
|
22
|
+
let SQLITE_OK: Int32 = 0
|
|
23
|
+
let SQLITE_ROW: Int32 = 100
|
|
24
|
+
let SQLITE_DONE: Int32 = 101
|
|
25
|
+
/** sqlite3_exec 在授权回调拒绝时给的是 SQLITE_AUTH(列出来便于断言时看明白) */
|
|
26
|
+
let SQLITE_AUTH: Int32 = 23
|
|
27
|
+
|
|
28
|
+
/** 列类型(sqlite3_column_type):界面要能说清「这格是数字还是文本」,所以逐格判 */
|
|
29
|
+
let SQLITE_INTEGER: Int32 = 1
|
|
30
|
+
let SQLITE_FLOAT: Int32 = 2
|
|
31
|
+
let SQLITE_TEXT: Int32 = 3
|
|
32
|
+
let SQLITE_BLOB: Int32 = 4
|
|
33
|
+
let SQLITE_NULL: Int32 = 5
|
|
34
|
+
|
|
35
|
+
/** 打开标志(sqlite3_open_v2):只读走 READONLY,写路径要显式给 READWRITE */
|
|
36
|
+
let SQLITE_OPEN_READONLY: Int32 = 1
|
|
37
|
+
let SQLITE_OPEN_READWRITE: Int32 = 2
|
|
38
|
+
let SQLITE_OPEN_CREATE: Int32 = 4
|
|
39
|
+
|
|
40
|
+
/** 授权动作码(sqlite3_set_authorizer):只列我们要拒的三类 */
|
|
41
|
+
let SQLITE_ATTACH: Int32 = 24
|
|
42
|
+
let SQLITE_DETACH: Int32 = 25
|
|
43
|
+
let SQLITE_FUNCTION: Int32 = 31
|
|
44
|
+
|
|
45
|
+
/** 授权回调返回值 */
|
|
46
|
+
let SQLITE_DENY: Int32 = 1
|
|
47
|
+
|
|
48
|
+
/** busy 等待上限(毫秒):另一个进程正写这个库时等着,而不是当场报 SQLITE_BUSY */
|
|
49
|
+
let SQLITE_BUSY_TIMEOUT_MS: Int32 = 3000
|
|
50
|
+
|
|
51
|
+
@C
|
|
52
|
+
foreign func sqlite3_libversion(): CString
|
|
53
|
+
|
|
54
|
+
@C
|
|
55
|
+
foreign func sqlite3_open_v2(filename: CString, ppDb: CPointer<CPointer<Unit>>, flags: Int32,
|
|
56
|
+
zVfs: CPointer<UInt8>): Int32
|
|
57
|
+
|
|
58
|
+
@C
|
|
59
|
+
foreign func sqlite3_close(db: CPointer<Unit>): Int32
|
|
60
|
+
|
|
61
|
+
@C
|
|
62
|
+
foreign func sqlite3_errmsg(db: CPointer<Unit>): CString
|
|
63
|
+
|
|
64
|
+
@C
|
|
65
|
+
foreign func sqlite3_exec(db: CPointer<Unit>, sql: CString, cb: CPointer<Unit>, arg: CPointer<Unit>,
|
|
66
|
+
errmsg: CPointer<Unit>): Int32
|
|
67
|
+
|
|
68
|
+
@C
|
|
69
|
+
foreign func sqlite3_changes(db: CPointer<Unit>): Int32
|
|
70
|
+
|
|
71
|
+
@C
|
|
72
|
+
foreign func sqlite3_last_insert_rowid(db: CPointer<Unit>): Int64
|
|
73
|
+
|
|
74
|
+
@C
|
|
75
|
+
foreign func sqlite3_busy_timeout(db: CPointer<Unit>, ms: Int32): Int32
|
|
76
|
+
|
|
77
|
+
@C
|
|
78
|
+
foreign func sqlite3_prepare_v2(db: CPointer<Unit>, sql: CString, nByte: Int32,
|
|
79
|
+
ppStmt: CPointer<CPointer<Unit>>, pzTail: CPointer<Unit>): Int32
|
|
80
|
+
|
|
81
|
+
@C
|
|
82
|
+
foreign func sqlite3_step(stmt: CPointer<Unit>): Int32
|
|
83
|
+
|
|
84
|
+
@C
|
|
85
|
+
foreign func sqlite3_finalize(stmt: CPointer<Unit>): Int32
|
|
86
|
+
|
|
87
|
+
@C
|
|
88
|
+
foreign func sqlite3_column_count(stmt: CPointer<Unit>): Int32
|
|
89
|
+
|
|
90
|
+
@C
|
|
91
|
+
foreign func sqlite3_column_name(stmt: CPointer<Unit>, i: Int32): CString
|
|
92
|
+
|
|
93
|
+
@C
|
|
94
|
+
foreign func sqlite3_column_type(stmt: CPointer<Unit>, i: Int32): Int32
|
|
95
|
+
|
|
96
|
+
@C
|
|
97
|
+
foreign func sqlite3_column_int64(stmt: CPointer<Unit>, i: Int32): Int64
|
|
98
|
+
|
|
99
|
+
@C
|
|
100
|
+
foreign func sqlite3_column_double(stmt: CPointer<Unit>, i: Int32): Float64
|
|
101
|
+
|
|
102
|
+
@C
|
|
103
|
+
foreign func sqlite3_column_text(stmt: CPointer<Unit>, i: Int32): CString
|
|
104
|
+
|
|
105
|
+
@C
|
|
106
|
+
foreign func sqlite3_column_bytes(stmt: CPointer<Unit>, i: Int32): Int32
|
|
107
|
+
|
|
108
|
+
@C
|
|
109
|
+
foreign func sqlite3_set_authorizer(
|
|
110
|
+
db: CPointer<Unit>,
|
|
111
|
+
cb: CFunc<(CPointer<Unit>, Int32, CString, CString, CString, CString) -> Int32>,
|
|
112
|
+
userdata: CPointer<Unit>): Int32
|
|
113
|
+
|
|
114
|
+
@C
|
|
115
|
+
foreign func sqlite3_enable_load_extension(db: CPointer<Unit>, onoff: Int32): Int32
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* 授权回调:拒掉「跑到别的文件去」的动作——`ATTACH` / `DETACH` 换库文件、
|
|
119
|
+
* `load_extension()` 加载任意原生库。**必须按语句判**:路径 scope 只管得住本次命令收到的那个路径,
|
|
120
|
+
* 管不住 SQL 里写死的另一个路径(D-018 第 4 条)。被拒时留一行 stderr,取证时能对上账。
|
|
121
|
+
*/
|
|
122
|
+
@C
|
|
123
|
+
func sqliteAuthorizer(app: CPointer<Unit>, code: Int32, arg1: CString, arg2: CString,
|
|
124
|
+
dbName: CString, triggerName: CString): Int32 {
|
|
125
|
+
let _ = app
|
|
126
|
+
let _ = arg2
|
|
127
|
+
let _ = dbName
|
|
128
|
+
let _ = triggerName
|
|
129
|
+
if (code == SQLITE_ATTACH || code == SQLITE_DETACH) {
|
|
130
|
+
eprintln("[cj-tauri] sqlite denied: attach/detach is not allowed (code=${code})")
|
|
131
|
+
return SQLITE_DENY
|
|
132
|
+
}
|
|
133
|
+
if (code == SQLITE_FUNCTION) {
|
|
134
|
+
// arg1 是被调用的函数名:只拒能加载原生代码的那个,其余内置函数照常放行
|
|
135
|
+
let fnName = sqliteCString(arg1)
|
|
136
|
+
if (fnName == "load_extension") {
|
|
137
|
+
eprintln("[cj-tauri] sqlite denied: load_extension() is not allowed")
|
|
138
|
+
return SQLITE_DENY
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return SQLITE_OK
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** C 字符串 → 仓颉字符串;NULL 给空串(调用方要区分 NULL 与空串时另判归属) */
|
|
145
|
+
func sqliteCString(s: CString): String {
|
|
146
|
+
if (s.isNull()) {
|
|
147
|
+
return ""
|
|
148
|
+
}
|
|
149
|
+
return s.toString()
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** 取最近一次错误文案;db 为空时给固定文案,避免收尾路径上再炸一次 */
|
|
153
|
+
func sqliteLastError(db: CPointer<Unit>): String {
|
|
154
|
+
if (db.isNull()) {
|
|
155
|
+
return "unknown error (null db handle)"
|
|
156
|
+
}
|
|
157
|
+
return sqliteCString(unsafe { sqlite3_errmsg(db) })
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** 关掉句柄:对空指针安全(出错路径也要能收尾),关不掉只记一行 stderr 不抛 */
|
|
161
|
+
func sqliteCloseQuietly(db: CPointer<Unit>): Unit {
|
|
162
|
+
if (db.isNull()) {
|
|
163
|
+
return
|
|
164
|
+
}
|
|
165
|
+
let rc = unsafe { sqlite3_close(db) }
|
|
166
|
+
if (rc != SQLITE_OK) {
|
|
167
|
+
eprintln("[cj-tauri] sqlite close returned ${rc}")
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* 打开数据库并装上护栏(每次命令短连接,见 D-018 第 9 条)。
|
|
173
|
+
*
|
|
174
|
+
* `readonly=true` 走 `SQLITE_OPEN_READONLY`——只读是**内核级**的,不是我们写的检查;
|
|
175
|
+
* 不存在的文件 + 只读 = 打开失败(不会顺手造一个空库)。
|
|
176
|
+
* 打开失败与护栏装不上都抛 `CommandException`(前端拿到可读文案)。
|
|
177
|
+
*/
|
|
178
|
+
func sqliteOpenGuarded(path: String, readonly: Bool): CPointer<Unit> {
|
|
179
|
+
var db: CPointer<Unit> = CPointer<Unit>()
|
|
180
|
+
let flags = if (readonly) {
|
|
181
|
+
SQLITE_OPEN_READONLY
|
|
182
|
+
} else {
|
|
183
|
+
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE
|
|
184
|
+
}
|
|
185
|
+
// inout db 取的是「栈上那个指针变量」的地址:C 侧写入的 handle 直接落到 db 上
|
|
186
|
+
let rc = unsafe { sqlite3_open_v2(LibC.mallocCString(path), inout db, flags, CPointer<UInt8>()) }
|
|
187
|
+
if (rc != SQLITE_OK) {
|
|
188
|
+
let msg = sqliteLastError(db)
|
|
189
|
+
sqliteCloseQuietly(db)
|
|
190
|
+
throw CommandException("sqlite: cannot open ${path}: ${msg}")
|
|
191
|
+
}
|
|
192
|
+
// 双保险之一:先关掉扩展加载(authorizer 之外再加一道)
|
|
193
|
+
let _ = unsafe { sqlite3_enable_load_extension(db, 0) }
|
|
194
|
+
let rcAuthorizer = unsafe { sqlite3_set_authorizer(db, sqliteAuthorizer, CPointer<Unit>()) }
|
|
195
|
+
if (rcAuthorizer != SQLITE_OK) {
|
|
196
|
+
sqliteCloseQuietly(db)
|
|
197
|
+
throw CommandException("sqlite: cannot install authorizer (rc=${rcAuthorizer})")
|
|
198
|
+
}
|
|
199
|
+
let _ = unsafe { sqlite3_busy_timeout(db, SQLITE_BUSY_TIMEOUT_MS) }
|
|
200
|
+
return db
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/** 本机链接的 SQLite 版本(`sqlite:info` 回投给页面,对账时也用它) */
|
|
204
|
+
func sqliteLibVersion(): String {
|
|
205
|
+
return sqliteCString(unsafe { sqlite3_libversion() })
|
|
206
|
+
}
|