@gemigo/app-sdk 0.2.5 → 0.2.7
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/dist/gemigo-app-sdk.es.js +649 -86
- package/dist/gemigo-app-sdk.umd.js +1 -1
- package/dist/types/auth.d.ts +35 -0
- package/dist/types/cloud.d.ts +288 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/web/auth.d.ts +3 -0
- package/dist/web/cloud.d.ts +2 -0
- package/package.json +1 -1
|
@@ -1,82 +1,82 @@
|
|
|
1
1
|
import { i as tryGetHost, n as createRPCProxy, t as callHost } from "./connection-DwOg1Kh5.js";
|
|
2
2
|
function createEventBus() {
|
|
3
|
-
let
|
|
3
|
+
let f = /* @__PURE__ */ new Map();
|
|
4
4
|
return {
|
|
5
|
-
on(
|
|
6
|
-
return
|
|
5
|
+
on(B, V) {
|
|
6
|
+
return f.has(B) || f.set(B, /* @__PURE__ */ new Set()), f.get(B).add(V), () => f.get(B)?.delete(V);
|
|
7
7
|
},
|
|
8
|
-
emit(
|
|
9
|
-
|
|
8
|
+
emit(B, ...V) {
|
|
9
|
+
f.get(B)?.forEach((f) => f(...V));
|
|
10
10
|
},
|
|
11
|
-
off(
|
|
12
|
-
|
|
11
|
+
off(B) {
|
|
12
|
+
B ? f.delete(B) : f.clear();
|
|
13
13
|
}
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
16
|
const sdkEventBus = createEventBus();
|
|
17
|
-
function createUnifiedAPI(
|
|
18
|
-
let
|
|
19
|
-
if (
|
|
20
|
-
let
|
|
21
|
-
mapping:
|
|
22
|
-
fallbacks:
|
|
17
|
+
function createUnifiedAPI(V) {
|
|
18
|
+
let H = tryGetHost, W = {}, G = {};
|
|
19
|
+
if (V.rpc) {
|
|
20
|
+
let f = createRPCProxy(V.rpc.methods, {
|
|
21
|
+
mapping: V.rpc.mapping,
|
|
22
|
+
fallbacks: V.rpc.fallbacks
|
|
23
23
|
});
|
|
24
|
-
Object.assign(
|
|
24
|
+
Object.assign(W, f);
|
|
25
25
|
}
|
|
26
|
-
if (
|
|
27
|
-
let
|
|
28
|
-
|
|
29
|
-
sdkEventBus.emit(
|
|
26
|
+
if (V.events) if (Array.isArray(V.events)) for (let f of V.events) {
|
|
27
|
+
let B = f;
|
|
28
|
+
W[f] = (f) => (H?.(), sdkEventBus.on(B, f)), G[f] = (...f) => {
|
|
29
|
+
sdkEventBus.emit(B, ...f);
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
|
-
else for (let [
|
|
33
|
-
if (!
|
|
34
|
-
let
|
|
35
|
-
|
|
36
|
-
sdkEventBus.emit(
|
|
32
|
+
else for (let [f, B] of Object.entries(V.events)) {
|
|
33
|
+
if (!B) continue;
|
|
34
|
+
let V = B, K = typeof V == "string" ? V : V.event, q = typeof V == "object" && "childMethod" in V && V.childMethod ? V.childMethod : f;
|
|
35
|
+
W[f] = (f) => (H?.(), sdkEventBus.on(K, f)), G[q] = (...f) => {
|
|
36
|
+
sdkEventBus.emit(K, ...f);
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
39
|
return {
|
|
40
|
-
api:
|
|
41
|
-
childMethods:
|
|
40
|
+
api: W,
|
|
41
|
+
childMethods: G
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
|
-
function createRPCAction(
|
|
45
|
-
return async (...
|
|
44
|
+
function createRPCAction(f, B) {
|
|
45
|
+
return async (...H) => {
|
|
46
46
|
try {
|
|
47
|
-
let
|
|
48
|
-
return
|
|
47
|
+
let U = await callHost(f, B.transform ? B.transform(...H) : H);
|
|
48
|
+
return B.onSuccess ? B.onSuccess(U) : U;
|
|
49
49
|
} catch {
|
|
50
|
-
return
|
|
50
|
+
return B.fallback(...H);
|
|
51
51
|
}
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
|
-
function createSDK(
|
|
55
|
-
let
|
|
56
|
-
if (
|
|
57
|
-
let { api:
|
|
58
|
-
|
|
54
|
+
function createSDK(f) {
|
|
55
|
+
let B = f.statics ? { ...f.statics } : {}, V = {};
|
|
56
|
+
if (f.modules) for (let [H, U] of Object.entries(f.modules)) {
|
|
57
|
+
let { api: f, childMethods: G } = createUnifiedAPI(U);
|
|
58
|
+
B[H] = f, Object.assign(V, G);
|
|
59
59
|
}
|
|
60
|
-
if (
|
|
61
|
-
let
|
|
62
|
-
|
|
60
|
+
if (f.actions) for (let [V, H] of Object.entries(f.actions)) {
|
|
61
|
+
let f = H;
|
|
62
|
+
B[V] = createRPCAction(f.method, f);
|
|
63
63
|
}
|
|
64
|
-
if (
|
|
65
|
-
get:
|
|
64
|
+
if (f.getters) for (let [V, H] of Object.entries(f.getters)) Object.defineProperty(B, V, {
|
|
65
|
+
get: H,
|
|
66
66
|
enumerable: !0,
|
|
67
67
|
configurable: !0
|
|
68
68
|
});
|
|
69
69
|
return {
|
|
70
|
-
sdk:
|
|
71
|
-
childMethods:
|
|
70
|
+
sdk: B,
|
|
71
|
+
childMethods: V
|
|
72
72
|
};
|
|
73
73
|
}
|
|
74
|
-
async function bootstrapSDK(
|
|
75
|
-
let { initConnection:
|
|
76
|
-
|
|
77
|
-
let
|
|
78
|
-
if (
|
|
79
|
-
return await
|
|
74
|
+
async function bootstrapSDK(B, V = {}) {
|
|
75
|
+
let { initConnection: H } = await import("./connection-C-IGR2wz.js");
|
|
76
|
+
H(B, V);
|
|
77
|
+
let U = await tryGetHost();
|
|
78
|
+
if (U && typeof U.getProtocolInfo == "function") try {
|
|
79
|
+
return await U.getProtocolInfo();
|
|
80
80
|
} catch {
|
|
81
81
|
return null;
|
|
82
82
|
}
|
|
@@ -84,31 +84,31 @@ async function bootstrapSDK(x, S = {}) {
|
|
|
84
84
|
}
|
|
85
85
|
var localStoragePrefix = () => `gemigo:${typeof window > "u" ? "unknown" : window.location.origin.replace(/[:/]/g, "_")}:`;
|
|
86
86
|
const fallbackStorage = {
|
|
87
|
-
get: async (
|
|
87
|
+
get: async (f) => {
|
|
88
88
|
if (typeof window > "u" || !window.localStorage) return null;
|
|
89
|
-
let
|
|
90
|
-
if (!
|
|
89
|
+
let B = window.localStorage.getItem(`${localStoragePrefix()}${f}`);
|
|
90
|
+
if (!B) return null;
|
|
91
91
|
try {
|
|
92
|
-
return JSON.parse(
|
|
92
|
+
return JSON.parse(B);
|
|
93
93
|
} catch {
|
|
94
94
|
return null;
|
|
95
95
|
}
|
|
96
96
|
},
|
|
97
|
-
set: async (
|
|
98
|
-
typeof window > "u" || !window.localStorage || window.localStorage.setItem(`${localStoragePrefix()}${
|
|
97
|
+
set: async (f, B) => {
|
|
98
|
+
typeof window > "u" || !window.localStorage || window.localStorage.setItem(`${localStoragePrefix()}${f}`, JSON.stringify(B));
|
|
99
99
|
},
|
|
100
|
-
delete: async (
|
|
101
|
-
typeof window > "u" || !window.localStorage || window.localStorage.removeItem(`${localStoragePrefix()}${
|
|
100
|
+
delete: async (f) => {
|
|
101
|
+
typeof window > "u" || !window.localStorage || window.localStorage.removeItem(`${localStoragePrefix()}${f}`);
|
|
102
102
|
},
|
|
103
103
|
clear: async () => {
|
|
104
104
|
if (typeof window > "u" || !window.localStorage) return;
|
|
105
|
-
let
|
|
106
|
-
for (let
|
|
107
|
-
let
|
|
108
|
-
|
|
105
|
+
let f = localStoragePrefix();
|
|
106
|
+
for (let B = window.localStorage.length - 1; B >= 0; --B) {
|
|
107
|
+
let V = window.localStorage.key(B);
|
|
108
|
+
V && V.startsWith(f) && window.localStorage.removeItem(V);
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
|
-
}, fallbackNotify = async (
|
|
111
|
+
}, fallbackNotify = async (f) => {
|
|
112
112
|
if (typeof window > "u" || typeof Notification > "u") return {
|
|
113
113
|
success: !1,
|
|
114
114
|
reason: "not_supported"
|
|
@@ -118,9 +118,9 @@ const fallbackStorage = {
|
|
|
118
118
|
reason: "permission_not_granted"
|
|
119
119
|
};
|
|
120
120
|
try {
|
|
121
|
-
return new Notification(
|
|
122
|
-
body:
|
|
123
|
-
icon:
|
|
121
|
+
return new Notification(f.title, {
|
|
122
|
+
body: f.message,
|
|
123
|
+
icon: f.icon
|
|
124
124
|
}), { success: !0 };
|
|
125
125
|
} catch {
|
|
126
126
|
return {
|
|
@@ -128,25 +128,586 @@ const fallbackStorage = {
|
|
|
128
128
|
reason: "failed_to_notify"
|
|
129
129
|
};
|
|
130
130
|
}
|
|
131
|
-
}, fallbackNetwork = { request: async (
|
|
132
|
-
let { method:
|
|
133
|
-
method:
|
|
134
|
-
headers:
|
|
135
|
-
body:
|
|
136
|
-
}),
|
|
137
|
-
|
|
138
|
-
let
|
|
131
|
+
}, fallbackNetwork = { request: async (f, B) => {
|
|
132
|
+
let { method: V = "GET", headers: H, body: U, responseType: W } = B ?? {}, G = await fetch(f, {
|
|
133
|
+
method: V,
|
|
134
|
+
headers: H,
|
|
135
|
+
body: U ? typeof U == "string" ? U : JSON.stringify(U) : void 0
|
|
136
|
+
}), K = {};
|
|
137
|
+
G.headers.forEach((f, B) => K[B] = f);
|
|
138
|
+
let q = W === "text" ? await G.text() : W === "arraybuffer" ? await G.arrayBuffer() : await G.json();
|
|
139
139
|
return {
|
|
140
|
-
status:
|
|
141
|
-
data:
|
|
142
|
-
headers:
|
|
140
|
+
status: G.status,
|
|
141
|
+
data: q,
|
|
142
|
+
headers: K
|
|
143
143
|
};
|
|
144
144
|
} };
|
|
145
|
-
var SDKError = class
|
|
146
|
-
constructor(
|
|
147
|
-
super(
|
|
145
|
+
var SDKError = class f extends Error {
|
|
146
|
+
constructor(B, V) {
|
|
147
|
+
super(V), this.code = B, this.name = "SDKError", Object.setPrototypeOf(this, f.prototype);
|
|
148
148
|
}
|
|
149
|
-
},
|
|
149
|
+
}, currentToken = null, currentApiBaseUrl = null;
|
|
150
|
+
function base64UrlEncode(f) {
|
|
151
|
+
let B = "";
|
|
152
|
+
for (let V of f) B += String.fromCharCode(V);
|
|
153
|
+
let V = globalThis.btoa;
|
|
154
|
+
if (!V) throw Error("base64 encoder not available");
|
|
155
|
+
return V(B).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
156
|
+
}
|
|
157
|
+
function randomString(f = 32) {
|
|
158
|
+
let B = new Uint8Array(f);
|
|
159
|
+
return crypto.getRandomValues(B), base64UrlEncode(B);
|
|
160
|
+
}
|
|
161
|
+
async function sha256Base64Url(f) {
|
|
162
|
+
let B = new TextEncoder().encode(f), V = await crypto.subtle.digest("SHA-256", B);
|
|
163
|
+
return base64UrlEncode(new Uint8Array(V));
|
|
164
|
+
}
|
|
165
|
+
function deriveDefaultAppId() {
|
|
166
|
+
if (typeof window > "u") return "unknown";
|
|
167
|
+
let f = window.location.hostname.toLowerCase();
|
|
168
|
+
return f.endsWith(".gemigo.app") ? f.replace(/\.gemigo\.app$/, "") : f;
|
|
169
|
+
}
|
|
170
|
+
function normalizeScopes(f) {
|
|
171
|
+
let B = (f ?? ["identity:basic"]).map((f) => String(f).trim()).filter(Boolean);
|
|
172
|
+
return B.length > 0 ? B : ["identity:basic"];
|
|
173
|
+
}
|
|
174
|
+
function buildBrokerUrl(f) {
|
|
175
|
+
let B = new URL("/sdk/broker", f.platformOrigin);
|
|
176
|
+
return B.searchParams.set("app_id", f.appId), B.searchParams.set("scope", f.scopes.join(" ")), B.searchParams.set("state", f.state), B.searchParams.set("code_challenge", f.codeChallenge), B.searchParams.set("code_challenge_method", "S256"), B.searchParams.set("origin", f.openerOrigin), B.toString();
|
|
177
|
+
}
|
|
178
|
+
async function exchangeCode(f, B, V) {
|
|
179
|
+
let H = await fetch(`${f.replace(/\/+$/, "")}/sdk/token`, {
|
|
180
|
+
method: "POST",
|
|
181
|
+
headers: { "Content-Type": "application/json" },
|
|
182
|
+
body: JSON.stringify({
|
|
183
|
+
code: B,
|
|
184
|
+
codeVerifier: V
|
|
185
|
+
})
|
|
186
|
+
});
|
|
187
|
+
if (!H.ok) {
|
|
188
|
+
let f = await H.json().catch(() => ({}));
|
|
189
|
+
throw Error(f.error || "Failed to exchange code");
|
|
190
|
+
}
|
|
191
|
+
return await H.json();
|
|
192
|
+
}
|
|
193
|
+
function getWebApiBaseUrl() {
|
|
194
|
+
return currentApiBaseUrl || "https://gemigo.io/api/v1";
|
|
195
|
+
}
|
|
196
|
+
const webAuth = {
|
|
197
|
+
async login(f = {}) {
|
|
198
|
+
if (typeof window > "u") throw new SDKError("NOT_SUPPORTED", "auth.login is only supported in browser environments.");
|
|
199
|
+
let B = f.platformOrigin?.trim() || "https://gemigo.io", V = f.apiBaseUrl?.trim() || `${B.replace(/\/+$/, "")}/api/v1`, H = f.appId?.trim() || deriveDefaultAppId(), U = normalizeScopes(f.scopes), W = typeof f.timeoutMs == "number" ? f.timeoutMs : 120 * 1e3, G = randomString(16), K = randomString(48), q = window.location.origin, J = Math.max(0, (window.screen.width - 520) / 2), Y = Math.max(0, (window.screen.height - 720) / 2), X = window.open("about:blank", "gemigo_sdk_auth", `popup=yes,width=520,height=720,left=${J},top=${Y}`);
|
|
200
|
+
if (!X) throw Error("Popup blocked. Please allow popups and retry.");
|
|
201
|
+
try {
|
|
202
|
+
X.document.title = "GemiGo Auth", X.document.body.innerHTML = "<div style=\"font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;padding:24px;\">Loading…</div>";
|
|
203
|
+
} catch {}
|
|
204
|
+
let Z = buildBrokerUrl({
|
|
205
|
+
platformOrigin: B,
|
|
206
|
+
appId: H,
|
|
207
|
+
scopes: U,
|
|
208
|
+
state: G,
|
|
209
|
+
codeChallenge: await sha256Base64Url(K),
|
|
210
|
+
openerOrigin: q
|
|
211
|
+
});
|
|
212
|
+
try {
|
|
213
|
+
X.location.href = Z;
|
|
214
|
+
} catch {
|
|
215
|
+
if (!window.open(Z, "gemigo_sdk_auth")) throw Error("Popup navigation failed. Please allow popups and retry.");
|
|
216
|
+
}
|
|
217
|
+
let Q = await exchangeCode(V, (await new Promise((f, V) => {
|
|
218
|
+
let H = window.setTimeout(() => {
|
|
219
|
+
U(), V(/* @__PURE__ */ Error("Login timeout."));
|
|
220
|
+
}, W), U = () => {
|
|
221
|
+
window.clearTimeout(H), window.removeEventListener("message", K);
|
|
222
|
+
try {
|
|
223
|
+
X.close();
|
|
224
|
+
} catch {}
|
|
225
|
+
}, K = (H) => {
|
|
226
|
+
if (H.origin !== new URL(B).origin) return;
|
|
227
|
+
let W = H.data;
|
|
228
|
+
if (!(!W || typeof W != "object") && W.state === G) {
|
|
229
|
+
if (W.type === "gemigo:sdk-auth-error") {
|
|
230
|
+
U(), V(Error(String(W.error || "auth_error")));
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
W.type === "gemigo:sdk-auth-code" && typeof W.code == "string" && (U(), f({ code: W.code }));
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
window.addEventListener("message", K);
|
|
237
|
+
})).code, K);
|
|
238
|
+
return currentToken = Q, currentApiBaseUrl = V, Q;
|
|
239
|
+
},
|
|
240
|
+
getAccessToken() {
|
|
241
|
+
return currentToken?.accessToken ?? null;
|
|
242
|
+
},
|
|
243
|
+
logout() {
|
|
244
|
+
currentToken = null;
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
function requireAccessToken() {
|
|
248
|
+
let f = webAuth.getAccessToken();
|
|
249
|
+
if (!f) throw new SDKError("PERMISSION_DENIED", "Login required. Call gemigo.auth.login() first.");
|
|
250
|
+
return f;
|
|
251
|
+
}
|
|
252
|
+
async function fetchJson(f, B = {}) {
|
|
253
|
+
let V = requireAccessToken(), H = getWebApiBaseUrl().replace(/\/+$/, ""), U = await fetch(`${H}${f}`, {
|
|
254
|
+
...B,
|
|
255
|
+
headers: {
|
|
256
|
+
...B.headers ?? {},
|
|
257
|
+
Authorization: `Bearer ${V}`
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
if (!U.ok) {
|
|
261
|
+
let f = (await U.json().catch(() => ({}))).error || `Request failed: ${U.status}`;
|
|
262
|
+
throw U.status === 401 || U.status === 403 ? new SDKError("PERMISSION_DENIED", f) : new SDKError("INTERNAL_ERROR", f);
|
|
263
|
+
}
|
|
264
|
+
return await U.json();
|
|
265
|
+
}
|
|
266
|
+
var WebCloudKv = class {
|
|
267
|
+
async get(f) {
|
|
268
|
+
return fetchJson(`/cloud/kv/get?key=${encodeURIComponent(f)}`);
|
|
269
|
+
}
|
|
270
|
+
async set(f, B, V) {
|
|
271
|
+
return fetchJson("/cloud/kv/set", {
|
|
272
|
+
method: "POST",
|
|
273
|
+
headers: { "Content-Type": "application/json" },
|
|
274
|
+
body: JSON.stringify({
|
|
275
|
+
key: f,
|
|
276
|
+
value: B,
|
|
277
|
+
ifMatch: V?.ifMatch
|
|
278
|
+
})
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
async delete(f, B) {
|
|
282
|
+
await fetchJson("/cloud/kv/delete", {
|
|
283
|
+
method: "POST",
|
|
284
|
+
headers: { "Content-Type": "application/json" },
|
|
285
|
+
body: JSON.stringify({
|
|
286
|
+
key: f,
|
|
287
|
+
ifMatch: B?.ifMatch
|
|
288
|
+
})
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
async list(f) {
|
|
292
|
+
let B = new URLSearchParams();
|
|
293
|
+
f?.prefix && B.set("prefix", f.prefix), typeof f?.limit == "number" && B.set("limit", String(f.limit)), f?.cursor && B.set("cursor", f.cursor);
|
|
294
|
+
let V = B.toString();
|
|
295
|
+
return fetchJson(`/cloud/kv/list${V ? `?${V}` : ""}`);
|
|
296
|
+
}
|
|
297
|
+
}, WebCloudDbQueryBuilder = class f {
|
|
298
|
+
constructor(f, B) {
|
|
299
|
+
this.collectionName = f, this.state = {
|
|
300
|
+
where: B?.where ?? [],
|
|
301
|
+
orderBy: B?.orderBy ?? {
|
|
302
|
+
field: "createdAt",
|
|
303
|
+
direction: "desc"
|
|
304
|
+
},
|
|
305
|
+
limit: B?.limit ?? 20,
|
|
306
|
+
cursor: B?.cursor ?? null
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
where(B, V, H) {
|
|
310
|
+
return new f(this.collectionName, {
|
|
311
|
+
...this.state,
|
|
312
|
+
where: [...this.state.where, {
|
|
313
|
+
field: B,
|
|
314
|
+
op: V,
|
|
315
|
+
value: H
|
|
316
|
+
}]
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
orderBy(B, V = "desc") {
|
|
320
|
+
return new f(this.collectionName, {
|
|
321
|
+
...this.state,
|
|
322
|
+
orderBy: {
|
|
323
|
+
field: B,
|
|
324
|
+
direction: V
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
limit(B) {
|
|
329
|
+
return new f(this.collectionName, {
|
|
330
|
+
...this.state,
|
|
331
|
+
limit: B
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
startAfter(B) {
|
|
335
|
+
return new f(this.collectionName, {
|
|
336
|
+
...this.state,
|
|
337
|
+
cursor: B
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
async get() {
|
|
341
|
+
return fetchJson(`/cloud/db/collections/${encodeURIComponent(this.collectionName)}/query`, {
|
|
342
|
+
method: "POST",
|
|
343
|
+
headers: { "Content-Type": "application/json" },
|
|
344
|
+
body: JSON.stringify({
|
|
345
|
+
where: this.state.where,
|
|
346
|
+
orderBy: this.state.orderBy,
|
|
347
|
+
limit: this.state.limit,
|
|
348
|
+
cursor: this.state.cursor
|
|
349
|
+
})
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
}, WebCloudDbCollection = class {
|
|
353
|
+
constructor(f) {
|
|
354
|
+
this.name = f;
|
|
355
|
+
}
|
|
356
|
+
async add(f, B) {
|
|
357
|
+
return fetchJson(`/cloud/db/collections/${encodeURIComponent(this.name)}/docs`, {
|
|
358
|
+
method: "POST",
|
|
359
|
+
headers: { "Content-Type": "application/json" },
|
|
360
|
+
body: JSON.stringify({
|
|
361
|
+
id: B?.id,
|
|
362
|
+
visibility: B?.visibility,
|
|
363
|
+
refType: B?.refType,
|
|
364
|
+
refId: B?.refId,
|
|
365
|
+
data: f
|
|
366
|
+
})
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
doc(f) {
|
|
370
|
+
let B = this.name;
|
|
371
|
+
return {
|
|
372
|
+
get: async () => fetchJson(`/cloud/db/collections/${encodeURIComponent(B)}/docs/${encodeURIComponent(f)}`),
|
|
373
|
+
set: async (V, H) => fetchJson(`/cloud/db/collections/${encodeURIComponent(B)}/docs/${encodeURIComponent(f)}`, {
|
|
374
|
+
method: "PUT",
|
|
375
|
+
headers: { "Content-Type": "application/json" },
|
|
376
|
+
body: JSON.stringify({
|
|
377
|
+
data: V,
|
|
378
|
+
ifMatch: H?.ifMatch,
|
|
379
|
+
visibility: H?.visibility,
|
|
380
|
+
refType: H?.refType,
|
|
381
|
+
refId: H?.refId
|
|
382
|
+
})
|
|
383
|
+
}),
|
|
384
|
+
update: async (V, H) => fetchJson(`/cloud/db/collections/${encodeURIComponent(B)}/docs/${encodeURIComponent(f)}`, {
|
|
385
|
+
method: "PATCH",
|
|
386
|
+
headers: { "Content-Type": "application/json" },
|
|
387
|
+
body: JSON.stringify({
|
|
388
|
+
patch: V,
|
|
389
|
+
ifMatch: H?.ifMatch
|
|
390
|
+
})
|
|
391
|
+
}),
|
|
392
|
+
delete: async () => fetchJson(`/cloud/db/collections/${encodeURIComponent(B)}/docs/${encodeURIComponent(f)}`, { method: "DELETE" }).then(() => void 0)
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
query() {
|
|
396
|
+
return new WebCloudDbQueryBuilder(this.name);
|
|
397
|
+
}
|
|
398
|
+
};
|
|
399
|
+
function toWxDoc(f) {
|
|
400
|
+
return {
|
|
401
|
+
...f.data && typeof f.data == "object" && !Array.isArray(f.data) ? f.data : {},
|
|
402
|
+
_id: f.id,
|
|
403
|
+
_openid: f.ownerId
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
function createWxCommand() {
|
|
407
|
+
return {
|
|
408
|
+
eq: (f) => ({
|
|
409
|
+
__gemigoWxCmd: "eq",
|
|
410
|
+
value: f
|
|
411
|
+
}),
|
|
412
|
+
neq: (f) => ({
|
|
413
|
+
__gemigoWxCmd: "neq",
|
|
414
|
+
value: f
|
|
415
|
+
}),
|
|
416
|
+
gt: (f) => ({
|
|
417
|
+
__gemigoWxCmd: "gt",
|
|
418
|
+
value: f
|
|
419
|
+
}),
|
|
420
|
+
gte: (f) => ({
|
|
421
|
+
__gemigoWxCmd: "gte",
|
|
422
|
+
value: f
|
|
423
|
+
}),
|
|
424
|
+
lt: (f) => ({
|
|
425
|
+
__gemigoWxCmd: "lt",
|
|
426
|
+
value: f
|
|
427
|
+
}),
|
|
428
|
+
lte: (f) => ({
|
|
429
|
+
__gemigoWxCmd: "lte",
|
|
430
|
+
value: f
|
|
431
|
+
}),
|
|
432
|
+
in: (f) => ({
|
|
433
|
+
__gemigoWxCmd: "in",
|
|
434
|
+
value: Array.isArray(f) ? f : []
|
|
435
|
+
}),
|
|
436
|
+
nin: (f) => ({
|
|
437
|
+
__gemigoWxCmd: "nin",
|
|
438
|
+
value: Array.isArray(f) ? f : []
|
|
439
|
+
}),
|
|
440
|
+
inc: (f) => ({
|
|
441
|
+
__gemigoWxCmd: "inc",
|
|
442
|
+
value: f
|
|
443
|
+
}),
|
|
444
|
+
set: (f) => ({
|
|
445
|
+
__gemigoWxCmd: "set",
|
|
446
|
+
value: f
|
|
447
|
+
}),
|
|
448
|
+
remove: () => ({ __gemigoWxCmd: "remove" })
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
function createWxServerDate(f) {
|
|
452
|
+
let B = typeof f?.offset == "number" && Number.isFinite(f.offset) ? f.offset : void 0;
|
|
453
|
+
return B === void 0 ? { __gemigoWxType: "serverDate" } : {
|
|
454
|
+
__gemigoWxType: "serverDate",
|
|
455
|
+
offset: B
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
function normalizeWxDirection(f) {
|
|
459
|
+
return f === "asc" ? "asc" : "desc";
|
|
460
|
+
}
|
|
461
|
+
async function wxQueryPage(f, B, V, H) {
|
|
462
|
+
return fetchJson(`/cloud/db/collections/${encodeURIComponent(f)}/query`, {
|
|
463
|
+
method: "POST",
|
|
464
|
+
headers: { "Content-Type": "application/json" },
|
|
465
|
+
body: JSON.stringify({
|
|
466
|
+
where: B.where,
|
|
467
|
+
orderBy: B.orderBy,
|
|
468
|
+
limit: H,
|
|
469
|
+
cursor: V
|
|
470
|
+
})
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
function createWxQuery(f, B, V) {
|
|
474
|
+
let H = {
|
|
475
|
+
where: V?.where ?? {},
|
|
476
|
+
orderBy: V?.orderBy ?? {
|
|
477
|
+
field: "createdAt",
|
|
478
|
+
direction: "desc"
|
|
479
|
+
},
|
|
480
|
+
limit: V?.limit ?? 20,
|
|
481
|
+
skip: V?.skip ?? 0,
|
|
482
|
+
cursor: V?.cursor ?? null
|
|
483
|
+
};
|
|
484
|
+
return {
|
|
485
|
+
where(V) {
|
|
486
|
+
return createWxQuery(f, B, {
|
|
487
|
+
...H,
|
|
488
|
+
where: {
|
|
489
|
+
...H.where,
|
|
490
|
+
...V ?? {}
|
|
491
|
+
}
|
|
492
|
+
});
|
|
493
|
+
},
|
|
494
|
+
orderBy(V, U) {
|
|
495
|
+
return createWxQuery(f, B, {
|
|
496
|
+
...H,
|
|
497
|
+
orderBy: {
|
|
498
|
+
field: String(V),
|
|
499
|
+
direction: normalizeWxDirection(U)
|
|
500
|
+
}
|
|
501
|
+
});
|
|
502
|
+
},
|
|
503
|
+
limit(V) {
|
|
504
|
+
return createWxQuery(f, B, {
|
|
505
|
+
...H,
|
|
506
|
+
limit: Math.max(1, Math.floor(Number(V) || 0))
|
|
507
|
+
});
|
|
508
|
+
},
|
|
509
|
+
skip(V) {
|
|
510
|
+
return createWxQuery(f, B, {
|
|
511
|
+
...H,
|
|
512
|
+
skip: Math.max(0, Math.floor(Number(V) || 0))
|
|
513
|
+
});
|
|
514
|
+
},
|
|
515
|
+
startAfter(V) {
|
|
516
|
+
let U = String(V ?? "").trim();
|
|
517
|
+
if (!U) throw new SDKError("INTERNAL_ERROR", "startAfter(cursor) requires a non-empty cursor");
|
|
518
|
+
return createWxQuery(f, B, {
|
|
519
|
+
...H,
|
|
520
|
+
cursor: U
|
|
521
|
+
});
|
|
522
|
+
},
|
|
523
|
+
async count() {
|
|
524
|
+
return fetchJson(`/cloud/db/collections/${encodeURIComponent(f)}/count`, {
|
|
525
|
+
method: "POST",
|
|
526
|
+
headers: { "Content-Type": "application/json" },
|
|
527
|
+
body: JSON.stringify({ where: H.where })
|
|
528
|
+
});
|
|
529
|
+
},
|
|
530
|
+
async update(B) {
|
|
531
|
+
let V = B?.data;
|
|
532
|
+
if (!V || typeof V != "object" || Array.isArray(V)) throw new SDKError("INTERNAL_ERROR", "update({data}) must be an object");
|
|
533
|
+
if ("_openid" in V) throw new SDKError("PERMISSION_DENIED", "Cannot write system field _openid");
|
|
534
|
+
return fetchJson(`/cloud/db/collections/${encodeURIComponent(f)}/update`, {
|
|
535
|
+
method: "POST",
|
|
536
|
+
headers: { "Content-Type": "application/json" },
|
|
537
|
+
body: JSON.stringify({
|
|
538
|
+
where: H.where,
|
|
539
|
+
data: V
|
|
540
|
+
})
|
|
541
|
+
});
|
|
542
|
+
},
|
|
543
|
+
async remove() {
|
|
544
|
+
return fetchJson(`/cloud/db/collections/${encodeURIComponent(f)}/remove`, {
|
|
545
|
+
method: "POST",
|
|
546
|
+
headers: { "Content-Type": "application/json" },
|
|
547
|
+
body: JSON.stringify({ where: H.where })
|
|
548
|
+
});
|
|
549
|
+
},
|
|
550
|
+
async get() {
|
|
551
|
+
let B = Math.min(H.limit, 100), V = H.skip;
|
|
552
|
+
if (V > 1e3) throw new SDKError("NOT_SUPPORTED", "skip(n) is capped at 1000; use cursor pagination instead.");
|
|
553
|
+
let U = H.cursor ?? null, W = V, G = B, K = [], q = 0;
|
|
554
|
+
for (; (W > 0 || G > 0) && q < 30;) {
|
|
555
|
+
let B = await wxQueryPage(f, H, U, Math.min(100, W > 0 ? W : G));
|
|
556
|
+
if (q += 1, B.items.length === 0) break;
|
|
557
|
+
if (W > 0) {
|
|
558
|
+
let f = Math.min(W, B.items.length);
|
|
559
|
+
W -= f;
|
|
560
|
+
let V = B.items.slice(f);
|
|
561
|
+
if (W === 0 && G > 0 && V.length > 0) {
|
|
562
|
+
let f = Math.min(G, V.length);
|
|
563
|
+
K.push(...V.slice(0, f).map(toWxDoc)), G -= f;
|
|
564
|
+
}
|
|
565
|
+
} else K.push(...B.items.slice(0, G).map(toWxDoc)), G = Math.max(0, G - B.items.length);
|
|
566
|
+
if (U = B.nextCursor, !U) break;
|
|
567
|
+
}
|
|
568
|
+
if (q >= 30) throw new SDKError("NOT_SUPPORTED", "skip/limit query requires too many requests; narrow your query.");
|
|
569
|
+
return {
|
|
570
|
+
data: K,
|
|
571
|
+
_meta: { nextCursor: U }
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
function createWxDatabase() {
|
|
577
|
+
let f = createWxCommand();
|
|
578
|
+
return {
|
|
579
|
+
command: f,
|
|
580
|
+
serverDate: (f) => createWxServerDate(f),
|
|
581
|
+
collection(B) {
|
|
582
|
+
let V = String(B).trim();
|
|
583
|
+
if (!V) throw new SDKError("INTERNAL_ERROR", "collection name is required");
|
|
584
|
+
let H = createWxQuery(V, f);
|
|
585
|
+
return {
|
|
586
|
+
...H,
|
|
587
|
+
add: async (f) => {
|
|
588
|
+
let B = f?.data;
|
|
589
|
+
if (B && typeof B == "object" && !Array.isArray(B) && "_openid" in B) throw new SDKError("PERMISSION_DENIED", "Cannot write system field _openid");
|
|
590
|
+
let H = B && typeof B == "object" && !Array.isArray(B) ? B._id : void 0, U = B && typeof B == "object" && !Array.isArray(B) ? { ...B } : B;
|
|
591
|
+
return U && typeof U == "object" && !Array.isArray(U) && delete U._id, { _id: (await webCloud.db.collection(V).add(U, { id: H ? String(H) : void 0 })).id };
|
|
592
|
+
},
|
|
593
|
+
doc: (f) => {
|
|
594
|
+
let B = webCloud.db.collection(V).doc(String(f));
|
|
595
|
+
return {
|
|
596
|
+
get: async () => ({ data: toWxDoc(await B.get()) }),
|
|
597
|
+
set: async (f) => {
|
|
598
|
+
let V = f?.data;
|
|
599
|
+
if (V && typeof V == "object" && !Array.isArray(V) && "_openid" in V) throw new SDKError("PERMISSION_DENIED", "Cannot write system field _openid");
|
|
600
|
+
await B.set(f?.data);
|
|
601
|
+
},
|
|
602
|
+
update: async (f) => {
|
|
603
|
+
let V = f?.data ?? {};
|
|
604
|
+
if (!V || typeof V != "object" || Array.isArray(V)) throw new SDKError("INTERNAL_ERROR", "update({data}) must be an object");
|
|
605
|
+
if ("_openid" in V) throw new SDKError("PERMISSION_DENIED", "Cannot write system field _openid");
|
|
606
|
+
await B.update(V);
|
|
607
|
+
},
|
|
608
|
+
remove: async () => (await B.delete(), { stats: { removed: 1 } })
|
|
609
|
+
};
|
|
610
|
+
},
|
|
611
|
+
get: async () => H.get()
|
|
612
|
+
};
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
const webCloud = {
|
|
617
|
+
kv: new WebCloudKv(),
|
|
618
|
+
db: { collection(f) {
|
|
619
|
+
let B = String(f).trim();
|
|
620
|
+
if (!B) throw new SDKError("INTERNAL_ERROR", "collection name is required");
|
|
621
|
+
return new WebCloudDbCollection(B);
|
|
622
|
+
} },
|
|
623
|
+
blob: {
|
|
624
|
+
async createUploadUrl(f) {
|
|
625
|
+
return fetchJson("/cloud/blob/upload-url", {
|
|
626
|
+
method: "POST",
|
|
627
|
+
headers: { "Content-Type": "application/json" },
|
|
628
|
+
body: JSON.stringify({
|
|
629
|
+
path: f.path,
|
|
630
|
+
visibility: f.visibility,
|
|
631
|
+
contentType: f.contentType,
|
|
632
|
+
expiresIn: f.expiresIn
|
|
633
|
+
})
|
|
634
|
+
});
|
|
635
|
+
},
|
|
636
|
+
async getDownloadUrl(f) {
|
|
637
|
+
return fetchJson("/cloud/blob/download-url", {
|
|
638
|
+
method: "POST",
|
|
639
|
+
headers: { "Content-Type": "application/json" },
|
|
640
|
+
body: JSON.stringify({
|
|
641
|
+
fileId: f.fileId,
|
|
642
|
+
expiresIn: f.expiresIn
|
|
643
|
+
})
|
|
644
|
+
});
|
|
645
|
+
}
|
|
646
|
+
},
|
|
647
|
+
functions: { async call(f, B) {
|
|
648
|
+
return (await fetchJson("/cloud/functions/call", {
|
|
649
|
+
method: "POST",
|
|
650
|
+
headers: { "Content-Type": "application/json" },
|
|
651
|
+
body: JSON.stringify({
|
|
652
|
+
name: f,
|
|
653
|
+
data: B ?? null
|
|
654
|
+
})
|
|
655
|
+
})).data;
|
|
656
|
+
} },
|
|
657
|
+
init(f) {},
|
|
658
|
+
database() {
|
|
659
|
+
return createWxDatabase();
|
|
660
|
+
},
|
|
661
|
+
async callFunction(f) {
|
|
662
|
+
let B = String(f?.name ?? "").trim();
|
|
663
|
+
if (!B) throw new SDKError("INTERNAL_ERROR", "callFunction name is required");
|
|
664
|
+
return { result: await webCloud.functions.call(B, f?.data) };
|
|
665
|
+
},
|
|
666
|
+
async uploadFile(f) {
|
|
667
|
+
let B = String(f?.cloudPath ?? "").trim().replace(/^\/+/, "");
|
|
668
|
+
if (!B) throw new SDKError("INTERNAL_ERROR", "cloudPath is required");
|
|
669
|
+
let V = f?.filePath;
|
|
670
|
+
if (!V) throw new SDKError("INTERNAL_ERROR", "filePath is required");
|
|
671
|
+
let H = V.type ? String(V.type) : void 0, { fileId: U, uploadUrl: W } = await webCloud.blob.createUploadUrl({
|
|
672
|
+
path: B,
|
|
673
|
+
visibility: "private",
|
|
674
|
+
contentType: H
|
|
675
|
+
});
|
|
676
|
+
return await fetch(W, {
|
|
677
|
+
method: "PUT",
|
|
678
|
+
headers: H ? { "Content-Type": H } : void 0,
|
|
679
|
+
body: V
|
|
680
|
+
}), { fileID: U };
|
|
681
|
+
},
|
|
682
|
+
async getTempFileURL(f) {
|
|
683
|
+
let B = Array.isArray(f?.fileList) ? f.fileList : [];
|
|
684
|
+
return { fileList: await Promise.all(B.map(async (f) => {
|
|
685
|
+
let B = typeof f == "string" ? f : String(f?.fileID ?? "");
|
|
686
|
+
if (!B) return {
|
|
687
|
+
fileID: "",
|
|
688
|
+
tempFileURL: "",
|
|
689
|
+
status: 400,
|
|
690
|
+
errMsg: "fileID is required"
|
|
691
|
+
};
|
|
692
|
+
try {
|
|
693
|
+
let { url: f } = await webCloud.blob.getDownloadUrl({ fileId: B });
|
|
694
|
+
return {
|
|
695
|
+
fileID: B,
|
|
696
|
+
tempFileURL: f,
|
|
697
|
+
status: 0
|
|
698
|
+
};
|
|
699
|
+
} catch (f) {
|
|
700
|
+
return {
|
|
701
|
+
fileID: B,
|
|
702
|
+
tempFileURL: "",
|
|
703
|
+
status: 500,
|
|
704
|
+
errMsg: f instanceof Error ? f.message : String(f)
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
})) };
|
|
708
|
+
}
|
|
709
|
+
};
|
|
710
|
+
var hostInfo = null, defaultCapabilities = {
|
|
150
711
|
storage: !0,
|
|
151
712
|
network: !1,
|
|
152
713
|
scheduler: !1,
|
|
@@ -163,12 +724,12 @@ var SDKError = class e extends Error {
|
|
|
163
724
|
capture: !1
|
|
164
725
|
}
|
|
165
726
|
};
|
|
166
|
-
const updateHostInfo = (
|
|
167
|
-
hostInfo =
|
|
727
|
+
const updateHostInfo = (f) => {
|
|
728
|
+
hostInfo = f;
|
|
168
729
|
};
|
|
169
|
-
var throwNotSupported = (
|
|
170
|
-
throw new SDKError("NOT_SUPPORTED", `${
|
|
171
|
-
}, stubAsync = (
|
|
730
|
+
var throwNotSupported = (f) => {
|
|
731
|
+
throw new SDKError("NOT_SUPPORTED", `${f} is not supported in this environment.`);
|
|
732
|
+
}, stubAsync = (f) => async () => throwNotSupported(f), stubHandler = (f) => () => throwNotSupported(f), aiAPI = {
|
|
172
733
|
chat: stubAsync("ai.chat"),
|
|
173
734
|
summarize: stubAsync("ai.summarize"),
|
|
174
735
|
translate: stubAsync("ai.translate")
|
|
@@ -257,6 +818,8 @@ const { sdk, childMethods } = createSDK({
|
|
|
257
818
|
} },
|
|
258
819
|
statics: {
|
|
259
820
|
SDKError,
|
|
821
|
+
auth: webAuth,
|
|
822
|
+
cloud: webCloud,
|
|
260
823
|
ai: aiAPI,
|
|
261
824
|
clipboard: clipboardAPI,
|
|
262
825
|
dialog: dialogAPI,
|
|
@@ -265,8 +828,8 @@ const { sdk, childMethods } = createSDK({
|
|
|
265
828
|
onFileDrop
|
|
266
829
|
}
|
|
267
830
|
});
|
|
268
|
-
bootstrapSDK(childMethods, { timeoutMs: 1500 }).then((
|
|
269
|
-
|
|
831
|
+
bootstrapSDK(childMethods, { timeoutMs: 1500 }).then((f) => {
|
|
832
|
+
f && updateHostInfo(f);
|
|
270
833
|
}), sdk.SDKError = SDKError;
|
|
271
834
|
var src_default = sdk;
|
|
272
835
|
export { src_default as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(e,t){typeof exports==`object`&&typeof module<`u`?module.exports=t():typeof define==`function`&&define.amd?define([],t):(e=typeof globalThis<`u`?globalThis:e||self,e.gemigo=t())})(this,function(){var e=Object.defineProperty,t=(e,t)=>()=>(e&&(t=e(e=0)),t),n=t=>{let n={};for(var r in t)e(n,r,{get:t[r],enumerable:!0});return n},r,i,a,o,s,c=t((()=>{(function(e){e.Call=`call`,e.Reply=`reply`,e.Syn=`syn`,e.SynAck=`synAck`,e.Ack=`ack`})(r||={}),(function(e){e.Fulfilled=`fulfilled`,e.Rejected=`rejected`})(i||={}),(function(e){e.ConnectionDestroyed=`ConnectionDestroyed`,e.ConnectionTimeout=`ConnectionTimeout`,e.NoIframeSrc=`NoIframeSrc`})(a||={}),(function(e){e.DataCloneError=`DataCloneError`})(o||={}),(function(e){e.Message=`message`})(s||={})})),l,u=t((()=>{l=(e,t)=>{let n=[],r=!1;return{destroy(i){r||(r=!0,t(`${e}: Destroying connection`),n.forEach(e=>{e(i)}))},onDestroy(e){r?e():n.push(e)}}}})),d,f=t((()=>{d=e=>(...t)=>{e&&console.log(`[Penpal]`,...t)}})),p,m,h=t((()=>{p=({name:e,message:t,stack:n})=>({name:e,message:t,stack:n}),m=e=>{let t=Error();return Object.keys(e).forEach(n=>t[n]=e[n]),t}})),g,_=t((()=>{h(),c(),g=(e,t,n)=>{let{localName:a,local:c,remote:l,originForSending:u,originForReceiving:d}=e,f=!1,m=e=>{if(e.source!==l||e.data.penpal!==r.Call)return;if(d!==`*`&&e.origin!==d){n(`${a} received message from origin ${e.origin} which did not match expected origin ${d}`);return}let{methodName:s,args:c,id:m}=e.data;n(`${a}: Received ${s}() call`);let h=e=>t=>{if(n(`${a}: Sending ${s}() reply`),f){n(`${a}: Unable to send ${s}() reply due to destroyed connection`);return}let c={penpal:r.Reply,id:m,resolution:e,returnValue:t};e===i.Rejected&&t instanceof Error&&(c.returnValue=p(t),c.returnValueIsError=!0);try{l.postMessage(c,u)}catch(e){if(e.name===o.DataCloneError){let t={penpal:r.Reply,id:m,resolution:i.Rejected,returnValue:p(e),returnValueIsError:!0};l.postMessage(t,u)}throw e}};new Promise(e=>e(t[s].apply(t,c))).then(h(i.Fulfilled),h(i.Rejected))};return c.addEventListener(s.Message,m),()=>{f=!0,c.removeEventListener(s.Message,m)}}})),v,y,ee=t((()=>{v=0,y=()=>++v})),b,x,S,C,w,T,E,D=t((()=>{b=`.`,x=e=>e?e.split(b):[],S=e=>e.join(b),C=(e,t)=>{let n=x(t||``);return n.push(e),S(n)},w=(e,t,n)=>{let r=x(t);return r.reduce((e,t,i)=>(e[t]===void 0&&(e[t]={}),i===r.length-1&&(e[t]=n),e[t]),e),e},T=(e,t)=>{let n={};return Object.keys(e).forEach(r=>{let i=e[r],a=C(r,t);typeof i==`object`&&Object.assign(n,T(i,a)),typeof i==`function`&&(n[a]=i)}),n},E=e=>{let t={};for(let n in e)w(t,n,e[n]);return t}})),O,k=t((()=>{ee(),h(),D(),c(),O=(e,t,n,o,c)=>{let{localName:l,local:u,remote:d,originForSending:f,originForReceiving:p}=t,h=!1;c(`${l}: Connecting call sender`);let g=e=>(...t)=>{c(`${l}: Sending ${e}() call`);let n;try{d.closed&&(n=!0)}catch{n=!0}if(n&&o(),h){let t=Error(`Unable to send ${e}() call due to destroyed connection`);throw t.code=a.ConnectionDestroyed,t}return new Promise((n,a)=>{let o=y(),h=t=>{if(t.source!==d||t.data.penpal!==r.Reply||t.data.id!==o)return;if(p!==`*`&&t.origin!==p){c(`${l} received message from origin ${t.origin} which did not match expected origin ${p}`);return}let f=t.data;c(`${l}: Received ${e}() reply`),u.removeEventListener(s.Message,h);let g=f.returnValue;f.returnValueIsError&&(g=m(g)),(f.resolution===i.Fulfilled?n:a)(g)};u.addEventListener(s.Message,h);let g={penpal:r.Call,id:o,methodName:e,args:t};d.postMessage(g,f)})},_=n.reduce((e,t)=>(e[t]=g(t),e),{});return Object.assign(e,E(_)),()=>{h=!0}}})),te=t((()=>{_(),k()})),ne=t((()=>{c()})),A,j=t((()=>{c(),A=(e,t)=>{let n;return e!==void 0&&(n=window.setTimeout(()=>{let n=Error(`Connection timed out after ${e}ms`);n.code=a.ConnectionTimeout,t(n)},e)),()=>{clearTimeout(n)}}})),re=t((()=>{c()})),ie=t((()=>{c(),te(),ne(),j(),re()})),M,ae=t((()=>{c(),_(),k(),M=(e,t,n,i)=>{let{destroy:a,onDestroy:o}=n;return n=>{if(!(e instanceof RegExp?e.test(n.origin):e===`*`||e===n.origin)){i(`Child: Handshake - Received SYN-ACK from origin ${n.origin} which did not match expected origin ${e}`);return}i(`Child: Handshake - Received SYN-ACK, responding with ACK`);let s=n.origin===`null`?`*`:n.origin,c={penpal:r.Ack,methodNames:Object.keys(t)};window.parent.postMessage(c,s);let l={localName:`Child`,local:window,remote:window.parent,originForSending:s,originForReceiving:n.origin};o(g(l,t,i));let u={};return o(O(u,l,n.data.methodNames,a,i)),u}}})),N,P,oe=t((()=>{u(),f(),c(),ae(),D(),j(),N=()=>{try{clearTimeout()}catch{return!1}return!0},P=(e={})=>{let{parentOrigin:t=`*`,methods:n={},timeout:i,debug:a=!1}=e,o=d(a),c=l(`Child`,o),{destroy:u,onDestroy:f}=c,p=M(t,T(n),c,o),m=()=>{o(`Child: Handshake - Sending SYN`);let e={penpal:r.Syn},n=t instanceof RegExp?`*`:t;window.parent.postMessage(e,n)};return{promise:new Promise((e,t)=>{let n=A(i,u),a=t=>{if(N()&&!(t.source!==parent||!t.data)&&t.data.penpal===r.SynAck){let r=p(t);r&&(window.removeEventListener(s.Message,a),n(),e(r))}};window.addEventListener(s.Message,a),m(),f(e=>{window.removeEventListener(s.Message,a),e&&t(e)})}),destroy(){u()}}}})),se=t((()=>{ie(),oe(),c()})),ce=n({callHost:()=>I,createRPCProxy:()=>L,getHost:()=>ue,hasConnectionFailed:()=>fe,initConnection:()=>pe,isConnected:()=>de,tryGetHost:()=>F,withFallback:()=>me});function le(){try{return window.self!==window.top}catch{return!0}}async function F(e,t){if(z)return z;if(B)return null;if(!le())return B=!0,null;if(!R){let n={},r=e??V;r&&Object.assign(n,r),R=P({methods:n,timeout:t?.timeoutMs??H}).promise.then(e=>(z=e,e)).catch(e=>(console.error(`[GemiGo Connection] Promise failed:`,e),B=!0,R=null,null))}return R}async function ue(){let e=await F();if(!e)throw Error(`Not connected to host. SDK may be running outside of a supported environment.`);return e}function de(){return z!==null}function fe(){return B}function pe(e,t){V=e,F(e,t)}async function I(e,t=[],n){let r=await F();if(r&&typeof r[e]==`function`){let i=await r[e](...t);if(i?.success!==!1)return i?.data===void 0?i?.value===void 0?i:i.value:i.data;if(n)return n(...t);throw Error(i?.error||`Host method ${String(e)} failed`)}if(n)return n(...t);throw Error(`Method ${String(e)} not supported in this environment`)}function L(e,t={}){let n={};for(let r of e){let e=t.mapping?.[r]||r,i=t.fallbacks?.[r];n[r]=(...t)=>I(e,t,i)}return n}function me(e,t){return async(...n)=>{try{return await e(...n)}catch{return t(...n)}}}var R,z,B,V,H,U=t((()=>{se(),R=null,z=null,B=!1,H=1500}));U();function W(){let e=new Map;return{on(t,n){return e.has(t)||e.set(t,new Set),e.get(t).add(n),()=>e.get(t)?.delete(n)},emit(t,...n){e.get(t)?.forEach(e=>e(...n))},off(t){t?e.delete(t):e.clear()}}}let G=W();function he(e){let t=F,n={},r={};if(e.rpc){let t=L(e.rpc.methods,{mapping:e.rpc.mapping,fallbacks:e.rpc.fallbacks});Object.assign(n,t)}if(e.events)if(Array.isArray(e.events))for(let i of e.events){let e=i;n[i]=n=>(t?.(),G.on(e,n)),r[i]=(...t)=>{G.emit(e,...t)}}else for(let[i,a]of Object.entries(e.events)){if(!a)continue;let e=a,o=typeof e==`string`?e:e.event,s=typeof e==`object`&&`childMethod`in e&&e.childMethod?e.childMethod:i;n[i]=e=>(t?.(),G.on(o,e)),r[s]=(...e)=>{G.emit(o,...e)}}return{api:n,childMethods:r}}function ge(e,t){return async(...n)=>{try{let r=await I(e,t.transform?t.transform(...n):n);return t.onSuccess?t.onSuccess(r):r}catch{return t.fallback(...n)}}}function _e(e){let t=e.statics?{...e.statics}:{},n={};if(e.modules)for(let[r,i]of Object.entries(e.modules)){let{api:e,childMethods:a}=he(i);t[r]=e,Object.assign(n,a)}if(e.actions)for(let[n,r]of Object.entries(e.actions)){let e=r;t[n]=ge(e.method,e)}if(e.getters)for(let[n,r]of Object.entries(e.getters))Object.defineProperty(t,n,{get:r,enumerable:!0,configurable:!0});return{sdk:t,childMethods:n}}async function ve(e,t={}){let{initConnection:n}=await Promise.resolve().then(()=>(U(),ce));n(e,t);let r=await F();if(r&&typeof r.getProtocolInfo==`function`)try{return await r.getProtocolInfo()}catch{return null}return null}U();var K=()=>`gemigo:${typeof window>`u`?`unknown`:window.location.origin.replace(/[:/]/g,`_`)}:`;let q={get:async e=>{if(typeof window>`u`||!window.localStorage)return null;let t=window.localStorage.getItem(`${K()}${e}`);if(!t)return null;try{return JSON.parse(t)}catch{return null}},set:async(e,t)=>{typeof window>`u`||!window.localStorage||window.localStorage.setItem(`${K()}${e}`,JSON.stringify(t))},delete:async e=>{typeof window>`u`||!window.localStorage||window.localStorage.removeItem(`${K()}${e}`)},clear:async()=>{if(typeof window>`u`||!window.localStorage)return;let e=K();for(let t=window.localStorage.length-1;t>=0;--t){let n=window.localStorage.key(t);n&&n.startsWith(e)&&window.localStorage.removeItem(n)}}},ye=async e=>{if(typeof window>`u`||typeof Notification>`u`)return{success:!1,reason:`not_supported`};if(Notification.permission!==`granted`)return{success:!1,reason:`permission_not_granted`};try{return new Notification(e.title,{body:e.message,icon:e.icon}),{success:!0}}catch{return{success:!1,reason:`failed_to_notify`}}},be={request:async(e,t)=>{let{method:n=`GET`,headers:r,body:i,responseType:a}=t??{},o=await fetch(e,{method:n,headers:r,body:i?typeof i==`string`?i:JSON.stringify(i):void 0}),s={};o.headers.forEach((e,t)=>s[t]=e);let c=a===`text`?await o.text():a===`arraybuffer`?await o.arrayBuffer():await o.json();return{status:o.status,data:c,headers:s}}};var J=class e extends Error{constructor(t,n){super(n),this.code=t,this.name=`SDKError`,Object.setPrototypeOf(this,e.prototype)}},Y=null,xe={storage:!0,network:!1,scheduler:!1,fileWatch:!1,fileWrite:!1,notification:!0,clipboard:!1,ai:!1,shell:!1,extension:{read:!1,events:!1,modify:!1,capture:!1}};let Se=e=>{Y=e};var X=e=>{throw new J(`NOT_SUPPORTED`,`${e} is not supported in this environment.`)},Z=e=>async()=>X(e),Q=e=>()=>X(e),Ce={chat:Z(`ai.chat`),summarize:Z(`ai.summarize`),translate:Z(`ai.translate`)},we={readText:Z(`clipboard.readText`),writeText:Z(`clipboard.writeText`),readImage:Z(`clipboard.readImage`),writeImage:Z(`clipboard.writeImage`),onChange:Q(`clipboard.onChange`)},Te={openFile:Z(`dialog.openFile`),openDirectory:Z(`dialog.openDirectory`),saveFile:Z(`dialog.saveFile`),message:Z(`dialog.message`)},Ee={readText:Z(`file.readText`),readBinary:Z(`file.readBinary`),write:Z(`file.write`),append:Z(`file.append`),exists:Z(`file.exists`),stat:Z(`file.stat`),copy:Z(`file.copy`),move:Z(`file.move`),remove:Z(`file.remove`),list:Z(`file.list`),mkdir:Z(`file.mkdir`),persistPermission:Z(`file.persistPermission`)},De=Q(`onNotificationAction`),Oe=Q(`onFileDrop`);let{sdk:$,childMethods:ke}=_e({getters:{platform:()=>Y?.platform??`web`,capabilities:()=>Y?.capabilities??xe},modules:{storage:{rpc:{methods:[`get`,`set`,`delete`,`clear`],mapping:{get:`storageGet`,set:`storageSet`,delete:`storageDelete`,clear:`storageClear`},fallbacks:{get:q.get,set:q.set,delete:q.delete,clear:q.clear}}},network:{rpc:{methods:[`request`],mapping:{request:`networkRequest`},fallbacks:{request:be.request}}},extension:{rpc:{methods:[`getPageInfo`,`getPageHTML`,`getPageText`,`getSelection`,`extractArticle`,`extractLinks`,`extractImages`,`queryElement`,`highlight`,`removeHighlight`,`insertWidget`,`updateWidget`,`removeWidget`,`injectCSS`,`removeCSS`,`captureVisible`,`getContextMenuEvent`]},events:[`onContextMenu`,`onSelectionChange`]}},actions:{notify:{method:`notify`,fallback:ye}},statics:{SDKError:J,ai:Ce,clipboard:we,dialog:Te,file:Ee,onNotificationAction:De,onFileDrop:Oe}});return ve(ke,{timeoutMs:1500}).then(e=>{e&&Se(e)}),$.SDKError=J,$});
|
|
1
|
+
(function(e,t){typeof exports==`object`&&typeof module<`u`?module.exports=t():typeof define==`function`&&define.amd?define([],t):(e=typeof globalThis<`u`?globalThis:e||self,e.gemigo=t())})(this,function(){var e=Object.defineProperty,t=(e,t)=>()=>(e&&(t=e(e=0)),t),n=t=>{let n={};for(var r in t)e(n,r,{get:t[r],enumerable:!0});return n},r,i,a,o,s,c=t((()=>{(function(e){e.Call=`call`,e.Reply=`reply`,e.Syn=`syn`,e.SynAck=`synAck`,e.Ack=`ack`})(r||={}),(function(e){e.Fulfilled=`fulfilled`,e.Rejected=`rejected`})(i||={}),(function(e){e.ConnectionDestroyed=`ConnectionDestroyed`,e.ConnectionTimeout=`ConnectionTimeout`,e.NoIframeSrc=`NoIframeSrc`})(a||={}),(function(e){e.DataCloneError=`DataCloneError`})(o||={}),(function(e){e.Message=`message`})(s||={})})),l,u=t((()=>{l=(e,t)=>{let n=[],r=!1;return{destroy(i){r||(r=!0,t(`${e}: Destroying connection`),n.forEach(e=>{e(i)}))},onDestroy(e){r?e():n.push(e)}}}})),d,f=t((()=>{d=e=>(...t)=>{e&&console.log(`[Penpal]`,...t)}})),p,m,h=t((()=>{p=({name:e,message:t,stack:n})=>({name:e,message:t,stack:n}),m=e=>{let t=Error();return Object.keys(e).forEach(n=>t[n]=e[n]),t}})),g,_=t((()=>{h(),c(),g=(e,t,n)=>{let{localName:a,local:c,remote:l,originForSending:u,originForReceiving:d}=e,f=!1,m=e=>{if(e.source!==l||e.data.penpal!==r.Call)return;if(d!==`*`&&e.origin!==d){n(`${a} received message from origin ${e.origin} which did not match expected origin ${d}`);return}let{methodName:s,args:c,id:m}=e.data;n(`${a}: Received ${s}() call`);let h=e=>t=>{if(n(`${a}: Sending ${s}() reply`),f){n(`${a}: Unable to send ${s}() reply due to destroyed connection`);return}let c={penpal:r.Reply,id:m,resolution:e,returnValue:t};e===i.Rejected&&t instanceof Error&&(c.returnValue=p(t),c.returnValueIsError=!0);try{l.postMessage(c,u)}catch(e){if(e.name===o.DataCloneError){let t={penpal:r.Reply,id:m,resolution:i.Rejected,returnValue:p(e),returnValueIsError:!0};l.postMessage(t,u)}throw e}};new Promise(e=>e(t[s].apply(t,c))).then(h(i.Fulfilled),h(i.Rejected))};return c.addEventListener(s.Message,m),()=>{f=!0,c.removeEventListener(s.Message,m)}}})),ee,te,ne=t((()=>{ee=0,te=()=>++ee})),v,y,b,x,S,C,w,T=t((()=>{v=`.`,y=e=>e?e.split(v):[],b=e=>e.join(v),x=(e,t)=>{let n=y(t||``);return n.push(e),b(n)},S=(e,t,n)=>{let r=y(t);return r.reduce((e,t,i)=>(e[t]===void 0&&(e[t]={}),i===r.length-1&&(e[t]=n),e[t]),e),e},C=(e,t)=>{let n={};return Object.keys(e).forEach(r=>{let i=e[r],a=x(r,t);typeof i==`object`&&Object.assign(n,C(i,a)),typeof i==`function`&&(n[a]=i)}),n},w=e=>{let t={};for(let n in e)S(t,n,e[n]);return t}})),E,D=t((()=>{ne(),h(),T(),c(),E=(e,t,n,o,c)=>{let{localName:l,local:u,remote:d,originForSending:f,originForReceiving:p}=t,h=!1;c(`${l}: Connecting call sender`);let g=e=>(...t)=>{c(`${l}: Sending ${e}() call`);let n;try{d.closed&&(n=!0)}catch{n=!0}if(n&&o(),h){let t=Error(`Unable to send ${e}() call due to destroyed connection`);throw t.code=a.ConnectionDestroyed,t}return new Promise((n,a)=>{let o=te(),h=t=>{if(t.source!==d||t.data.penpal!==r.Reply||t.data.id!==o)return;if(p!==`*`&&t.origin!==p){c(`${l} received message from origin ${t.origin} which did not match expected origin ${p}`);return}let f=t.data;c(`${l}: Received ${e}() reply`),u.removeEventListener(s.Message,h);let g=f.returnValue;f.returnValueIsError&&(g=m(g)),(f.resolution===i.Fulfilled?n:a)(g)};u.addEventListener(s.Message,h);let g={penpal:r.Call,id:o,methodName:e,args:t};d.postMessage(g,f)})},_=n.reduce((e,t)=>(e[t]=g(t),e),{});return Object.assign(e,w(_)),()=>{h=!0}}})),re=t((()=>{_(),D()})),ie=t((()=>{c()})),ae,O=t((()=>{c(),ae=(e,t)=>{let n;return e!==void 0&&(n=window.setTimeout(()=>{let n=Error(`Connection timed out after ${e}ms`);n.code=a.ConnectionTimeout,t(n)},e)),()=>{clearTimeout(n)}}})),oe=t((()=>{c()})),se=t((()=>{c(),re(),ie(),O(),oe()})),k,ce=t((()=>{c(),_(),D(),k=(e,t,n,i)=>{let{destroy:a,onDestroy:o}=n;return n=>{if(!(e instanceof RegExp?e.test(n.origin):e===`*`||e===n.origin)){i(`Child: Handshake - Received SYN-ACK from origin ${n.origin} which did not match expected origin ${e}`);return}i(`Child: Handshake - Received SYN-ACK, responding with ACK`);let s=n.origin===`null`?`*`:n.origin,c={penpal:r.Ack,methodNames:Object.keys(t)};window.parent.postMessage(c,s);let l={localName:`Child`,local:window,remote:window.parent,originForSending:s,originForReceiving:n.origin};o(g(l,t,i));let u={};return o(E(u,l,n.data.methodNames,a,i)),u}}})),A,j,le=t((()=>{u(),f(),c(),ce(),T(),O(),A=()=>{try{clearTimeout()}catch{return!1}return!0},j=(e={})=>{let{parentOrigin:t=`*`,methods:n={},timeout:i,debug:a=!1}=e,o=d(a),c=l(`Child`,o),{destroy:u,onDestroy:f}=c,p=k(t,C(n),c,o),m=()=>{o(`Child: Handshake - Sending SYN`);let e={penpal:r.Syn},n=t instanceof RegExp?`*`:t;window.parent.postMessage(e,n)};return{promise:new Promise((e,t)=>{let n=ae(i,u),a=t=>{if(A()&&!(t.source!==parent||!t.data)&&t.data.penpal===r.SynAck){let r=p(t);r&&(window.removeEventListener(s.Message,a),n(),e(r))}};window.addEventListener(s.Message,a),m(),f(e=>{window.removeEventListener(s.Message,a),e&&t(e)})}),destroy(){u()}}}})),ue=t((()=>{se(),le(),c()})),de=n({callHost:()=>N,createRPCProxy:()=>P,getHost:()=>pe,hasConnectionFailed:()=>he,initConnection:()=>ge,isConnected:()=>me,tryGetHost:()=>M,withFallback:()=>_e});function fe(){try{return window.self!==window.top}catch{return!0}}async function M(e,t){if(I)return I;if(L)return null;if(!fe())return L=!0,null;if(!F){let n={},r=e??R;r&&Object.assign(n,r),F=j({methods:n,timeout:t?.timeoutMs??z}).promise.then(e=>(I=e,e)).catch(e=>(console.error(`[GemiGo Connection] Promise failed:`,e),L=!0,F=null,null))}return F}async function pe(){let e=await M();if(!e)throw Error(`Not connected to host. SDK may be running outside of a supported environment.`);return e}function me(){return I!==null}function he(){return L}function ge(e,t){R=e,M(e,t)}async function N(e,t=[],n){let r=await M();if(r&&typeof r[e]==`function`){let i=await r[e](...t);if(i?.success!==!1)return i?.data===void 0?i?.value===void 0?i:i.value:i.data;if(n)return n(...t);throw Error(i?.error||`Host method ${String(e)} failed`)}if(n)return n(...t);throw Error(`Method ${String(e)} not supported in this environment`)}function P(e,t={}){let n={};for(let r of e){let e=t.mapping?.[r]||r,i=t.fallbacks?.[r];n[r]=(...t)=>N(e,t,i)}return n}function _e(e,t){return async(...n)=>{try{return await e(...n)}catch{return t(...n)}}}var F,I,L,R,z,B=t((()=>{ue(),F=null,I=null,L=!1,z=1500}));B();function ve(){let e=new Map;return{on(t,n){return e.has(t)||e.set(t,new Set),e.get(t).add(n),()=>e.get(t)?.delete(n)},emit(t,...n){e.get(t)?.forEach(e=>e(...n))},off(t){t?e.delete(t):e.clear()}}}let V=ve();function ye(e){let t=M,n={},r={};if(e.rpc){let t=P(e.rpc.methods,{mapping:e.rpc.mapping,fallbacks:e.rpc.fallbacks});Object.assign(n,t)}if(e.events)if(Array.isArray(e.events))for(let i of e.events){let e=i;n[i]=n=>(t?.(),V.on(e,n)),r[i]=(...t)=>{V.emit(e,...t)}}else for(let[i,a]of Object.entries(e.events)){if(!a)continue;let e=a,o=typeof e==`string`?e:e.event,s=typeof e==`object`&&`childMethod`in e&&e.childMethod?e.childMethod:i;n[i]=e=>(t?.(),V.on(o,e)),r[s]=(...e)=>{V.emit(o,...e)}}return{api:n,childMethods:r}}function be(e,t){return async(...n)=>{try{let r=await N(e,t.transform?t.transform(...n):n);return t.onSuccess?t.onSuccess(r):r}catch{return t.fallback(...n)}}}function xe(e){let t=e.statics?{...e.statics}:{},n={};if(e.modules)for(let[r,i]of Object.entries(e.modules)){let{api:e,childMethods:a}=ye(i);t[r]=e,Object.assign(n,a)}if(e.actions)for(let[n,r]of Object.entries(e.actions)){let e=r;t[n]=be(e.method,e)}if(e.getters)for(let[n,r]of Object.entries(e.getters))Object.defineProperty(t,n,{get:r,enumerable:!0,configurable:!0});return{sdk:t,childMethods:n}}async function Se(e,t={}){let{initConnection:n}=await Promise.resolve().then(()=>(B(),de));n(e,t);let r=await M();if(r&&typeof r.getProtocolInfo==`function`)try{return await r.getProtocolInfo()}catch{return null}return null}B();var H=()=>`gemigo:${typeof window>`u`?`unknown`:window.location.origin.replace(/[:/]/g,`_`)}:`;let U={get:async e=>{if(typeof window>`u`||!window.localStorage)return null;let t=window.localStorage.getItem(`${H()}${e}`);if(!t)return null;try{return JSON.parse(t)}catch{return null}},set:async(e,t)=>{typeof window>`u`||!window.localStorage||window.localStorage.setItem(`${H()}${e}`,JSON.stringify(t))},delete:async e=>{typeof window>`u`||!window.localStorage||window.localStorage.removeItem(`${H()}${e}`)},clear:async()=>{if(typeof window>`u`||!window.localStorage)return;let e=H();for(let t=window.localStorage.length-1;t>=0;--t){let n=window.localStorage.key(t);n&&n.startsWith(e)&&window.localStorage.removeItem(n)}}},Ce=async e=>{if(typeof window>`u`||typeof Notification>`u`)return{success:!1,reason:`not_supported`};if(Notification.permission!==`granted`)return{success:!1,reason:`permission_not_granted`};try{return new Notification(e.title,{body:e.message,icon:e.icon}),{success:!0}}catch{return{success:!1,reason:`failed_to_notify`}}},we={request:async(e,t)=>{let{method:n=`GET`,headers:r,body:i,responseType:a}=t??{},o=await fetch(e,{method:n,headers:r,body:i?typeof i==`string`?i:JSON.stringify(i):void 0}),s={};o.headers.forEach((e,t)=>s[t]=e);let c=a===`text`?await o.text():a===`arraybuffer`?await o.arrayBuffer():await o.json();return{status:o.status,data:c,headers:s}}};var W=class e extends Error{constructor(t,n){super(n),this.code=t,this.name=`SDKError`,Object.setPrototypeOf(this,e.prototype)}},G=null,K=null;function Te(e){let t=``;for(let n of e)t+=String.fromCharCode(n);let n=globalThis.btoa;if(!n)throw Error(`base64 encoder not available`);return n(t).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/g,``)}function Ee(e=32){let t=new Uint8Array(e);return crypto.getRandomValues(t),Te(t)}async function De(e){let t=new TextEncoder().encode(e),n=await crypto.subtle.digest(`SHA-256`,t);return Te(new Uint8Array(n))}function Oe(){if(typeof window>`u`)return`unknown`;let e=window.location.hostname.toLowerCase();return e.endsWith(`.gemigo.app`)?e.replace(/\.gemigo\.app$/,``):e}function ke(e){let t=(e??[`identity:basic`]).map(e=>String(e).trim()).filter(Boolean);return t.length>0?t:[`identity:basic`]}function Ae(e){let t=new URL(`/sdk/broker`,e.platformOrigin);return t.searchParams.set(`app_id`,e.appId),t.searchParams.set(`scope`,e.scopes.join(` `)),t.searchParams.set(`state`,e.state),t.searchParams.set(`code_challenge`,e.codeChallenge),t.searchParams.set(`code_challenge_method`,`S256`),t.searchParams.set(`origin`,e.openerOrigin),t.toString()}async function je(e,t,n){let r=await fetch(`${e.replace(/\/+$/,``)}/sdk/token`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({code:t,codeVerifier:n})});if(!r.ok){let e=await r.json().catch(()=>({}));throw Error(e.error||`Failed to exchange code`)}return await r.json()}function Me(){return K||`https://gemigo.io/api/v1`}let Ne={async login(e={}){if(typeof window>`u`)throw new W(`NOT_SUPPORTED`,`auth.login is only supported in browser environments.`);let t=e.platformOrigin?.trim()||`https://gemigo.io`,n=e.apiBaseUrl?.trim()||`${t.replace(/\/+$/,``)}/api/v1`,r=e.appId?.trim()||Oe(),i=ke(e.scopes),a=typeof e.timeoutMs==`number`?e.timeoutMs:120*1e3,o=Ee(16),s=Ee(48),c=window.location.origin,l=Math.max(0,(window.screen.width-520)/2),u=Math.max(0,(window.screen.height-720)/2),d=window.open(`about:blank`,`gemigo_sdk_auth`,`popup=yes,width=520,height=720,left=${l},top=${u}`);if(!d)throw Error(`Popup blocked. Please allow popups and retry.`);try{d.document.title=`GemiGo Auth`,d.document.body.innerHTML=`<div style="font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;padding:24px;">Loading…</div>`}catch{}let f=Ae({platformOrigin:t,appId:r,scopes:i,state:o,codeChallenge:await De(s),openerOrigin:c});try{d.location.href=f}catch{if(!window.open(f,`gemigo_sdk_auth`))throw Error(`Popup navigation failed. Please allow popups and retry.`)}let p=await je(n,(await new Promise((e,n)=>{let r=window.setTimeout(()=>{i(),n(Error(`Login timeout.`))},a),i=()=>{window.clearTimeout(r),window.removeEventListener(`message`,s);try{d.close()}catch{}},s=r=>{if(r.origin!==new URL(t).origin)return;let a=r.data;if(!(!a||typeof a!=`object`)&&a.state===o){if(a.type===`gemigo:sdk-auth-error`){i(),n(Error(String(a.error||`auth_error`)));return}a.type===`gemigo:sdk-auth-code`&&typeof a.code==`string`&&(i(),e({code:a.code}))}};window.addEventListener(`message`,s)})).code,s);return G=p,K=n,p},getAccessToken(){return G?.accessToken??null},logout(){G=null}};function Pe(){let e=Ne.getAccessToken();if(!e)throw new W(`PERMISSION_DENIED`,`Login required. Call gemigo.auth.login() first.`);return e}async function q(e,t={}){let n=Pe(),r=Me().replace(/\/+$/,``),i=await fetch(`${r}${e}`,{...t,headers:{...t.headers??{},Authorization:`Bearer ${n}`}});if(!i.ok){let e=(await i.json().catch(()=>({}))).error||`Request failed: ${i.status}`;throw i.status===401||i.status===403?new W(`PERMISSION_DENIED`,e):new W(`INTERNAL_ERROR`,e)}return await i.json()}var Fe=class{async get(e){return q(`/cloud/kv/get?key=${encodeURIComponent(e)}`)}async set(e,t,n){return q(`/cloud/kv/set`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({key:e,value:t,ifMatch:n?.ifMatch})})}async delete(e,t){await q(`/cloud/kv/delete`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({key:e,ifMatch:t?.ifMatch})})}async list(e){let t=new URLSearchParams;e?.prefix&&t.set(`prefix`,e.prefix),typeof e?.limit==`number`&&t.set(`limit`,String(e.limit)),e?.cursor&&t.set(`cursor`,e.cursor);let n=t.toString();return q(`/cloud/kv/list${n?`?${n}`:``}`)}},Ie=class e{constructor(e,t){this.collectionName=e,this.state={where:t?.where??[],orderBy:t?.orderBy??{field:`createdAt`,direction:`desc`},limit:t?.limit??20,cursor:t?.cursor??null}}where(t,n,r){return new e(this.collectionName,{...this.state,where:[...this.state.where,{field:t,op:n,value:r}]})}orderBy(t,n=`desc`){return new e(this.collectionName,{...this.state,orderBy:{field:t,direction:n}})}limit(t){return new e(this.collectionName,{...this.state,limit:t})}startAfter(t){return new e(this.collectionName,{...this.state,cursor:t})}async get(){return q(`/cloud/db/collections/${encodeURIComponent(this.collectionName)}/query`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({where:this.state.where,orderBy:this.state.orderBy,limit:this.state.limit,cursor:this.state.cursor})})}},Le=class{constructor(e){this.name=e}async add(e,t){return q(`/cloud/db/collections/${encodeURIComponent(this.name)}/docs`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({id:t?.id,visibility:t?.visibility,refType:t?.refType,refId:t?.refId,data:e})})}doc(e){let t=this.name;return{get:async()=>q(`/cloud/db/collections/${encodeURIComponent(t)}/docs/${encodeURIComponent(e)}`),set:async(n,r)=>q(`/cloud/db/collections/${encodeURIComponent(t)}/docs/${encodeURIComponent(e)}`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({data:n,ifMatch:r?.ifMatch,visibility:r?.visibility,refType:r?.refType,refId:r?.refId})}),update:async(n,r)=>q(`/cloud/db/collections/${encodeURIComponent(t)}/docs/${encodeURIComponent(e)}`,{method:`PATCH`,headers:{"Content-Type":`application/json`},body:JSON.stringify({patch:n,ifMatch:r?.ifMatch})}),delete:async()=>q(`/cloud/db/collections/${encodeURIComponent(t)}/docs/${encodeURIComponent(e)}`,{method:`DELETE`}).then(()=>void 0)}}query(){return new Ie(this.name)}};function J(e){return{...e.data&&typeof e.data==`object`&&!Array.isArray(e.data)?e.data:{},_id:e.id,_openid:e.ownerId}}function Re(){return{eq:e=>({__gemigoWxCmd:`eq`,value:e}),neq:e=>({__gemigoWxCmd:`neq`,value:e}),gt:e=>({__gemigoWxCmd:`gt`,value:e}),gte:e=>({__gemigoWxCmd:`gte`,value:e}),lt:e=>({__gemigoWxCmd:`lt`,value:e}),lte:e=>({__gemigoWxCmd:`lte`,value:e}),in:e=>({__gemigoWxCmd:`in`,value:Array.isArray(e)?e:[]}),nin:e=>({__gemigoWxCmd:`nin`,value:Array.isArray(e)?e:[]}),inc:e=>({__gemigoWxCmd:`inc`,value:e}),set:e=>({__gemigoWxCmd:`set`,value:e}),remove:()=>({__gemigoWxCmd:`remove`})}}function ze(e){let t=typeof e?.offset==`number`&&Number.isFinite(e.offset)?e.offset:void 0;return t===void 0?{__gemigoWxType:`serverDate`}:{__gemigoWxType:`serverDate`,offset:t}}function Be(e){return e===`asc`?`asc`:`desc`}async function Ve(e,t,n,r){return q(`/cloud/db/collections/${encodeURIComponent(e)}/query`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({where:t.where,orderBy:t.orderBy,limit:r,cursor:n})})}function Y(e,t,n){let r={where:n?.where??{},orderBy:n?.orderBy??{field:`createdAt`,direction:`desc`},limit:n?.limit??20,skip:n?.skip??0,cursor:n?.cursor??null};return{where(n){return Y(e,t,{...r,where:{...r.where,...n??{}}})},orderBy(n,i){return Y(e,t,{...r,orderBy:{field:String(n),direction:Be(i)}})},limit(n){return Y(e,t,{...r,limit:Math.max(1,Math.floor(Number(n)||0))})},skip(n){return Y(e,t,{...r,skip:Math.max(0,Math.floor(Number(n)||0))})},startAfter(n){let i=String(n??``).trim();if(!i)throw new W(`INTERNAL_ERROR`,`startAfter(cursor) requires a non-empty cursor`);return Y(e,t,{...r,cursor:i})},async count(){return q(`/cloud/db/collections/${encodeURIComponent(e)}/count`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({where:r.where})})},async update(t){let n=t?.data;if(!n||typeof n!=`object`||Array.isArray(n))throw new W(`INTERNAL_ERROR`,`update({data}) must be an object`);if(`_openid`in n)throw new W(`PERMISSION_DENIED`,`Cannot write system field _openid`);return q(`/cloud/db/collections/${encodeURIComponent(e)}/update`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({where:r.where,data:n})})},async remove(){return q(`/cloud/db/collections/${encodeURIComponent(e)}/remove`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({where:r.where})})},async get(){let t=Math.min(r.limit,100),n=r.skip;if(n>1e3)throw new W(`NOT_SUPPORTED`,`skip(n) is capped at 1000; use cursor pagination instead.`);let i=r.cursor??null,a=n,o=t,s=[],c=0;for(;(a>0||o>0)&&c<30;){let t=await Ve(e,r,i,Math.min(100,a>0?a:o));if(c+=1,t.items.length===0)break;if(a>0){let e=Math.min(a,t.items.length);a-=e;let n=t.items.slice(e);if(a===0&&o>0&&n.length>0){let e=Math.min(o,n.length);s.push(...n.slice(0,e).map(J)),o-=e}}else s.push(...t.items.slice(0,o).map(J)),o=Math.max(0,o-t.items.length);if(i=t.nextCursor,!i)break}if(c>=30)throw new W(`NOT_SUPPORTED`,`skip/limit query requires too many requests; narrow your query.`);return{data:s,_meta:{nextCursor:i}}}}}function He(){let e=Re();return{command:e,serverDate:e=>ze(e),collection(t){let n=String(t).trim();if(!n)throw new W(`INTERNAL_ERROR`,`collection name is required`);let r=Y(n,e);return{...r,add:async e=>{let t=e?.data;if(t&&typeof t==`object`&&!Array.isArray(t)&&`_openid`in t)throw new W(`PERMISSION_DENIED`,`Cannot write system field _openid`);let r=t&&typeof t==`object`&&!Array.isArray(t)?t._id:void 0,i=t&&typeof t==`object`&&!Array.isArray(t)?{...t}:t;return i&&typeof i==`object`&&!Array.isArray(i)&&delete i._id,{_id:(await X.db.collection(n).add(i,{id:r?String(r):void 0})).id}},doc:e=>{let t=X.db.collection(n).doc(String(e));return{get:async()=>({data:J(await t.get())}),set:async e=>{let n=e?.data;if(n&&typeof n==`object`&&!Array.isArray(n)&&`_openid`in n)throw new W(`PERMISSION_DENIED`,`Cannot write system field _openid`);await t.set(e?.data)},update:async e=>{let n=e?.data??{};if(!n||typeof n!=`object`||Array.isArray(n))throw new W(`INTERNAL_ERROR`,`update({data}) must be an object`);if(`_openid`in n)throw new W(`PERMISSION_DENIED`,`Cannot write system field _openid`);await t.update(n)},remove:async()=>(await t.delete(),{stats:{removed:1}})}},get:async()=>r.get()}}}}let X={kv:new Fe,db:{collection(e){let t=String(e).trim();if(!t)throw new W(`INTERNAL_ERROR`,`collection name is required`);return new Le(t)}},blob:{async createUploadUrl(e){return q(`/cloud/blob/upload-url`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({path:e.path,visibility:e.visibility,contentType:e.contentType,expiresIn:e.expiresIn})})},async getDownloadUrl(e){return q(`/cloud/blob/download-url`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({fileId:e.fileId,expiresIn:e.expiresIn})})}},functions:{async call(e,t){return(await q(`/cloud/functions/call`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({name:e,data:t??null})})).data}},init(e){},database(){return He()},async callFunction(e){let t=String(e?.name??``).trim();if(!t)throw new W(`INTERNAL_ERROR`,`callFunction name is required`);return{result:await X.functions.call(t,e?.data)}},async uploadFile(e){let t=String(e?.cloudPath??``).trim().replace(/^\/+/,``);if(!t)throw new W(`INTERNAL_ERROR`,`cloudPath is required`);let n=e?.filePath;if(!n)throw new W(`INTERNAL_ERROR`,`filePath is required`);let r=n.type?String(n.type):void 0,{fileId:i,uploadUrl:a}=await X.blob.createUploadUrl({path:t,visibility:`private`,contentType:r});return await fetch(a,{method:`PUT`,headers:r?{"Content-Type":r}:void 0,body:n}),{fileID:i}},async getTempFileURL(e){let t=Array.isArray(e?.fileList)?e.fileList:[];return{fileList:await Promise.all(t.map(async e=>{let t=typeof e==`string`?e:String(e?.fileID??``);if(!t)return{fileID:``,tempFileURL:``,status:400,errMsg:`fileID is required`};try{let{url:e}=await X.blob.getDownloadUrl({fileId:t});return{fileID:t,tempFileURL:e,status:0}}catch(e){return{fileID:t,tempFileURL:``,status:500,errMsg:e instanceof Error?e.message:String(e)}}}))}}};var Z=null,Ue={storage:!0,network:!1,scheduler:!1,fileWatch:!1,fileWrite:!1,notification:!0,clipboard:!1,ai:!1,shell:!1,extension:{read:!1,events:!1,modify:!1,capture:!1}};let We=e=>{Z=e};var Ge=e=>{throw new W(`NOT_SUPPORTED`,`${e} is not supported in this environment.`)},Q=e=>async()=>Ge(e),$=e=>()=>Ge(e),Ke={chat:Q(`ai.chat`),summarize:Q(`ai.summarize`),translate:Q(`ai.translate`)},qe={readText:Q(`clipboard.readText`),writeText:Q(`clipboard.writeText`),readImage:Q(`clipboard.readImage`),writeImage:Q(`clipboard.writeImage`),onChange:$(`clipboard.onChange`)},Je={openFile:Q(`dialog.openFile`),openDirectory:Q(`dialog.openDirectory`),saveFile:Q(`dialog.saveFile`),message:Q(`dialog.message`)},Ye={readText:Q(`file.readText`),readBinary:Q(`file.readBinary`),write:Q(`file.write`),append:Q(`file.append`),exists:Q(`file.exists`),stat:Q(`file.stat`),copy:Q(`file.copy`),move:Q(`file.move`),remove:Q(`file.remove`),list:Q(`file.list`),mkdir:Q(`file.mkdir`),persistPermission:Q(`file.persistPermission`)},Xe=$(`onNotificationAction`),Ze=$(`onFileDrop`);let{sdk:Qe,childMethods:$e}=xe({getters:{platform:()=>Z?.platform??`web`,capabilities:()=>Z?.capabilities??Ue},modules:{storage:{rpc:{methods:[`get`,`set`,`delete`,`clear`],mapping:{get:`storageGet`,set:`storageSet`,delete:`storageDelete`,clear:`storageClear`},fallbacks:{get:U.get,set:U.set,delete:U.delete,clear:U.clear}}},network:{rpc:{methods:[`request`],mapping:{request:`networkRequest`},fallbacks:{request:we.request}}},extension:{rpc:{methods:[`getPageInfo`,`getPageHTML`,`getPageText`,`getSelection`,`extractArticle`,`extractLinks`,`extractImages`,`queryElement`,`highlight`,`removeHighlight`,`insertWidget`,`updateWidget`,`removeWidget`,`injectCSS`,`removeCSS`,`captureVisible`,`getContextMenuEvent`]},events:[`onContextMenu`,`onSelectionChange`]}},actions:{notify:{method:`notify`,fallback:Ce}},statics:{SDKError:W,auth:Ne,cloud:X,ai:Ke,clipboard:qe,dialog:Je,file:Ye,onNotificationAction:Xe,onFileDrop:Ze}});return Se($e,{timeoutMs:1500}).then(e=>{e&&We(e)}),Qe.SDKError=W,Qe});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export type AuthScope = 'identity:basic' | 'storage:rw' | string;
|
|
2
|
+
export interface AuthLoginOptions {
|
|
3
|
+
/**
|
|
4
|
+
* App identifier used for consent + app-scoped identity.
|
|
5
|
+
* In GemiGo hosted apps, default is derived from `<slug>.gemigo.app`.
|
|
6
|
+
*/
|
|
7
|
+
appId?: string;
|
|
8
|
+
scopes?: AuthScope[];
|
|
9
|
+
/**
|
|
10
|
+
* Platform origin that hosts the broker page, e.g. `https://gemigo.io`.
|
|
11
|
+
* Defaults to `https://gemigo.io`.
|
|
12
|
+
*/
|
|
13
|
+
platformOrigin?: string;
|
|
14
|
+
/**
|
|
15
|
+
* API base URL, e.g. `https://gemigo.io/api/v1` (or `https://api.gemigo.io/api/v1`).
|
|
16
|
+
* Defaults to `${platformOrigin}/api/v1`.
|
|
17
|
+
*/
|
|
18
|
+
apiBaseUrl?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Popup wait timeout.
|
|
21
|
+
*/
|
|
22
|
+
timeoutMs?: number;
|
|
23
|
+
}
|
|
24
|
+
export interface AuthTokenResponse {
|
|
25
|
+
accessToken: string;
|
|
26
|
+
expiresIn: number;
|
|
27
|
+
appId: string;
|
|
28
|
+
appUserId: string;
|
|
29
|
+
scopes: string[];
|
|
30
|
+
}
|
|
31
|
+
export interface AuthAPI {
|
|
32
|
+
login(options?: AuthLoginOptions): Promise<AuthTokenResponse>;
|
|
33
|
+
getAccessToken(): string | null;
|
|
34
|
+
logout(): void;
|
|
35
|
+
}
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
export type CloudScope = 'identity:basic' | 'storage:rw' | 'db:rw' | 'blob:rw' | 'functions:invoke' | string;
|
|
2
|
+
export type CloudVisibility = 'private' | 'public' | string;
|
|
3
|
+
export interface CloudKvItemMeta {
|
|
4
|
+
key: string;
|
|
5
|
+
etag: string;
|
|
6
|
+
updatedAt: number;
|
|
7
|
+
valueBytes: number;
|
|
8
|
+
}
|
|
9
|
+
export interface CloudKvAPI {
|
|
10
|
+
get<T = unknown>(key: string): Promise<{
|
|
11
|
+
key: string;
|
|
12
|
+
value: T;
|
|
13
|
+
etag: string;
|
|
14
|
+
updatedAt: number;
|
|
15
|
+
}>;
|
|
16
|
+
set(key: string, value: unknown, options?: {
|
|
17
|
+
ifMatch?: string;
|
|
18
|
+
}): Promise<{
|
|
19
|
+
key: string;
|
|
20
|
+
etag: string;
|
|
21
|
+
updatedAt: number;
|
|
22
|
+
}>;
|
|
23
|
+
delete(key: string, options?: {
|
|
24
|
+
ifMatch?: string;
|
|
25
|
+
}): Promise<void>;
|
|
26
|
+
list(options?: {
|
|
27
|
+
prefix?: string;
|
|
28
|
+
limit?: number;
|
|
29
|
+
cursor?: string | null;
|
|
30
|
+
}): Promise<{
|
|
31
|
+
items: CloudKvItemMeta[];
|
|
32
|
+
nextCursor: string | null;
|
|
33
|
+
}>;
|
|
34
|
+
}
|
|
35
|
+
export interface CloudDbDoc<T = unknown> {
|
|
36
|
+
id: string;
|
|
37
|
+
ownerId: string;
|
|
38
|
+
visibility: CloudVisibility;
|
|
39
|
+
refType: string | null;
|
|
40
|
+
refId: string | null;
|
|
41
|
+
data: T;
|
|
42
|
+
createdAt: number;
|
|
43
|
+
updatedAt: number;
|
|
44
|
+
etag: string;
|
|
45
|
+
}
|
|
46
|
+
export type CloudDbWhereOp = '==';
|
|
47
|
+
export interface CloudDbWhere {
|
|
48
|
+
field: 'ownerId' | 'visibility' | 'refType' | 'refId';
|
|
49
|
+
op: CloudDbWhereOp;
|
|
50
|
+
value: string;
|
|
51
|
+
}
|
|
52
|
+
export interface CloudDbQueryInput {
|
|
53
|
+
where?: CloudDbWhere[];
|
|
54
|
+
orderBy?: {
|
|
55
|
+
field: 'createdAt' | 'updatedAt';
|
|
56
|
+
direction: 'asc' | 'desc';
|
|
57
|
+
};
|
|
58
|
+
limit?: number;
|
|
59
|
+
cursor?: string | null;
|
|
60
|
+
}
|
|
61
|
+
export interface CloudDbQueryResult<T = unknown> {
|
|
62
|
+
items: Array<CloudDbDoc<T>>;
|
|
63
|
+
nextCursor: string | null;
|
|
64
|
+
}
|
|
65
|
+
export interface CloudDbDocumentRef<T = unknown> {
|
|
66
|
+
get(): Promise<CloudDbDoc<T>>;
|
|
67
|
+
set(data: T, options?: {
|
|
68
|
+
ifMatch?: string;
|
|
69
|
+
visibility?: CloudVisibility;
|
|
70
|
+
refType?: string;
|
|
71
|
+
refId?: string;
|
|
72
|
+
}): Promise<CloudDbDoc<T>>;
|
|
73
|
+
update(patch: Partial<T>, options?: {
|
|
74
|
+
ifMatch?: string;
|
|
75
|
+
}): Promise<CloudDbDoc<T>>;
|
|
76
|
+
delete(): Promise<void>;
|
|
77
|
+
}
|
|
78
|
+
export interface CloudDbQueryBuilder<T = unknown> {
|
|
79
|
+
where(field: CloudDbWhere['field'], op: CloudDbWhereOp, value: string): CloudDbQueryBuilder<T>;
|
|
80
|
+
orderBy(field: 'createdAt' | 'updatedAt', direction?: 'asc' | 'desc'): CloudDbQueryBuilder<T>;
|
|
81
|
+
limit(n: number): CloudDbQueryBuilder<T>;
|
|
82
|
+
startAfter(cursor: string): CloudDbQueryBuilder<T>;
|
|
83
|
+
get(): Promise<CloudDbQueryResult<T>>;
|
|
84
|
+
}
|
|
85
|
+
export interface CloudDbCollection<T = unknown> {
|
|
86
|
+
add(data: T, options?: {
|
|
87
|
+
id?: string;
|
|
88
|
+
visibility?: CloudVisibility;
|
|
89
|
+
refType?: string;
|
|
90
|
+
refId?: string;
|
|
91
|
+
}): Promise<CloudDbDoc<T>>;
|
|
92
|
+
doc(id: string): CloudDbDocumentRef<T>;
|
|
93
|
+
query(): CloudDbQueryBuilder<T>;
|
|
94
|
+
}
|
|
95
|
+
export interface CloudDbAPI {
|
|
96
|
+
collection<T = unknown>(name: string): CloudDbCollection<T>;
|
|
97
|
+
}
|
|
98
|
+
export interface CloudBlobAPI {
|
|
99
|
+
createUploadUrl(input: {
|
|
100
|
+
path?: string;
|
|
101
|
+
visibility?: CloudVisibility;
|
|
102
|
+
contentType?: string;
|
|
103
|
+
expiresIn?: number;
|
|
104
|
+
}): Promise<{
|
|
105
|
+
fileId: string;
|
|
106
|
+
uploadUrl: string;
|
|
107
|
+
expiresIn: number;
|
|
108
|
+
}>;
|
|
109
|
+
getDownloadUrl(input: {
|
|
110
|
+
fileId: string;
|
|
111
|
+
expiresIn?: number;
|
|
112
|
+
}): Promise<{
|
|
113
|
+
fileId: string;
|
|
114
|
+
url: string;
|
|
115
|
+
expiresIn: number;
|
|
116
|
+
}>;
|
|
117
|
+
}
|
|
118
|
+
export interface CloudFunctionsAPI {
|
|
119
|
+
call<T = unknown>(name: string, payload?: unknown): Promise<T>;
|
|
120
|
+
}
|
|
121
|
+
export type WxCloudQueryDirection = 'asc' | 'desc';
|
|
122
|
+
export type WxCloudCommandExpr = {
|
|
123
|
+
__gemigoWxCmd: 'eq';
|
|
124
|
+
value: unknown;
|
|
125
|
+
} | {
|
|
126
|
+
__gemigoWxCmd: 'neq';
|
|
127
|
+
value: unknown;
|
|
128
|
+
} | {
|
|
129
|
+
__gemigoWxCmd: 'gt';
|
|
130
|
+
value: unknown;
|
|
131
|
+
} | {
|
|
132
|
+
__gemigoWxCmd: 'gte';
|
|
133
|
+
value: unknown;
|
|
134
|
+
} | {
|
|
135
|
+
__gemigoWxCmd: 'lt';
|
|
136
|
+
value: unknown;
|
|
137
|
+
} | {
|
|
138
|
+
__gemigoWxCmd: 'lte';
|
|
139
|
+
value: unknown;
|
|
140
|
+
} | {
|
|
141
|
+
__gemigoWxCmd: 'in';
|
|
142
|
+
value: unknown[];
|
|
143
|
+
} | {
|
|
144
|
+
__gemigoWxCmd: 'nin';
|
|
145
|
+
value: unknown[];
|
|
146
|
+
} | {
|
|
147
|
+
__gemigoWxCmd: 'inc';
|
|
148
|
+
value: number;
|
|
149
|
+
} | {
|
|
150
|
+
__gemigoWxCmd: 'set';
|
|
151
|
+
value: unknown;
|
|
152
|
+
} | {
|
|
153
|
+
__gemigoWxCmd: 'remove';
|
|
154
|
+
};
|
|
155
|
+
export interface WxCloudCommand {
|
|
156
|
+
eq(value: unknown): WxCloudCommandExpr;
|
|
157
|
+
neq(value: unknown): WxCloudCommandExpr;
|
|
158
|
+
gt(value: unknown): WxCloudCommandExpr;
|
|
159
|
+
gte(value: unknown): WxCloudCommandExpr;
|
|
160
|
+
lt(value: unknown): WxCloudCommandExpr;
|
|
161
|
+
lte(value: unknown): WxCloudCommandExpr;
|
|
162
|
+
in(list: unknown[]): WxCloudCommandExpr;
|
|
163
|
+
nin(list: unknown[]): WxCloudCommandExpr;
|
|
164
|
+
inc(n: number): WxCloudCommandExpr;
|
|
165
|
+
set(value: unknown): WxCloudCommandExpr;
|
|
166
|
+
remove(): WxCloudCommandExpr;
|
|
167
|
+
}
|
|
168
|
+
export type WxCloudServerDate = {
|
|
169
|
+
__gemigoWxType: 'serverDate';
|
|
170
|
+
offset?: number;
|
|
171
|
+
};
|
|
172
|
+
export interface WxCloudGetResult<TDoc = unknown> {
|
|
173
|
+
data: TDoc[];
|
|
174
|
+
/**
|
|
175
|
+
* GemiGo extension: opaque cursor for efficient pagination.
|
|
176
|
+
* - Kept in `_meta` to preserve wx.cloud-style `{ data }` shape.
|
|
177
|
+
*/
|
|
178
|
+
_meta?: {
|
|
179
|
+
nextCursor: string | null;
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
export interface WxCloudAddResult {
|
|
183
|
+
_id: string;
|
|
184
|
+
}
|
|
185
|
+
export interface WxCloudRemoveResult {
|
|
186
|
+
stats: {
|
|
187
|
+
removed: number;
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
export interface WxCloudCountResult {
|
|
191
|
+
total: number;
|
|
192
|
+
}
|
|
193
|
+
export interface WxCloudUpdateResult {
|
|
194
|
+
stats: {
|
|
195
|
+
updated: number;
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
export interface WxCloudDocumentRef<TData = unknown> {
|
|
199
|
+
get(): Promise<{
|
|
200
|
+
data: (TData & {
|
|
201
|
+
_id: string;
|
|
202
|
+
});
|
|
203
|
+
}>;
|
|
204
|
+
set(input: {
|
|
205
|
+
data: TData;
|
|
206
|
+
}): Promise<void>;
|
|
207
|
+
update(input: {
|
|
208
|
+
data: Partial<TData>;
|
|
209
|
+
}): Promise<void>;
|
|
210
|
+
remove(): Promise<WxCloudRemoveResult>;
|
|
211
|
+
}
|
|
212
|
+
export interface WxCloudQuery<TData = unknown> {
|
|
213
|
+
where(condition: Record<string, unknown>): WxCloudQuery<TData>;
|
|
214
|
+
orderBy(field: string, direction?: WxCloudQueryDirection): WxCloudQuery<TData>;
|
|
215
|
+
limit(n: number): WxCloudQuery<TData>;
|
|
216
|
+
skip(n: number): WxCloudQuery<TData>;
|
|
217
|
+
/**
|
|
218
|
+
* GemiGo extension: cursor pagination (recommended over large skip).
|
|
219
|
+
* Cursor is obtained from `_meta.nextCursor` of a previous `get()`.
|
|
220
|
+
*/
|
|
221
|
+
startAfter(cursor: string): WxCloudQuery<TData>;
|
|
222
|
+
get(): Promise<WxCloudGetResult<TData & {
|
|
223
|
+
_id: string;
|
|
224
|
+
}>>;
|
|
225
|
+
count(): Promise<WxCloudCountResult>;
|
|
226
|
+
update(input: {
|
|
227
|
+
data: Record<string, unknown>;
|
|
228
|
+
}): Promise<WxCloudUpdateResult>;
|
|
229
|
+
remove(): Promise<WxCloudRemoveResult>;
|
|
230
|
+
}
|
|
231
|
+
export interface WxCloudCollection<TData = unknown> extends WxCloudQuery<TData> {
|
|
232
|
+
add(input: {
|
|
233
|
+
data: TData;
|
|
234
|
+
}): Promise<WxCloudAddResult>;
|
|
235
|
+
doc(id: string): WxCloudDocumentRef<TData>;
|
|
236
|
+
}
|
|
237
|
+
export interface WxCloudDatabase {
|
|
238
|
+
readonly command: WxCloudCommand;
|
|
239
|
+
serverDate(options?: {
|
|
240
|
+
offset?: number;
|
|
241
|
+
}): WxCloudServerDate;
|
|
242
|
+
collection<TData = unknown>(name: string): WxCloudCollection<TData>;
|
|
243
|
+
}
|
|
244
|
+
export interface WxCloudCallFunctionInput {
|
|
245
|
+
name: string;
|
|
246
|
+
data?: unknown;
|
|
247
|
+
}
|
|
248
|
+
export interface WxCloudCallFunctionResult<TResult = unknown> {
|
|
249
|
+
result: TResult;
|
|
250
|
+
}
|
|
251
|
+
export interface WxCloudUploadFileInput {
|
|
252
|
+
cloudPath: string;
|
|
253
|
+
filePath: Blob;
|
|
254
|
+
}
|
|
255
|
+
export interface WxCloudUploadFileResult {
|
|
256
|
+
fileID: string;
|
|
257
|
+
}
|
|
258
|
+
export interface WxCloudGetTempFileURLInput {
|
|
259
|
+
fileList: Array<string | {
|
|
260
|
+
fileID: string;
|
|
261
|
+
}>;
|
|
262
|
+
}
|
|
263
|
+
export interface WxCloudGetTempFileURLResult {
|
|
264
|
+
fileList: Array<{
|
|
265
|
+
fileID: string;
|
|
266
|
+
tempFileURL: string;
|
|
267
|
+
status: number;
|
|
268
|
+
errMsg?: string;
|
|
269
|
+
}>;
|
|
270
|
+
}
|
|
271
|
+
export interface CloudAPI {
|
|
272
|
+
kv: CloudKvAPI;
|
|
273
|
+
db: CloudDbAPI;
|
|
274
|
+
blob: CloudBlobAPI;
|
|
275
|
+
functions: CloudFunctionsAPI;
|
|
276
|
+
/** wx.cloud.init-style facade (currently a no-op config holder) */
|
|
277
|
+
init(options?: {
|
|
278
|
+
env?: string;
|
|
279
|
+
}): void;
|
|
280
|
+
/** wx.cloud.database() facade */
|
|
281
|
+
database(): WxCloudDatabase;
|
|
282
|
+
/** wx.cloud.callFunction facade */
|
|
283
|
+
callFunction<TResult = unknown>(input: WxCloudCallFunctionInput): Promise<WxCloudCallFunctionResult<TResult>>;
|
|
284
|
+
/** wx.cloud.uploadFile facade (web accepts Blob/File) */
|
|
285
|
+
uploadFile(input: WxCloudUploadFileInput): Promise<WxCloudUploadFileResult>;
|
|
286
|
+
/** wx.cloud.getTempFileURL facade */
|
|
287
|
+
getTempFileURL(input: WxCloudGetTempFileURLInput): Promise<WxCloudGetTempFileURLResult>;
|
|
288
|
+
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Platform, Capabilities, SDKError, FileEntry } from './common';
|
|
2
2
|
import { StorageAPI } from './storage';
|
|
3
|
+
import { AuthAPI } from './auth';
|
|
4
|
+
import { CloudAPI } from './cloud';
|
|
3
5
|
import { NotifyOptions, NotifyResult } from './notify';
|
|
4
6
|
import { AIAPI } from './ai';
|
|
5
7
|
import { ClipboardAPI } from './clipboard';
|
|
@@ -16,6 +18,8 @@ import { ExtensionAPI } from './extension';
|
|
|
16
18
|
export type { Platform, Capabilities, FileEntry, FileStat, RPCResult, RPCResultWithData, SDKErrorCode, } from './common';
|
|
17
19
|
export { SDKError } from './common';
|
|
18
20
|
export type { StorageAPI } from './storage';
|
|
21
|
+
export type { AuthAPI, AuthLoginOptions, AuthScope, AuthTokenResponse } from './auth';
|
|
22
|
+
export type { CloudAPI, CloudScope, CloudVisibility, WxCloudQueryDirection, WxCloudCommandExpr, WxCloudCommand, WxCloudServerDate, WxCloudGetResult, WxCloudAddResult, WxCloudRemoveResult, WxCloudDocumentRef, WxCloudQuery, WxCloudCollection, WxCloudDatabase, WxCloudCallFunctionInput, WxCloudCallFunctionResult, WxCloudUploadFileInput, WxCloudUploadFileResult, WxCloudGetTempFileURLInput, WxCloudGetTempFileURLResult, CloudKvAPI, CloudKvItemMeta, CloudDbAPI, CloudDbCollection, CloudDbDoc, CloudDbDocumentRef, CloudDbQueryBuilder, CloudDbQueryInput, CloudDbQueryResult, CloudDbWhere, CloudDbWhereOp, CloudBlobAPI, CloudFunctionsAPI, } from './cloud';
|
|
19
23
|
export type { NotifyAction, NotifyOptions, NotifyResult, NotifyFn, NotificationActionHandler, } from './notify';
|
|
20
24
|
export type { ChatMessage, ChatResponse, TranslateOptions, TranslateResult, AIAPI } from './ai';
|
|
21
25
|
export type { ClipboardContent, ClipboardChangeCallback, ClipboardAPI } from './clipboard';
|
|
@@ -42,6 +46,10 @@ export interface GemigoSDK {
|
|
|
42
46
|
readonly SDKError: typeof SDKError;
|
|
43
47
|
/** Persistent key-value storage */
|
|
44
48
|
storage: StorageAPI;
|
|
49
|
+
/** App identity & login (App SDK V0) */
|
|
50
|
+
auth: AuthAPI;
|
|
51
|
+
/** Gemigo Cloud (hosted backend) */
|
|
52
|
+
cloud: CloudAPI;
|
|
45
53
|
/**
|
|
46
54
|
* Send system notification
|
|
47
55
|
* @param options - Notification options
|