@gemigo/app-sdk 0.2.6 → 0.2.8

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