@yufengtadian/freedom-cli 1.13.1 → 1.13.3
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/LICENSE +40 -0
- package/README.md +119 -15
- package/lib/agents.js +448 -0
- package/lib/build.js +189 -45
- package/lib/cli.js +258 -9
- package/lib/config.js +20 -1
- package/lib/desktop.js +133 -0
- package/lib/dev.js +149 -0
- package/lib/mcp.js +217 -0
- package/lib/release.js +90 -0
- package/lib/security.js +113 -54
- package/lib/shell.js +170 -63
- package/lib/toolchain.js +339 -0
- package/lib/tui.js +37 -1
- package/lib/utils.js +51 -0
- package/lib/verify.js +48 -12
- package/lib/webkit.js +45 -0
- package/package.json +3 -2
- package/shell/darwin-arm64/freedom-shell +0 -0
- package/shell/linux-x64/freedom-shell +0 -0
- package/shell/win-x64/freedom-shell.exe +0 -0
- package/skill/freedom/SKILL.md +159 -0
- package/templates/desktop/app.html +559 -0
- package/templates/desktop/backend/desktop.mjs +327 -0
- package/templates/desktop/freedom.config.js +32 -0
- package/templates/desktop/icon.ico +0 -0
- package/templates/go/go.mod +3 -0
- package/templates/go/pkg/freedom/anti_debug_linux.go +69 -0
- package/templates/go/pkg/freedom/anti_debug_other.go +5 -3
- package/templates/go/pkg/freedom/anti_debug_windows.go +238 -11
- package/templates/go/pkg/freedom/assets/freedom.js +3 -0
- package/templates/go/pkg/freedom/assets_embed.go +1 -0
- package/templates/go/pkg/freedom/backend_proc.go +5 -5
- package/templates/go/pkg/freedom/events_windows.go +5 -5
- package/templates/go/pkg/freedom/freedom.go +64 -10
- package/templates/go/pkg/freedom/msgwindow_windows.go +8 -8
- package/templates/go/pkg/freedom/resources.go +119 -14
- package/templates/go/pkg/freedom/securetemp.go +61 -0
- package/templates/go/pkg/freedom/securetemp_other.go +20 -0
- package/templates/go/pkg/freedom/securetemp_windows.go +25 -0
- package/templates/go/pkg/freedom/security.go +293 -64
- package/templates/go/pkg/freedom/shutdown.go +55 -0
- package/templates/go/pkg/freedom/shutdown_windows.go +47 -0
- package/templates/go/pkg/freedom/store.go +11 -3
- package/templates/go/pkg/freedom/syscap_windows.go +33 -33
- package/templates/go/pkg/freedom/sysint_windows.go +2 -2
- package/templates/go/pkg/freedom/tray_windows.go +18 -18
- package/templates/go/pkg/freedom/updater.go +3 -3
- package/templates/go/pkg/freedom/window_other.go +7 -1
- package/templates/go/pkg/freedom/window_windows.go +185 -17
- package/templates/go/third_party/webview_go/CHANGELOG.md +15 -0
- package/templates/go/third_party/webview_go/FREEDOM-PATCH.md +32 -0
- package/templates/go/third_party/webview_go/LICENSE +22 -0
- package/templates/go/third_party/webview_go/README.md +50 -0
- package/templates/go/third_party/webview_go/glue.c +36 -0
- package/templates/go/third_party/webview_go/go.mod +3 -0
- package/templates/go/third_party/webview_go/go.sum +0 -0
- package/templates/go/third_party/webview_go/libs/mswebview2/LICENSE +27 -0
- package/templates/go/third_party/webview_go/libs/mswebview2/include/WebView2.h +23568 -0
- package/templates/go/third_party/webview_go/libs/mswebview2/include/vendor.go +2 -0
- package/templates/go/third_party/webview_go/libs/mswebview2/vendor.go +2 -0
- package/templates/go/third_party/webview_go/libs/mswebview2/version.txt +1 -0
- package/templates/go/third_party/webview_go/libs/webview/LICENSE +22 -0
- package/templates/go/third_party/webview_go/libs/webview/include/vendor.go +2 -0
- package/templates/go/third_party/webview_go/libs/webview/include/webview.h +3598 -0
- package/templates/go/third_party/webview_go/libs/webview/vendor.go +2 -0
- package/templates/go/third_party/webview_go/libs/webview/version.txt +1 -0
- package/templates/go/third_party/webview_go/webkit2_40.go +21 -0
- package/templates/go/third_party/webview_go/webkit2_41.go +8 -0
- package/templates/go/third_party/webview_go/webview.cc +1 -0
- package/templates/go/third_party/webview_go/webview.go +332 -0
- package/templates/installer/app.nsi +43 -0
- package/templates/project/freedom.config.js +14 -0
- package/templates/project/freedom.d.ts +77 -0
- package/templates/project-minimal/freedom.config.js +14 -0
- package/templates/project-minimal/freedom.d.ts +77 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
fb6b17d826041411e6346cd9a785a5ceba7987c4
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// 本地补丁(Freedom):WebKitGTK 的 pkg-config 依赖名按构建标签选择,
|
|
2
|
+
// 上游把它写死成 webkit2gtk-4.0,而 Ubuntu 24.04 / Debian 13 已移除 4.0,
|
|
3
|
+
// 只保留同一套 C API 的 webkit2gtk-4.1 —— 写死会让 `go build` 在新发行版上直接失败。
|
|
4
|
+
//
|
|
5
|
+
// 选择规则(两个文件互斥,任何时刻只有一行 pkg-config 生效):
|
|
6
|
+
//
|
|
7
|
+
// 默认(无标签) → webkit2gtk-4.0(老发行版与既有 CI 产物基线不变)
|
|
8
|
+
// -tags webkit2_41 → webkit2gtk-4.1
|
|
9
|
+
//
|
|
10
|
+
// 构建脚本按 pkg-config 实际可用性自动决定是否加 -tags webkit2_41,见
|
|
11
|
+
// freedom-cli/lib/webkit.js 与 tools/webkit-env.sh。
|
|
12
|
+
// webkitgtk-6.0 是另一套 API(NetworkSession/权限处理器重写),不能按此桥接,需上游适配。
|
|
13
|
+
|
|
14
|
+
//go:build !webkit2_41
|
|
15
|
+
|
|
16
|
+
package webview
|
|
17
|
+
|
|
18
|
+
/*
|
|
19
|
+
#cgo linux openbsd freebsd netbsd pkg-config: gtk+-3.0 webkit2gtk-4.0
|
|
20
|
+
*/
|
|
21
|
+
import "C"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#include "webview.h"
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
package webview
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
#cgo CFLAGS: -I${SRCDIR}/libs/webview/include
|
|
5
|
+
#cgo CXXFLAGS: -I${SRCDIR}/libs/webview/include -DWEBVIEW_STATIC
|
|
6
|
+
|
|
7
|
+
#cgo linux openbsd freebsd netbsd CXXFLAGS: -DWEBVIEW_GTK -std=c++11
|
|
8
|
+
#cgo linux openbsd freebsd netbsd LDFLAGS: -ldl
|
|
9
|
+
// 本地补丁:webkit2gtk 的 pkg-config 名字不再写死为 4.0,改由 webkit2_40.go /
|
|
10
|
+
// webkit2_41.go 按构建标签提供(Ubuntu 24.04+ 已移除 webkit2gtk-4.0)。
|
|
11
|
+
|
|
12
|
+
#cgo darwin CXXFLAGS: -DWEBVIEW_COCOA -std=c++11
|
|
13
|
+
#cgo darwin LDFLAGS: -framework WebKit -ldl
|
|
14
|
+
|
|
15
|
+
#cgo windows CXXFLAGS: -DWEBVIEW_EDGE -std=c++14 -I${SRCDIR}/libs/mswebview2/include
|
|
16
|
+
#cgo windows LDFLAGS: -static -ladvapi32 -lole32 -lshell32 -lshlwapi -luser32 -lversion
|
|
17
|
+
|
|
18
|
+
#include "webview.h"
|
|
19
|
+
|
|
20
|
+
#include <stdlib.h>
|
|
21
|
+
#include <stdint.h>
|
|
22
|
+
|
|
23
|
+
void CgoWebViewDispatch(webview_t w, uintptr_t arg);
|
|
24
|
+
void CgoWebViewBind(webview_t w, const char *name, uintptr_t index);
|
|
25
|
+
void CgoWebViewUnbind(webview_t w, const char *name);
|
|
26
|
+
*/
|
|
27
|
+
import "C"
|
|
28
|
+
import (
|
|
29
|
+
_ "github.com/webview/webview_go/libs/mswebview2"
|
|
30
|
+
_ "github.com/webview/webview_go/libs/mswebview2/include"
|
|
31
|
+
_ "github.com/webview/webview_go/libs/webview"
|
|
32
|
+
_ "github.com/webview/webview_go/libs/webview/include"
|
|
33
|
+
"encoding/json"
|
|
34
|
+
"errors"
|
|
35
|
+
"reflect"
|
|
36
|
+
"runtime"
|
|
37
|
+
"sync"
|
|
38
|
+
"unsafe"
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
func init() {
|
|
42
|
+
// Ensure that main.main is called from the main thread
|
|
43
|
+
runtime.LockOSThread()
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Hints are used to configure window sizing and resizing
|
|
47
|
+
type Hint int
|
|
48
|
+
|
|
49
|
+
const (
|
|
50
|
+
// Width and height are default size
|
|
51
|
+
HintNone = C.WEBVIEW_HINT_NONE
|
|
52
|
+
|
|
53
|
+
// Window size can not be changed by a user
|
|
54
|
+
HintFixed = C.WEBVIEW_HINT_FIXED
|
|
55
|
+
|
|
56
|
+
// Width and height are minimum bounds
|
|
57
|
+
HintMin = C.WEBVIEW_HINT_MIN
|
|
58
|
+
|
|
59
|
+
// Width and height are maximum bounds
|
|
60
|
+
HintMax = C.WEBVIEW_HINT_MAX
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
type WebView interface {
|
|
64
|
+
|
|
65
|
+
// Run runs the main loop until it's terminated. After this function exits -
|
|
66
|
+
// you must destroy the webview.
|
|
67
|
+
Run()
|
|
68
|
+
|
|
69
|
+
// Terminate stops the main loop. It is safe to call this function from
|
|
70
|
+
// a background thread.
|
|
71
|
+
Terminate()
|
|
72
|
+
|
|
73
|
+
// Dispatch posts a function to be executed on the main thread. You normally
|
|
74
|
+
// do not need to call this function, unless you want to tweak the native
|
|
75
|
+
// window.
|
|
76
|
+
Dispatch(f func())
|
|
77
|
+
|
|
78
|
+
// Destroy destroys a webview and closes the native window.
|
|
79
|
+
Destroy()
|
|
80
|
+
|
|
81
|
+
// Window returns a native window handle pointer. When using GTK backend the
|
|
82
|
+
// pointer is GtkWindow pointer, when using Cocoa backend the pointer is
|
|
83
|
+
// NSWindow pointer, when using Win32 backend the pointer is HWND pointer.
|
|
84
|
+
Window() unsafe.Pointer
|
|
85
|
+
|
|
86
|
+
// SetTitle updates the title of the native window. Must be called from the UI
|
|
87
|
+
// thread.
|
|
88
|
+
SetTitle(title string)
|
|
89
|
+
|
|
90
|
+
// SetSize updates native window size. See Hint constants.
|
|
91
|
+
SetSize(w int, h int, hint Hint)
|
|
92
|
+
|
|
93
|
+
// Navigate navigates webview to the given URL. URL may be a properly encoded data.
|
|
94
|
+
// URI. Examples:
|
|
95
|
+
// w.Navigate("https://github.com/webview/webview")
|
|
96
|
+
// w.Navigate("data:text/html,%3Ch1%3EHello%3C%2Fh1%3E")
|
|
97
|
+
// w.Navigate("data:text/html;base64,PGgxPkhlbGxvPC9oMT4=")
|
|
98
|
+
Navigate(url string)
|
|
99
|
+
|
|
100
|
+
// SetHtml sets the webview HTML directly.
|
|
101
|
+
// Example: w.SetHtml(w, "<h1>Hello</h1>");
|
|
102
|
+
SetHtml(html string)
|
|
103
|
+
|
|
104
|
+
// Init injects JavaScript code at the initialization of the new page. Every
|
|
105
|
+
// time the webview will open a the new page - this initialization code will
|
|
106
|
+
// be executed. It is guaranteed that code is executed before window.onload.
|
|
107
|
+
Init(js string)
|
|
108
|
+
|
|
109
|
+
// Eval evaluates arbitrary JavaScript code. Evaluation happens asynchronously,
|
|
110
|
+
// also the result of the expression is ignored. Use RPC bindings if you want
|
|
111
|
+
// to receive notifications about the results of the evaluation.
|
|
112
|
+
Eval(js string)
|
|
113
|
+
|
|
114
|
+
// Bind binds a callback function so that it will appear under the given name
|
|
115
|
+
// as a global JavaScript function. Internally it uses webview_init().
|
|
116
|
+
// Callback receives a request string and a user-provided argument pointer.
|
|
117
|
+
// Request string is a JSON array of all the arguments passed to the
|
|
118
|
+
// JavaScript function.
|
|
119
|
+
//
|
|
120
|
+
// f must be a function
|
|
121
|
+
// f must return either value and error or just error
|
|
122
|
+
Bind(name string, f interface{}) error
|
|
123
|
+
|
|
124
|
+
// Removes a callback that was previously set by Bind.
|
|
125
|
+
Unbind(name string) error
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
type webview struct {
|
|
129
|
+
w C.webview_t
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
var (
|
|
133
|
+
m sync.Mutex
|
|
134
|
+
index uintptr
|
|
135
|
+
dispatch = map[uintptr]func(){}
|
|
136
|
+
bindings = map[uintptr]func(id, req string) (interface{}, error){}
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
func boolToInt(b bool) C.int {
|
|
140
|
+
if b {
|
|
141
|
+
return 1
|
|
142
|
+
}
|
|
143
|
+
return 0
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// New calls NewWindow to create a new window and a new webview instance. If debug
|
|
147
|
+
// is non-zero - developer tools will be enabled (if the platform supports them).
|
|
148
|
+
func New(debug bool) WebView { return NewWindow(debug, nil) }
|
|
149
|
+
|
|
150
|
+
// NewWindow creates a new webview instance. If debug is non-zero - developer
|
|
151
|
+
// tools will be enabled (if the platform supports them). Window parameter can be
|
|
152
|
+
// a pointer to the native window handle. If it's non-null - then child WebView is
|
|
153
|
+
// embedded into the given parent window. Otherwise a new window is created.
|
|
154
|
+
// Depending on the platform, a GtkWindow, NSWindow or HWND pointer can be passed
|
|
155
|
+
// here.
|
|
156
|
+
func NewWindow(debug bool, window unsafe.Pointer) WebView {
|
|
157
|
+
w := &webview{}
|
|
158
|
+
w.w = C.webview_create(boolToInt(debug), window)
|
|
159
|
+
return w
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
func (w *webview) Destroy() {
|
|
163
|
+
C.webview_destroy(w.w)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
func (w *webview) Run() {
|
|
167
|
+
C.webview_run(w.w)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
func (w *webview) Terminate() {
|
|
171
|
+
C.webview_terminate(w.w)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
func (w *webview) Window() unsafe.Pointer {
|
|
175
|
+
return C.webview_get_window(w.w)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
func (w *webview) Navigate(url string) {
|
|
179
|
+
s := C.CString(url)
|
|
180
|
+
defer C.free(unsafe.Pointer(s))
|
|
181
|
+
C.webview_navigate(w.w, s)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
func (w *webview) SetHtml(html string) {
|
|
185
|
+
s := C.CString(html)
|
|
186
|
+
defer C.free(unsafe.Pointer(s))
|
|
187
|
+
C.webview_set_html(w.w, s)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
func (w *webview) SetTitle(title string) {
|
|
191
|
+
s := C.CString(title)
|
|
192
|
+
defer C.free(unsafe.Pointer(s))
|
|
193
|
+
C.webview_set_title(w.w, s)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
func (w *webview) SetSize(width int, height int, hint Hint) {
|
|
197
|
+
C.webview_set_size(w.w, C.int(width), C.int(height), C.webview_hint_t(hint))
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
func (w *webview) Init(js string) {
|
|
201
|
+
s := C.CString(js)
|
|
202
|
+
defer C.free(unsafe.Pointer(s))
|
|
203
|
+
C.webview_init(w.w, s)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
func (w *webview) Eval(js string) {
|
|
207
|
+
s := C.CString(js)
|
|
208
|
+
defer C.free(unsafe.Pointer(s))
|
|
209
|
+
C.webview_eval(w.w, s)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
func (w *webview) Dispatch(f func()) {
|
|
213
|
+
m.Lock()
|
|
214
|
+
for ; dispatch[index] != nil; index++ {
|
|
215
|
+
}
|
|
216
|
+
dispatch[index] = f
|
|
217
|
+
m.Unlock()
|
|
218
|
+
C.CgoWebViewDispatch(w.w, C.uintptr_t(index))
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
//export _webviewDispatchGoCallback
|
|
222
|
+
func _webviewDispatchGoCallback(index unsafe.Pointer) {
|
|
223
|
+
m.Lock()
|
|
224
|
+
f := dispatch[uintptr(index)]
|
|
225
|
+
delete(dispatch, uintptr(index))
|
|
226
|
+
m.Unlock()
|
|
227
|
+
f()
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
//export _webviewBindingGoCallback
|
|
231
|
+
func _webviewBindingGoCallback(w C.webview_t, id *C.char, req *C.char, index uintptr) {
|
|
232
|
+
m.Lock()
|
|
233
|
+
f := bindings[uintptr(index)]
|
|
234
|
+
m.Unlock()
|
|
235
|
+
jsString := func(v interface{}) string { b, _ := json.Marshal(v); return string(b) }
|
|
236
|
+
status, result := 0, ""
|
|
237
|
+
if res, err := f(C.GoString(id), C.GoString(req)); err != nil {
|
|
238
|
+
status = -1
|
|
239
|
+
result = jsString(err.Error())
|
|
240
|
+
} else if b, err := json.Marshal(res); err != nil {
|
|
241
|
+
status = -1
|
|
242
|
+
result = jsString(err.Error())
|
|
243
|
+
} else {
|
|
244
|
+
status = 0
|
|
245
|
+
result = string(b)
|
|
246
|
+
}
|
|
247
|
+
s := C.CString(result)
|
|
248
|
+
defer C.free(unsafe.Pointer(s))
|
|
249
|
+
C.webview_return(w, id, C.int(status), s)
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
func (w *webview) Bind(name string, f interface{}) error {
|
|
253
|
+
v := reflect.ValueOf(f)
|
|
254
|
+
// f must be a function
|
|
255
|
+
if v.Kind() != reflect.Func {
|
|
256
|
+
return errors.New("only functions can be bound")
|
|
257
|
+
}
|
|
258
|
+
// f must return either value and error or just error
|
|
259
|
+
if n := v.Type().NumOut(); n > 2 {
|
|
260
|
+
return errors.New("function may only return a value or a value+error")
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
binding := func(id, req string) (interface{}, error) {
|
|
264
|
+
raw := []json.RawMessage{}
|
|
265
|
+
if err := json.Unmarshal([]byte(req), &raw); err != nil {
|
|
266
|
+
return nil, err
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
isVariadic := v.Type().IsVariadic()
|
|
270
|
+
numIn := v.Type().NumIn()
|
|
271
|
+
if (isVariadic && len(raw) < numIn-1) || (!isVariadic && len(raw) != numIn) {
|
|
272
|
+
return nil, errors.New("function arguments mismatch")
|
|
273
|
+
}
|
|
274
|
+
args := []reflect.Value{}
|
|
275
|
+
for i := range raw {
|
|
276
|
+
var arg reflect.Value
|
|
277
|
+
if isVariadic && i >= numIn-1 {
|
|
278
|
+
arg = reflect.New(v.Type().In(numIn - 1).Elem())
|
|
279
|
+
} else {
|
|
280
|
+
arg = reflect.New(v.Type().In(i))
|
|
281
|
+
}
|
|
282
|
+
if err := json.Unmarshal(raw[i], arg.Interface()); err != nil {
|
|
283
|
+
return nil, err
|
|
284
|
+
}
|
|
285
|
+
args = append(args, arg.Elem())
|
|
286
|
+
}
|
|
287
|
+
errorType := reflect.TypeOf((*error)(nil)).Elem()
|
|
288
|
+
res := v.Call(args)
|
|
289
|
+
switch len(res) {
|
|
290
|
+
case 0:
|
|
291
|
+
// No results from the function, just return nil
|
|
292
|
+
return nil, nil
|
|
293
|
+
case 1:
|
|
294
|
+
// One result may be a value, or an error
|
|
295
|
+
if res[0].Type().Implements(errorType) {
|
|
296
|
+
if res[0].Interface() != nil {
|
|
297
|
+
return nil, res[0].Interface().(error)
|
|
298
|
+
}
|
|
299
|
+
return nil, nil
|
|
300
|
+
}
|
|
301
|
+
return res[0].Interface(), nil
|
|
302
|
+
case 2:
|
|
303
|
+
// Two results: first one is value, second is error
|
|
304
|
+
if !res[1].Type().Implements(errorType) {
|
|
305
|
+
return nil, errors.New("second return value must be an error")
|
|
306
|
+
}
|
|
307
|
+
if res[1].Interface() == nil {
|
|
308
|
+
return res[0].Interface(), nil
|
|
309
|
+
}
|
|
310
|
+
return res[0].Interface(), res[1].Interface().(error)
|
|
311
|
+
default:
|
|
312
|
+
return nil, errors.New("unexpected number of return values")
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
m.Lock()
|
|
317
|
+
for ; bindings[index] != nil; index++ {
|
|
318
|
+
}
|
|
319
|
+
bindings[index] = binding
|
|
320
|
+
m.Unlock()
|
|
321
|
+
cname := C.CString(name)
|
|
322
|
+
defer C.free(unsafe.Pointer(cname))
|
|
323
|
+
C.CgoWebViewBind(w.w, cname, C.uintptr_t(index))
|
|
324
|
+
return nil
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
func (w *webview) Unbind(name string) error {
|
|
328
|
+
cname := C.CString(name)
|
|
329
|
+
defer C.free(unsafe.Pointer(cname))
|
|
330
|
+
C.CgoWebViewUnbind(w.w, cname)
|
|
331
|
+
return nil
|
|
332
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
; Freedom NSIS 安装器模板(freedom build --installer 填充 @...@ 占位符后编译)。
|
|
2
|
+
; 占位符:@NAME@ 应用名 / @VERSION@ 版本 / @SRC@ 产物目录(exe + resources)
|
|
3
|
+
; @OUT@ 输出目录 / @EXE@ 可执行文件名。
|
|
4
|
+
Unicode true
|
|
5
|
+
!include "MUI2.nsh"
|
|
6
|
+
|
|
7
|
+
!define APPNAME "@NAME@"
|
|
8
|
+
!define VERSION "@VERSION@"
|
|
9
|
+
!define SRC "@SRC@"
|
|
10
|
+
!define OUT "@OUT@"
|
|
11
|
+
!define EXE "@EXE@"
|
|
12
|
+
|
|
13
|
+
Name "${APPNAME}"
|
|
14
|
+
OutFile "${OUT}\${APPNAME}-setup-${VERSION}.exe"
|
|
15
|
+
InstallDir "$PROGRAMFILES64\${APPNAME}"
|
|
16
|
+
InstallDirRegKey HKLM "Software\${APPNAME}" "InstallDir"
|
|
17
|
+
RequestExecutionLevel admin
|
|
18
|
+
|
|
19
|
+
!insertmacro MUI_PAGE_DIRECTORY
|
|
20
|
+
!insertmacro MUI_PAGE_INSTFILES
|
|
21
|
+
!insertmacro MUI_UNPAGE_CONFIRM
|
|
22
|
+
!insertmacro MUI_UNPAGE_INSTFILES
|
|
23
|
+
!insertmacro MUI_LANGUAGE "SimpChinese"
|
|
24
|
+
|
|
25
|
+
Section "Install"
|
|
26
|
+
SetOutPath "$INSTDIR"
|
|
27
|
+
File /r "${SRC}\*.*"
|
|
28
|
+
WriteUninstaller "$INSTDIR\uninstall.exe"
|
|
29
|
+
CreateShortCut "$DESKTOP\${APPNAME}.lnk" "$INSTDIR\${EXE}"
|
|
30
|
+
CreateShortCut "$SMPROGRAMS\${APPNAME}.lnk" "$INSTDIR\${EXE}"
|
|
31
|
+
WriteRegStr HKLM "Software\${APPNAME}" "InstallDir" "$INSTDIR"
|
|
32
|
+
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayName" "${APPNAME}"
|
|
33
|
+
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayVersion" "${VERSION}"
|
|
34
|
+
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "UninstallString" "$INSTDIR\uninstall.exe"
|
|
35
|
+
SectionEnd
|
|
36
|
+
|
|
37
|
+
Section "Uninstall"
|
|
38
|
+
RMDir /r "$INSTDIR"
|
|
39
|
+
Delete "$DESKTOP\${APPNAME}.lnk"
|
|
40
|
+
Delete "$SMPROGRAMS\${APPNAME}.lnk"
|
|
41
|
+
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}"
|
|
42
|
+
DeleteRegKey HKLM "Software\${APPNAME}"
|
|
43
|
+
SectionEnd
|
|
@@ -54,4 +54,18 @@ export default {
|
|
|
54
54
|
// 示例(Node 后端):
|
|
55
55
|
// backend: { command: 'node', args: ['backend/main.mjs'] }
|
|
56
56
|
// backend: undefined,
|
|
57
|
+
|
|
58
|
+
// 单实例:true 时二次启动把命令行参数转发给已运行实例后自动退出,
|
|
59
|
+
// 主实例前端收 freedom.on('app.secondInstance', ({args})=>…)(Windows 生效)。
|
|
60
|
+
// singleInstance: false,
|
|
61
|
+
|
|
62
|
+
// 自动更新(发布环:freedom keygen 生成密钥 → 公钥填这里 → 发版 freedom manifest 签 latest.json):
|
|
63
|
+
// updater: {
|
|
64
|
+
// manifestURL: 'https://your.host/latest.json',
|
|
65
|
+
// publicKey: '<freedom keygen 输出的 base64 公钥>',
|
|
66
|
+
// requireSignature: false, // 开启后产物还须通过平台代码签名复核(仅 Windows)
|
|
67
|
+
// },
|
|
68
|
+
|
|
69
|
+
// dev 流自定义启动命令(默认 `npm run dev`,freedom dev 用它拉起 vite 并热更壳窗口):
|
|
70
|
+
// dev: { command: 'npm run dev' },
|
|
57
71
|
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// Freedom 桌面壳前端 SDK 类型声明(window.freedom)
|
|
2
|
+
// 运行时由壳注入(assets/freedom.js);本文件仅类型提示,不参与打包产物。
|
|
3
|
+
// 用法:tsconfig "include": ["src", "freedom.d.ts"],直接 window.freedom.* 获得补全。
|
|
4
|
+
|
|
5
|
+
export {};
|
|
6
|
+
|
|
7
|
+
interface FreedomWindowAPI {
|
|
8
|
+
minimize(): Promise<void>;
|
|
9
|
+
maximize(): Promise<void>;
|
|
10
|
+
unmaximize(): Promise<void>;
|
|
11
|
+
toggleMaximize(): Promise<boolean>;
|
|
12
|
+
close(): Promise<void>;
|
|
13
|
+
isMaximized(): Promise<boolean>;
|
|
14
|
+
isFrameless(): Promise<boolean>;
|
|
15
|
+
show(): Promise<void>;
|
|
16
|
+
hide(): Promise<void>;
|
|
17
|
+
focus(): Promise<void>;
|
|
18
|
+
setPosition(x: number, y: number): Promise<void>;
|
|
19
|
+
setSize(w: number, h: number): Promise<void>;
|
|
20
|
+
getPosition(): Promise<{ x: number; y: number }>;
|
|
21
|
+
getSize(): Promise<{ width: number; height: number }>;
|
|
22
|
+
setAlwaysOnTop(on: boolean): Promise<void>;
|
|
23
|
+
setFullscreen(on: boolean): Promise<void>;
|
|
24
|
+
startDrag(): Promise<void>;
|
|
25
|
+
/** 多窗口:spec.url 或 spec.html 指定页面,返回 {id} */
|
|
26
|
+
create(spec: { title?: string; url?: string; html?: string; width?: number; height?: number }): Promise<{ id: string }>;
|
|
27
|
+
list(): Promise<Array<{ id: string; title?: string }>>;
|
|
28
|
+
focusWindow(id: string): Promise<void>;
|
|
29
|
+
closeWindow(id: string): Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface FreedomAPI {
|
|
33
|
+
/** 调用后端方法(任意语言后端,NDJSON/JSON-RPC over stdio),返回 Promise。 */
|
|
34
|
+
call(method: string, ...args: unknown[]): Promise<any>;
|
|
35
|
+
invoke(method: string, ...args: unknown[]): Promise<any>;
|
|
36
|
+
/** 订阅后端推送事件,返回取消订阅函数。 */
|
|
37
|
+
on(event: string, fn: (data: any) => void): () => void;
|
|
38
|
+
off(event: string, fn: (data: any) => void): void;
|
|
39
|
+
once(event: string, fn: (data: any) => void): () => void;
|
|
40
|
+
emit(event: string, data?: unknown): void;
|
|
41
|
+
|
|
42
|
+
window: FreedomWindowAPI;
|
|
43
|
+
/** 系统能力总入口(taskbar/backdrop/dialog 等,平台差异见 README 能力矩阵)。 */
|
|
44
|
+
sys: Record<string, (params?: unknown) => Promise<any>>;
|
|
45
|
+
clipboard: { read(): Promise<string>; write(text: string): Promise<void> };
|
|
46
|
+
shell: { open(url: string): Promise<void> };
|
|
47
|
+
notification: { show(opts: { title: string; body?: string }): Promise<void> };
|
|
48
|
+
shortcut: { register(combo: string, fn: () => void): Promise<() => void> };
|
|
49
|
+
autostart: { enable(): Promise<void>; disable(): Promise<void>; isEnabled(): Promise<boolean> };
|
|
50
|
+
protocol: { register(scheme: string): Promise<void>; unregister(scheme: string): Promise<void> };
|
|
51
|
+
app: { launchArgs(): Promise<string[]> };
|
|
52
|
+
path: { get(kind: string, name?: string): Promise<string> };
|
|
53
|
+
store: {
|
|
54
|
+
get(namespace: string, key: string): Promise<any>;
|
|
55
|
+
set(namespace: string, key: string, value: unknown): Promise<void>;
|
|
56
|
+
delete(namespace: string, key: string): Promise<void>;
|
|
57
|
+
keys(namespace: string): Promise<string[]>;
|
|
58
|
+
};
|
|
59
|
+
os: { info(): Promise<Record<string, any>> };
|
|
60
|
+
process: { exit(): Promise<void>; restart(): Promise<void> };
|
|
61
|
+
/** 自动更新:check 验签后缓存条目;install 仅认 check 结果,进度经 update.* 事件回推。 */
|
|
62
|
+
update: { check(): Promise<void>; install(): Promise<void> };
|
|
63
|
+
taskbar: Record<string, (params?: unknown) => Promise<any>>;
|
|
64
|
+
dialog: {
|
|
65
|
+
message(opts: { title?: string; text: string; type?: string }): Promise<any>;
|
|
66
|
+
open(opts?: Record<string, any>): Promise<string | string[] | null>;
|
|
67
|
+
save(opts?: Record<string, any>): Promise<string | null>;
|
|
68
|
+
};
|
|
69
|
+
tray: Record<string, (params?: unknown) => Promise<any>>;
|
|
70
|
+
menu: Record<string, (params?: unknown) => Promise<any>>;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
declare global {
|
|
74
|
+
interface Window {
|
|
75
|
+
freedom: FreedomAPI;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -55,4 +55,18 @@ export default {
|
|
|
55
55
|
// 示例(Node 后端):
|
|
56
56
|
// backend: { command: 'node', args: ['backend/main.mjs'] }
|
|
57
57
|
// backend: undefined,
|
|
58
|
+
|
|
59
|
+
// 单实例:true 时二次启动把命令行参数转发给已运行实例后自动退出,
|
|
60
|
+
// 主实例前端收 freedom.on('app.secondInstance', ({args})=>…)(Windows 生效)。
|
|
61
|
+
// singleInstance: false,
|
|
62
|
+
|
|
63
|
+
// 自动更新(发布环:freedom keygen 生成密钥 → 公钥填这里 → 发版 freedom manifest 签 latest.json):
|
|
64
|
+
// updater: {
|
|
65
|
+
// manifestURL: 'https://your.host/latest.json',
|
|
66
|
+
// publicKey: '<freedom keygen 输出的 base64 公钥>',
|
|
67
|
+
// requireSignature: false, // 开启后产物还须通过平台代码签名复核(仅 Windows)
|
|
68
|
+
// },
|
|
69
|
+
|
|
70
|
+
// dev 流自定义启动命令(默认 `npm run dev`,freedom dev 用它拉起 vite 并热更壳窗口):
|
|
71
|
+
// dev: { command: 'npm run dev' },
|
|
58
72
|
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// Freedom 桌面壳前端 SDK 类型声明(window.freedom)
|
|
2
|
+
// 运行时由壳注入(assets/freedom.js);本文件仅类型提示,不参与打包产物。
|
|
3
|
+
// 用法:tsconfig "include": ["src", "freedom.d.ts"],直接 window.freedom.* 获得补全。
|
|
4
|
+
|
|
5
|
+
export {};
|
|
6
|
+
|
|
7
|
+
interface FreedomWindowAPI {
|
|
8
|
+
minimize(): Promise<void>;
|
|
9
|
+
maximize(): Promise<void>;
|
|
10
|
+
unmaximize(): Promise<void>;
|
|
11
|
+
toggleMaximize(): Promise<boolean>;
|
|
12
|
+
close(): Promise<void>;
|
|
13
|
+
isMaximized(): Promise<boolean>;
|
|
14
|
+
isFrameless(): Promise<boolean>;
|
|
15
|
+
show(): Promise<void>;
|
|
16
|
+
hide(): Promise<void>;
|
|
17
|
+
focus(): Promise<void>;
|
|
18
|
+
setPosition(x: number, y: number): Promise<void>;
|
|
19
|
+
setSize(w: number, h: number): Promise<void>;
|
|
20
|
+
getPosition(): Promise<{ x: number; y: number }>;
|
|
21
|
+
getSize(): Promise<{ width: number; height: number }>;
|
|
22
|
+
setAlwaysOnTop(on: boolean): Promise<void>;
|
|
23
|
+
setFullscreen(on: boolean): Promise<void>;
|
|
24
|
+
startDrag(): Promise<void>;
|
|
25
|
+
/** 多窗口:spec.url 或 spec.html 指定页面,返回 {id} */
|
|
26
|
+
create(spec: { title?: string; url?: string; html?: string; width?: number; height?: number }): Promise<{ id: string }>;
|
|
27
|
+
list(): Promise<Array<{ id: string; title?: string }>>;
|
|
28
|
+
focusWindow(id: string): Promise<void>;
|
|
29
|
+
closeWindow(id: string): Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface FreedomAPI {
|
|
33
|
+
/** 调用后端方法(任意语言后端,NDJSON/JSON-RPC over stdio),返回 Promise。 */
|
|
34
|
+
call(method: string, ...args: unknown[]): Promise<any>;
|
|
35
|
+
invoke(method: string, ...args: unknown[]): Promise<any>;
|
|
36
|
+
/** 订阅后端推送事件,返回取消订阅函数。 */
|
|
37
|
+
on(event: string, fn: (data: any) => void): () => void;
|
|
38
|
+
off(event: string, fn: (data: any) => void): void;
|
|
39
|
+
once(event: string, fn: (data: any) => void): () => void;
|
|
40
|
+
emit(event: string, data?: unknown): void;
|
|
41
|
+
|
|
42
|
+
window: FreedomWindowAPI;
|
|
43
|
+
/** 系统能力总入口(taskbar/backdrop/dialog 等,平台差异见 README 能力矩阵)。 */
|
|
44
|
+
sys: Record<string, (params?: unknown) => Promise<any>>;
|
|
45
|
+
clipboard: { read(): Promise<string>; write(text: string): Promise<void> };
|
|
46
|
+
shell: { open(url: string): Promise<void> };
|
|
47
|
+
notification: { show(opts: { title: string; body?: string }): Promise<void> };
|
|
48
|
+
shortcut: { register(combo: string, fn: () => void): Promise<() => void> };
|
|
49
|
+
autostart: { enable(): Promise<void>; disable(): Promise<void>; isEnabled(): Promise<boolean> };
|
|
50
|
+
protocol: { register(scheme: string): Promise<void>; unregister(scheme: string): Promise<void> };
|
|
51
|
+
app: { launchArgs(): Promise<string[]> };
|
|
52
|
+
path: { get(kind: string, name?: string): Promise<string> };
|
|
53
|
+
store: {
|
|
54
|
+
get(namespace: string, key: string): Promise<any>;
|
|
55
|
+
set(namespace: string, key: string, value: unknown): Promise<void>;
|
|
56
|
+
delete(namespace: string, key: string): Promise<void>;
|
|
57
|
+
keys(namespace: string): Promise<string[]>;
|
|
58
|
+
};
|
|
59
|
+
os: { info(): Promise<Record<string, any>> };
|
|
60
|
+
process: { exit(): Promise<void>; restart(): Promise<void> };
|
|
61
|
+
/** 自动更新:check 验签后缓存条目;install 仅认 check 结果,进度经 update.* 事件回推。 */
|
|
62
|
+
update: { check(): Promise<void>; install(): Promise<void> };
|
|
63
|
+
taskbar: Record<string, (params?: unknown) => Promise<any>>;
|
|
64
|
+
dialog: {
|
|
65
|
+
message(opts: { title?: string; text: string; type?: string }): Promise<any>;
|
|
66
|
+
open(opts?: Record<string, any>): Promise<string | string[] | null>;
|
|
67
|
+
save(opts?: Record<string, any>): Promise<string | null>;
|
|
68
|
+
};
|
|
69
|
+
tray: Record<string, (params?: unknown) => Promise<any>>;
|
|
70
|
+
menu: Record<string, (params?: unknown) => Promise<any>>;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
declare global {
|
|
74
|
+
interface Window {
|
|
75
|
+
freedom: FreedomAPI;
|
|
76
|
+
}
|
|
77
|
+
}
|