primitive-app 3.2.0-alpha.2 → 3.2.0-alpha.20
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/components/ui/native-select/NativeSelectOptGroup.vue.d.ts +48 -48
- package/dist/components/ui/native-select/NativeSelectOption.vue.d.ts +50 -50
- package/dist/dev-tools/blob-explorer/blobExplorerTypes.d.ts +11 -2
- package/dist/dev-tools/document-explorer/composables/useOptimisticList.d.ts +3 -3
- package/dist/dev-tools/document-explorer/documentLists.d.ts +72 -0
- package/dist/dev-tools/document-explorer/utils.d.ts +1 -0
- package/dist/dev-tools/vite-plugin/generated-env-resolver-core.d.ts +131 -12
- package/dist/dev-tools/vite-plugin/index.cjs +3 -3
- package/dist/dev-tools/vite-plugin/index.js +173 -105
- package/dist/dev-tools/vite-plugin/primitive-env.d.ts +1 -1
- package/dist/index.cjs +5 -5
- package/dist/index.js +3418 -3402
- package/dist/lib/portal-target.d.ts +14 -0
- package/dist/lib-CZJJRJq3.cjs +1 -0
- package/dist/{lib-B7ZH2Pdd.js → lib-SnRn0TGH.js} +101 -29
- package/dist/primitive-app.css +1 -1
- package/dist/services/JsBaoClientService.d.ts +4 -2
- package/dist/testing/index.cjs +1 -1
- package/dist/testing/index.js +4 -4
- package/package.json +3 -2
- package/src/style.css +185 -2
- package/dist/lib-CFnieS8T.cjs +0 -1
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ComputedRef, type Ref } from "vue";
|
|
2
|
+
/**
|
|
3
|
+
* Render the portaled content of descendants (dialogs, dropdown menus,
|
|
4
|
+
* selects, popovers, sheets) into `target` instead of `document.body`.
|
|
5
|
+
*
|
|
6
|
+
* The dev tools provide their themed root, so what they open keeps their
|
|
7
|
+
* styling rather than the host app's.
|
|
8
|
+
*/
|
|
9
|
+
export declare function providePortalTarget(target: Ref<HTMLElement | undefined>): void;
|
|
10
|
+
/**
|
|
11
|
+
* The element portaled content renders into: the nearest
|
|
12
|
+
* `providePortalTarget` element once it is mounted, otherwise `"body"`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function usePortalTarget(): ComputedRef<HTMLElement | "body">;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
let e=require("js-bao-wss-client");var t={debug:0,info:1,warn:2,error:3,none:4},n=`warn`,r=class e{#e;scope;constructor(e,t){this.#e=e,this.scope=t}get level(){return this.#e.level}set level(e){this.setLevel(e)}debug(...e){this.#t(`debug`,e)}log(...e){this.#t(`info`,e,`log`)}warn(...e){this.#t(`warn`,e)}error(...e){this.#t(`error`,e)}shouldLog(e){return t[e]>=t[this.level]}getLevel(){return this.level}setLevel(e){e in t&&(this.#e.level=e)}forScope(t){let n=t.trim(),r=n?[...this.scope,n]:this.scope;return new e(this.#e,r)}#t(e,t,n){if(!this.shouldLog(e))return;let r=n??(e===`info`?`log`:e),i=this.scope.length?`[${this.scope.join(`:`)}]`:void 0,a=i?[i,...t]:t;console[r](...a)}},i={level:n},a=new r(i,[]).forScope(`PrimitiveApp`);function o(e){i.level=e}var s=a.forScope(`JsBaoClientService`);function c(){if(typeof window>`u`)return!1;let e=window.location.hostname;return e===`localhost`||e===`127.0.0.1`||e===`[::1]`||e.endsWith(`.localhost`)||e.endsWith(`.local`)}var l=new class{client=null;clientInitializationPromise=null;config=null;initialize(e){s.debug(`Initializing with config:`,{appId:e.appId?`${e.appId.substring(0,10)}...`:`MISSING`,apiUrl:e.apiUrl,wsUrl:e.wsUrl,oauthRedirectUri:e.oauthRedirectUri});let t=[];(!e.appId||e.appId===`MISSING_APP_ID`)&&t.push(`appId`),(!e.apiUrl||e.apiUrl===`MISSING_API_URL`)&&t.push(`apiUrl`),(!e.wsUrl||e.wsUrl===`MISSING_WS_URL`)&&t.push(`wsUrl`),(!e.oauthRedirectUri||e.oauthRedirectUri===`MISSING_OAUTH_REDIRECT_URI`)&&t.push(`oauthRedirectUri`),t.length>0&&(s.error(`❌ Configuration validation failed!`),s.error(`Missing or invalid fields:`,t),s.error(`This will cause OAuth and API calls to fail.`),s.error(`Identity (appId/apiUrl/wsUrl) comes from primitive/config.json via the primitiveEnv() Vite plugin — check that the project has one and that an environment is selected ('primitive env use <name>'). Callback and logging settings come from your .env files.`)),this.config=e}getConfig(){return this.config}async getClientAsync(){if(s.debug(`Getting client async`),this.clientInitializationPromise)return this.clientInitializationPromise;if(!this.config)throw Error(`JsBaoClientService not initialized. Call initialize() first.`);return this.clientInitializationPromise=(async()=>{s.debug(`=== INITIALIZING CLIENT ===`),s.debug(`Configuration:`,this.config);let t=await(0,e.initializeClient)(this.config);if(t.on(`status`,e=>{s.debug(`Client status changed:`,e)}),t.on(`error`,e=>{s.error(`Client error:`,e)}),this.client=t,c()&&(window.__primitiveAppClient=t,this.config?.models&&Array.isArray(this.config.models))){let e={};for(let t of this.config.models){let n=t.schema?.name;if(n){let r=n.charAt(0).toUpperCase()+n.slice(1);e[r]=t}}window.__primitiveAppModels=e,s.debug(`Registered models on window:`,Object.keys(e))}return s.debug(`=== CLIENT INITIALIZATION COMPLETE ===`),t})(),this.clientInitializationPromise}setExternalClient(e){s.debug(`Setting external client from host app`),this.client=e,this.clientInitializationPromise=Promise.resolve(e)}clearClient(){return s.debug(`Clearing client singleton...`),this.client&&(this.client.disconnect().catch(e=>{s.warn(`Background disconnect failed (this is usually harmless):`,e)}),this.client=null,this.clientInitializationPromise=null,c()&&(window.__primitiveAppClient=void 0,window.__primitiveAppModels=void 0)),Promise.resolve()}};function u(e){l.initialize(e)}async function d(e,t){let n=[],r;for(let i=0;i<t;i++){let t=await e(r);if(n.push(...t.items??[]),!t.hasMore||!t.nextCursor)return{items:n,complete:!0};r=t.nextCursor}return{items:n,complete:!1}}function f(e){let t=new Map;for(let n of e)t.has(n.documentId)||t.set(n.documentId,n);return Array.from(t.values())}async function p(e,t,n){let r=new URLSearchParams({includeRoot:`true`,limit:String(t)});n&&r.set(`cursor`,n);let i=await e.makeRequest(`GET`,`/me/owned-documents?${r.toString()}`);return{items:i?.items??[],hasMore:typeof i?.hasMore==`boolean`?i.hasMore:!!i?.nextCursor,nextCursor:i?.nextCursor??void 0}}function m(e,t){let n=Date.parse(e.createdAt||``),r=Date.parse(e.createCommittedAt||``),i=Math.max(Number.isFinite(n)?n:-1/0,Number.isFinite(r)?r:-1/0);return Number.isFinite(i)&&t-i<=6e4}async function h(e,{pageSize:t=100,maxPages:n=50}={}){let[r,i,a]=await Promise.all([d(n=>p(e,t,n),n),e.me.ownedDocuments({includeRoot:!0,localOnly:!0}),e.me.ownedDocuments({includeRoot:!0,refreshFromServer:!1})]),o=Date.now();return{owned:f([...r.items,...i,...a.filter(e=>m(e,o))]),complete:r.complete}}async function g(e,t={}){let{pageSize:n=100,maxPages:r=50}=t,[i,a]=await Promise.all([h(e,{pageSize:n,maxPages:r}),d(t=>e.me.sharedDocuments({limit:n,cursor:t}),r)]);return{owned:i.owned,shared:f(a.items),complete:i.complete&&a.complete}}var _=a.forScope(`TestHarness`),v=`===TEST===`;async function y(e={}){let{networkSync:t=!1}=e,n=await l.getClientAsync(),r=`${v} ${`${Date.now()}-${Math.random().toString(36).substring(2,11)}`}`;if(t){let{metadata:e}=await n.documents.create({title:r}),t=e.documentId,{doc:i}=await n.documents.open(t);if(!i)throw Error(`[TestHarness] Failed to open synced test document`);return n.setDefaultDocumentId(t),_.debug(`Created synced test document`,{docId:t}),b.set(t,{client:n,docId:t,networkSync:!0}),{docId:t}}let{metadata:i}=await n.documents.create({title:r,localOnly:!0}),a=i.documentId,{doc:o}=await n.documents.open(a,{waitForLoad:`local`,enableNetworkSync:!1});if(!o)throw Error(`[TestHarness] Failed to open test document`);return n.setDefaultDocumentId(a),_.debug(`Created test document`,{docId:a}),b.set(a,{client:n,docId:a,networkSync:!1}),{docId:a}}var b=new Map;async function x(e){let t=b.get(e.docId);if(!t){_.warn(`destroyTestDocument called with unknown handle`,{docId:e.docId});return}b.delete(e.docId);try{t.networkSync?await t.client.documents.delete(t.docId,{forceCloseIfOpen:!0}):(await t.client.documents.close(t.docId),await t.client.documents.evict(t.docId,{force:!0}))}catch(e){_.error(`Failed to destroy test document`,{docId:t.docId,err:e})}}async function S(){try{let e=await l.getClientAsync();_.debug(`[deleteAllTestDocuments] Starting cleanup...`),await e.syncMetadata({scope:`all`});let{owned:t}=await h(e),n=t.filter(e=>e.title?.startsWith(v));if(n.length===0)return 0;_.debug(`[deleteAllTestDocuments] Found test documents to delete`,{count:n.length});let r=0;for(let t of n)try{e.documents.isOpen(t.documentId)&&await e.documents.close(t.documentId),await e.documents.evict(t.documentId,{force:!0}),r++}catch(e){_.error(`[deleteAllTestDocuments] Failed to delete test document`,{documentId:t.documentId,err:e})}return _.debug(`[deleteAllTestDocuments] Cleanup complete`,{evictedCount:r}),r}catch(e){return _.error(`[deleteAllTestDocuments] Top-level error during cleanup`,{err:e}),0}}function C(e){return e.flatMap(e=>e.tests.map(t=>({id:t.id,name:t.name,group:e.name,environment:t.environment??e.environment,run:t.run})))}Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,"c",{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return x}}),Object.defineProperty(exports,"l",{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return y}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return S}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return C}});
|
|
@@ -72,7 +72,7 @@ var l = new class {
|
|
|
72
72
|
oauthRedirectUri: e.oauthRedirectUri
|
|
73
73
|
});
|
|
74
74
|
let t = [];
|
|
75
|
-
(!e.appId || e.appId === "MISSING_APP_ID") && t.push("appId"), (!e.apiUrl || e.apiUrl === "MISSING_API_URL") && t.push("apiUrl"), (!e.wsUrl || e.wsUrl === "MISSING_WS_URL") && t.push("wsUrl"), (!e.oauthRedirectUri || e.oauthRedirectUri === "MISSING_OAUTH_REDIRECT_URI") && t.push("oauthRedirectUri"), t.length > 0 && (s.error("❌ Configuration validation failed!"), s.error("Missing or invalid fields:", t), s.error("This will cause OAuth and API calls to fail."), s.error("Identity (appId/apiUrl/wsUrl) comes from
|
|
75
|
+
(!e.appId || e.appId === "MISSING_APP_ID") && t.push("appId"), (!e.apiUrl || e.apiUrl === "MISSING_API_URL") && t.push("apiUrl"), (!e.wsUrl || e.wsUrl === "MISSING_WS_URL") && t.push("wsUrl"), (!e.oauthRedirectUri || e.oauthRedirectUri === "MISSING_OAUTH_REDIRECT_URI") && t.push("oauthRedirectUri"), t.length > 0 && (s.error("❌ Configuration validation failed!"), s.error("Missing or invalid fields:", t), s.error("This will cause OAuth and API calls to fail."), s.error("Identity (appId/apiUrl/wsUrl) comes from primitive/config.json via the primitiveEnv() Vite plugin — check that the project has one and that an environment is selected ('primitive env use <name>'). Callback and logging settings come from your .env files.")), this.config = e;
|
|
76
76
|
}
|
|
77
77
|
getConfig() {
|
|
78
78
|
return this.config;
|
|
@@ -104,24 +104,96 @@ var l = new class {
|
|
|
104
104
|
setExternalClient(e) {
|
|
105
105
|
s.debug("Setting external client from host app"), this.client = e, this.clientInitializationPromise = Promise.resolve(e);
|
|
106
106
|
}
|
|
107
|
-
|
|
108
|
-
s.debug("Clearing client singleton..."), this.client && (this.client.disconnect().catch((e) => {
|
|
107
|
+
clearClient() {
|
|
108
|
+
return s.debug("Clearing client singleton..."), this.client && (this.client.disconnect().catch((e) => {
|
|
109
109
|
s.warn("Background disconnect failed (this is usually harmless):", e);
|
|
110
|
-
}), this.client = null, this.clientInitializationPromise = null, c() && (window.__primitiveAppClient = void 0, window.__primitiveAppModels = void 0));
|
|
110
|
+
}), this.client = null, this.clientInitializationPromise = null, c() && (window.__primitiveAppClient = void 0, window.__primitiveAppModels = void 0)), Promise.resolve();
|
|
111
111
|
}
|
|
112
112
|
}();
|
|
113
113
|
function u(e) {
|
|
114
114
|
l.initialize(e);
|
|
115
115
|
}
|
|
116
|
+
async function d(e, t) {
|
|
117
|
+
let n = [], r;
|
|
118
|
+
for (let i = 0; i < t; i++) {
|
|
119
|
+
let t = await e(r);
|
|
120
|
+
if (n.push(...t.items ?? []), !t.hasMore || !t.nextCursor) return {
|
|
121
|
+
items: n,
|
|
122
|
+
complete: !0
|
|
123
|
+
};
|
|
124
|
+
r = t.nextCursor;
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
items: n,
|
|
128
|
+
complete: !1
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function f(e) {
|
|
132
|
+
let t = /* @__PURE__ */ new Map();
|
|
133
|
+
for (let n of e) t.has(n.documentId) || t.set(n.documentId, n);
|
|
134
|
+
return Array.from(t.values());
|
|
135
|
+
}
|
|
136
|
+
async function p(e, t, n) {
|
|
137
|
+
let r = new URLSearchParams({
|
|
138
|
+
includeRoot: "true",
|
|
139
|
+
limit: String(t)
|
|
140
|
+
});
|
|
141
|
+
n && r.set("cursor", n);
|
|
142
|
+
let i = await e.makeRequest("GET", `/me/owned-documents?${r.toString()}`);
|
|
143
|
+
return {
|
|
144
|
+
items: i?.items ?? [],
|
|
145
|
+
hasMore: typeof i?.hasMore == "boolean" ? i.hasMore : !!i?.nextCursor,
|
|
146
|
+
nextCursor: i?.nextCursor ?? void 0
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
function m(e, t) {
|
|
150
|
+
let n = Date.parse(e.createdAt || ""), r = Date.parse(e.createCommittedAt || ""), i = Math.max(Number.isFinite(n) ? n : -Infinity, Number.isFinite(r) ? r : -Infinity);
|
|
151
|
+
return Number.isFinite(i) && t - i <= 6e4;
|
|
152
|
+
}
|
|
153
|
+
async function h(e, { pageSize: t = 100, maxPages: n = 50 } = {}) {
|
|
154
|
+
let [r, i, a] = await Promise.all([
|
|
155
|
+
d((n) => p(e, t, n), n),
|
|
156
|
+
e.me.ownedDocuments({
|
|
157
|
+
includeRoot: !0,
|
|
158
|
+
localOnly: !0
|
|
159
|
+
}),
|
|
160
|
+
e.me.ownedDocuments({
|
|
161
|
+
includeRoot: !0,
|
|
162
|
+
refreshFromServer: !1
|
|
163
|
+
})
|
|
164
|
+
]), o = Date.now();
|
|
165
|
+
return {
|
|
166
|
+
owned: f([
|
|
167
|
+
...r.items,
|
|
168
|
+
...i,
|
|
169
|
+
...a.filter((e) => m(e, o))
|
|
170
|
+
]),
|
|
171
|
+
complete: r.complete
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
async function g(e, t = {}) {
|
|
175
|
+
let { pageSize: n = 100, maxPages: r = 50 } = t, [i, a] = await Promise.all([h(e, {
|
|
176
|
+
pageSize: n,
|
|
177
|
+
maxPages: r
|
|
178
|
+
}), d((t) => e.me.sharedDocuments({
|
|
179
|
+
limit: n,
|
|
180
|
+
cursor: t
|
|
181
|
+
}), r)]);
|
|
182
|
+
return {
|
|
183
|
+
owned: i.owned,
|
|
184
|
+
shared: f(a.items),
|
|
185
|
+
complete: i.complete && a.complete
|
|
186
|
+
};
|
|
187
|
+
}
|
|
116
188
|
//#endregion
|
|
117
189
|
//#region src/dev-tools/test-harness/lib.ts
|
|
118
|
-
var
|
|
119
|
-
async function
|
|
120
|
-
let { networkSync: t = !1 } = e, n = await l.getClientAsync(), r = `${
|
|
190
|
+
var _ = a.forScope("TestHarness"), v = "===TEST===";
|
|
191
|
+
async function y(e = {}) {
|
|
192
|
+
let { networkSync: t = !1 } = e, n = await l.getClientAsync(), r = `${v} ${`${Date.now()}-${Math.random().toString(36).substring(2, 11)}`}`;
|
|
121
193
|
if (t) {
|
|
122
194
|
let { metadata: e } = await n.documents.create({ title: r }), t = e.documentId, { doc: i } = await n.documents.open(t);
|
|
123
195
|
if (!i) throw Error("[TestHarness] Failed to open synced test document");
|
|
124
|
-
return n.setDefaultDocumentId(t),
|
|
196
|
+
return n.setDefaultDocumentId(t), _.debug("Created synced test document", { docId: t }), b.set(t, {
|
|
125
197
|
client: n,
|
|
126
198
|
docId: t,
|
|
127
199
|
networkSync: !0
|
|
@@ -135,51 +207,51 @@ async function p(e = {}) {
|
|
|
135
207
|
enableNetworkSync: !1
|
|
136
208
|
});
|
|
137
209
|
if (!o) throw Error("[TestHarness] Failed to open test document");
|
|
138
|
-
return n.setDefaultDocumentId(a),
|
|
210
|
+
return n.setDefaultDocumentId(a), _.debug("Created test document", { docId: a }), b.set(a, {
|
|
139
211
|
client: n,
|
|
140
212
|
docId: a,
|
|
141
213
|
networkSync: !1
|
|
142
214
|
}), { docId: a };
|
|
143
215
|
}
|
|
144
|
-
var
|
|
145
|
-
async function
|
|
146
|
-
let t =
|
|
216
|
+
var b = /* @__PURE__ */ new Map();
|
|
217
|
+
async function x(e) {
|
|
218
|
+
let t = b.get(e.docId);
|
|
147
219
|
if (!t) {
|
|
148
|
-
|
|
220
|
+
_.warn("destroyTestDocument called with unknown handle", { docId: e.docId });
|
|
149
221
|
return;
|
|
150
222
|
}
|
|
151
|
-
|
|
223
|
+
b.delete(e.docId);
|
|
152
224
|
try {
|
|
153
225
|
t.networkSync ? await t.client.documents.delete(t.docId, { forceCloseIfOpen: !0 }) : (await t.client.documents.close(t.docId), await t.client.documents.evict(t.docId, { force: !0 }));
|
|
154
226
|
} catch (e) {
|
|
155
|
-
|
|
227
|
+
_.error("Failed to destroy test document", {
|
|
156
228
|
docId: t.docId,
|
|
157
229
|
err: e
|
|
158
230
|
});
|
|
159
231
|
}
|
|
160
232
|
}
|
|
161
|
-
async function
|
|
233
|
+
async function S() {
|
|
162
234
|
try {
|
|
163
235
|
let e = await l.getClientAsync();
|
|
164
|
-
|
|
165
|
-
let t =
|
|
166
|
-
if (
|
|
167
|
-
|
|
168
|
-
let
|
|
169
|
-
for (let
|
|
170
|
-
e.documents.isOpen(
|
|
236
|
+
_.debug("[deleteAllTestDocuments] Starting cleanup..."), await e.syncMetadata({ scope: "all" });
|
|
237
|
+
let { owned: t } = await h(e), n = t.filter((e) => e.title?.startsWith(v));
|
|
238
|
+
if (n.length === 0) return 0;
|
|
239
|
+
_.debug("[deleteAllTestDocuments] Found test documents to delete", { count: n.length });
|
|
240
|
+
let r = 0;
|
|
241
|
+
for (let t of n) try {
|
|
242
|
+
e.documents.isOpen(t.documentId) && await e.documents.close(t.documentId), await e.documents.evict(t.documentId, { force: !0 }), r++;
|
|
171
243
|
} catch (e) {
|
|
172
|
-
|
|
173
|
-
documentId:
|
|
244
|
+
_.error("[deleteAllTestDocuments] Failed to delete test document", {
|
|
245
|
+
documentId: t.documentId,
|
|
174
246
|
err: e
|
|
175
247
|
});
|
|
176
248
|
}
|
|
177
|
-
return
|
|
249
|
+
return _.debug("[deleteAllTestDocuments] Cleanup complete", { evictedCount: r }), r;
|
|
178
250
|
} catch (e) {
|
|
179
|
-
return
|
|
251
|
+
return _.error("[deleteAllTestDocuments] Top-level error during cleanup", { err: e }), 0;
|
|
180
252
|
}
|
|
181
253
|
}
|
|
182
|
-
function
|
|
254
|
+
function C(e) {
|
|
183
255
|
return e.flatMap((e) => e.tests.map((t) => ({
|
|
184
256
|
id: t.id,
|
|
185
257
|
name: t.name,
|
|
@@ -189,4 +261,4 @@ function _(e) {
|
|
|
189
261
|
})));
|
|
190
262
|
}
|
|
191
263
|
//#endregion
|
|
192
|
-
export {
|
|
264
|
+
export { g as a, a as c, x as i, o as l, y as n, u as o, S as r, l as s, C as t };
|
package/dist/primitive-app.css
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
[data-v-
|
|
1
|
+
[data-v-8904b115] tr[data-slot=table-row]{border-bottom-width:0}[data-v-8904b115] th[data-slot=table-head],[data-v-8904b115] td[data-slot=table-cell]{height:1.5rem;padding-top:.25rem;padding-bottom:.25rem}.scrollbar-thin::-webkit-scrollbar{width:6px;height:6px}.scrollbar-thin::-webkit-scrollbar-track{background:0 0}.scrollbar-thin::-webkit-scrollbar-thumb{background:var(--color-border);border-radius:3px}.scrollbar-thin::-webkit-scrollbar-thumb:hover{background:var(--color-muted-foreground)}
|
|
2
2
|
/*$vite$:1*/
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
* `VITE_APP_ID`, `VITE_API_URL`, `VITE_WS_URL` and `VITE_APP_NAME` are NOT
|
|
78
78
|
* authored by hand. They are filled in at build time by the `primitiveEnv()`
|
|
79
79
|
* plugin (`primitive-app/vite`) from the Primitive environment selected in
|
|
80
|
-
*
|
|
80
|
+
* `primitive/config.json` — the one place a backend URL and app ID are typed.
|
|
81
81
|
* Choose the environment with `primitive env use <name>`, or `--primitive-env`
|
|
82
82
|
* on a deploy; `VITE_WS_URL` is derived from the API URL by scheme swap.
|
|
83
83
|
*
|
|
@@ -130,7 +130,9 @@ declare class JsBaoClientService {
|
|
|
130
130
|
*/
|
|
131
131
|
setExternalClient(client: JsBaoClient): void;
|
|
132
132
|
/**
|
|
133
|
-
* Clears the singleton instance (used during logout)
|
|
133
|
+
* Clears the singleton instance (used during logout). Nothing here is
|
|
134
|
+
* awaited — the disconnect runs in the background — but the method keeps
|
|
135
|
+
* returning a promise for the callers that await it.
|
|
134
136
|
*/
|
|
135
137
|
clearClient(): Promise<void>;
|
|
136
138
|
}
|
package/dist/testing/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../rolldown-runtime-BNMv73og.cjs"),t=require("../lib-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../rolldown-runtime-BNMv73og.cjs"),t=require("../lib-CZJJRJq3.cjs");let n=require("js-bao-wss-client"),r=require("node:fs"),i=require("node:path");i=e.i(i,1);let a=require("vitest");var o=`000000`;function s(e,t,n){if(e)return e;throw Error(`[primitive-app/testing] Missing ${t}: pass it to registerPrimitiveTests() or set the ${n} environment variable.`)}function c(){let e=i.default.resolve(process.cwd(),`public/sql-wasm.wasm`);if(!(0,r.existsSync)(e)){console.warn(`[primitive-app/testing] ${e} not found — using the client's default database config. If client init fails to load sql-wasm.wasm, pass clientOptions.databaseConfig explicitly.`);return}return{type:`sqljs`,options:{locateFile:()=>e}}}async function l(e){let t=[],n=[];for(let[r,i]of Object.entries(e))try{let e=(await i())?.default;Array.isArray(e)?t.push(...e):e&&typeof e==`object`&&`tests`in e?t.push(e):n.push({file:r,error:Error(`Default export is not a TestGroup (expected { name, tests }).`)})}catch(e){n.push({file:r,error:e})}return{groups:t,failures:n}}async function u(e){let{models:r,testModules:i,otpCode:u=o,testTimeoutMs:d=6e4,clientOptions:f,cleanupTestDocuments:p=!0,failBelowFullScore:m=!0}=e,h=s(e.appId??process.env.VITE_APP_ID,`appId`,`VITE_APP_ID`),g=s(e.apiUrl??process.env.VITE_API_URL,`apiUrl`,`VITE_API_URL`),_=s(e.wsUrl??process.env.VITE_WS_URL,`wsUrl`,`VITE_WS_URL`),v=s(e.email??process.env.PRIMITIVE_TEST_EMAIL,`email`,`PRIMITIVE_TEST_EMAIL`),{groups:y,failures:b}=await l(i);for(let e of b)(0,a.describe)(e.file,()=>{(0,a.it)(`loads without errors`,()=>{throw e.error instanceof Error?e.error:Error(String(e.error))})});if(y.length===0){b.length===0&&console.warn(`[primitive-app/testing] No *.primitive-test.ts groups found — nothing to register.`);return}let x;(0,a.beforeAll)(async()=>{x=await(0,n.initializeClient)({apiUrl:g,wsUrl:_,appId:h,models:r,storageConfig:{type:`auto`},databaseConfig:c(),...f});try{await x.otpVerify(v,u)}catch(e){throw Error(`[primitive-app/testing] OTP sign-in failed for ${v}. The test bypass requires the app's testAccountBaseEmails whitelist to cover this address (and invite-only/domain/waitlist apps reject provisioning like any signup). Underlying error: ${e instanceof Error?e.message:String(e)}`)}t.s.initialize({apiUrl:g,wsUrl:_,appId:h,models:r,oauthRedirectUri:f?.oauthRedirectUri??process.env.VITE_OAUTH_REDIRECT_URI??`http://localhost/oauth/callback-unused-in-node-tests`,...f}),t.s.setExternalClient(x)},12e4),(0,a.afterAll)(async()=>{if(x){if(p)try{await t.r()}catch(e){console.warn(`[primitive-app/testing] Test-document cleanup failed:`,e)}await x.disconnect()}},6e4);for(let e of y)(0,a.describe)(e.name,()=>{for(let t of e.tests){if((t.environment??e.environment)===`browser`){a.it.skip(t.name,()=>{});continue}(0,a.it)(t.name,async()=>{let e=await t.run(e=>console.log(`[${t.id}] ${e}`));e&&console.log(`[${t.id}] ${e}`);let n=e?.match(/^(\d+)\/(\d+)\s*\((\d+(?:\.\d+)?)%\)/);if(m&&n&&Number(n[1])!==Number(n[2]))throw Error(`Scored below full marks: ${e}`)},d)}})}exports.PRIMITIVE_TEST_OTP_CODE=o,exports.registerPrimitiveTests=u;
|
package/dist/testing/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { r as e, s as t } from "../lib-SnRn0TGH.js";
|
|
2
2
|
import { initializeClient as n } from "js-bao-wss-client";
|
|
3
3
|
import { existsSync as r } from "node:fs";
|
|
4
4
|
import i from "node:path";
|
|
@@ -66,18 +66,18 @@ async function p(r) {
|
|
|
66
66
|
} catch (e) {
|
|
67
67
|
throw Error(`[primitive-app/testing] OTP sign-in failed for ${S}. The test bypass requires the app's testAccountBaseEmails whitelist to cover this address (and invite-only/domain/waitlist apps reject provisioning like any signup). Underlying error: ${e instanceof Error ? e.message : String(e)}`);
|
|
68
68
|
}
|
|
69
|
-
|
|
69
|
+
t.initialize({
|
|
70
70
|
apiUrl: b,
|
|
71
71
|
wsUrl: x,
|
|
72
72
|
appId: y,
|
|
73
73
|
models: i,
|
|
74
74
|
oauthRedirectUri: g?.oauthRedirectUri ?? process.env.VITE_OAUTH_REDIRECT_URI ?? "http://localhost/oauth/callback-unused-in-node-tests",
|
|
75
75
|
...g
|
|
76
|
-
}),
|
|
76
|
+
}), t.setExternalClient(T);
|
|
77
77
|
}, 12e4), a(async () => {
|
|
78
78
|
if (T) {
|
|
79
79
|
if (_) try {
|
|
80
|
-
await
|
|
80
|
+
await e();
|
|
81
81
|
} catch (e) {
|
|
82
82
|
console.warn("[primitive-app/testing] Test-document cleanup failed:", e);
|
|
83
83
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "primitive-app",
|
|
3
|
-
"version": "3.2.0-alpha.
|
|
3
|
+
"version": "3.2.0-alpha.20",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"author": "Primitive LLC",
|
|
6
6
|
"type": "module",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"dev": "vite",
|
|
43
43
|
"build": "pnpm codegen && run-p type-check \"build-only {@}\" -- && pnpm build:dts",
|
|
44
44
|
"preview": "vite preview",
|
|
45
|
+
"test": "vitest run",
|
|
45
46
|
"clean": "rm -rf dist && pnpm clean-modules",
|
|
46
47
|
"clean-modules": "rm -rf node_modules pnpm-lock.yaml",
|
|
47
48
|
"build-only": "vite build",
|
|
@@ -109,7 +110,7 @@
|
|
|
109
110
|
"eslint-plugin-vue": "~10.9.2",
|
|
110
111
|
"jiti": "^2.7.0",
|
|
111
112
|
"js-bao": "^0.5.1",
|
|
112
|
-
"js-bao-wss-client": "^
|
|
113
|
+
"js-bao-wss-client": "^3.0.0",
|
|
113
114
|
"npm-run-all2": "^9.0.2",
|
|
114
115
|
"pinia": "^3.0.4",
|
|
115
116
|
"prettier": "3.9.4",
|
package/src/style.css
CHANGED
|
@@ -83,7 +83,13 @@
|
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
/*
|
|
87
|
+
* The platform palette. The dev tools (`.primitive-devtools`) declare it on
|
|
88
|
+
* their own scope too, so a host that re-themes these tokens in `:root` keeps
|
|
89
|
+
* its theme out of the overlay.
|
|
90
|
+
*/
|
|
91
|
+
:root,
|
|
92
|
+
.primitive-devtools {
|
|
87
93
|
--radius: 0.625rem;
|
|
88
94
|
--background: oklch(1 0 0);
|
|
89
95
|
--foreground: oklch(0.129 0.042 264.695);
|
|
@@ -119,7 +125,8 @@
|
|
|
119
125
|
--sidebar-ring: oklch(0.704 0.04 256.788);
|
|
120
126
|
}
|
|
121
127
|
|
|
122
|
-
.dark
|
|
128
|
+
.dark,
|
|
129
|
+
.dark .primitive-devtools {
|
|
123
130
|
--background: oklch(0.129 0.042 264.695);
|
|
124
131
|
--foreground: oklch(0.984 0.003 247.858);
|
|
125
132
|
--card: oklch(0.129 0.042 264.695);
|
|
@@ -154,6 +161,182 @@
|
|
|
154
161
|
--sidebar-ring: oklch(0.446 0.043 257.281);
|
|
155
162
|
}
|
|
156
163
|
|
|
164
|
+
/* The dev tools' own type: Tailwind's default stacks, whatever the host sets. */
|
|
165
|
+
.primitive-devtools {
|
|
166
|
+
--font-sans:
|
|
167
|
+
ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
|
|
168
|
+
"Segoe UI Symbol", "Noto Color Emoji";
|
|
169
|
+
--font-mono:
|
|
170
|
+
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
|
|
171
|
+
"Courier New", monospace;
|
|
172
|
+
font-family: var(--font-sans);
|
|
173
|
+
line-height: 1.5;
|
|
174
|
+
color: var(--foreground);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/*
|
|
178
|
+
* The Tailwind theme the dev tools' utilities read. The host's Tailwind build
|
|
179
|
+
* compiles those utilities, so a host `@theme` that redefines a key
|
|
180
|
+
* (`--color-background`, `--spacing`, `--text-sm`) would otherwise restyle the
|
|
181
|
+
* overlay; inside the scope each key is primitive-app's value, or Tailwind's
|
|
182
|
+
* default, again. Tailwind writes some keys into the classes at build time
|
|
183
|
+
* (breakpoints, shadows, tw-animate's easing and duration, and any key a host
|
|
184
|
+
* declares `@theme inline`), out of a scope's reach.
|
|
185
|
+
* tests/devtools-theme-isolation-3938.test.ts (this package) fails when a
|
|
186
|
+
* dev-tools class starts reading a key missing here.
|
|
187
|
+
*/
|
|
188
|
+
.primitive-devtools {
|
|
189
|
+
--color-background: var(--background);
|
|
190
|
+
--color-foreground: var(--foreground);
|
|
191
|
+
--color-card: var(--card);
|
|
192
|
+
--color-card-foreground: var(--card-foreground);
|
|
193
|
+
--color-popover: var(--popover);
|
|
194
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
195
|
+
--color-primary: var(--primary);
|
|
196
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
197
|
+
--color-secondary: var(--secondary);
|
|
198
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
199
|
+
--color-muted: var(--muted);
|
|
200
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
201
|
+
--color-accent: var(--accent);
|
|
202
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
203
|
+
--color-destructive: var(--destructive);
|
|
204
|
+
--color-destructive-foreground: var(--destructive-foreground);
|
|
205
|
+
--color-border: var(--border);
|
|
206
|
+
--color-input: var(--input);
|
|
207
|
+
--color-ring: var(--ring);
|
|
208
|
+
--color-black: #000;
|
|
209
|
+
--color-white: #fff;
|
|
210
|
+
--color-red-100: oklch(93.6% 0.032 17.717);
|
|
211
|
+
--color-red-500: oklch(63.7% 0.237 25.331);
|
|
212
|
+
--color-red-600: oklch(57.7% 0.245 27.325);
|
|
213
|
+
--color-red-700: oklch(50.5% 0.213 27.518);
|
|
214
|
+
--color-orange-500: oklch(70.5% 0.213 47.604);
|
|
215
|
+
--color-amber-500: oklch(76.9% 0.188 70.08);
|
|
216
|
+
--color-amber-600: oklch(66.6% 0.179 58.318);
|
|
217
|
+
--color-green-100: oklch(96.2% 0.044 156.743);
|
|
218
|
+
--color-green-500: oklch(72.3% 0.219 149.579);
|
|
219
|
+
--color-green-600: oklch(62.7% 0.194 149.214);
|
|
220
|
+
--color-green-700: oklch(52.7% 0.154 150.069);
|
|
221
|
+
--color-teal-500: oklch(70.4% 0.14 182.503);
|
|
222
|
+
--color-blue-100: oklch(93.2% 0.032 255.585);
|
|
223
|
+
--color-blue-500: oklch(62.3% 0.214 259.815);
|
|
224
|
+
--color-blue-600: oklch(54.6% 0.245 262.881);
|
|
225
|
+
--color-blue-700: oklch(48.8% 0.243 264.376);
|
|
226
|
+
--color-indigo-500: oklch(58.5% 0.233 277.117);
|
|
227
|
+
--color-indigo-600: oklch(51.1% 0.262 276.966);
|
|
228
|
+
--color-purple-500: oklch(62.7% 0.265 303.9);
|
|
229
|
+
--color-pink-500: oklch(65.6% 0.241 354.308);
|
|
230
|
+
--radius-xs: 0.125rem;
|
|
231
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
232
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
233
|
+
--radius-lg: var(--radius);
|
|
234
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
235
|
+
--spacing: 0.25rem;
|
|
236
|
+
/*
|
|
237
|
+
* A host `@theme` may add a step to the spacing scale (`--spacing-10`), and
|
|
238
|
+
* Tailwind then compiles `w-10`, `px-4`, `top-1/2`, `max-w-lg` and
|
|
239
|
+
* `leading-none` to read it. Each step the dev tools' classes use is held
|
|
240
|
+
* here at the value that class has without it. Decimal steps are looked up
|
|
241
|
+
* under both spellings (`--spacing-1\.5`, `--spacing-1_5`).
|
|
242
|
+
*/
|
|
243
|
+
--spacing-0: 0;
|
|
244
|
+
--spacing-0\.5: calc(var(--spacing) * 0.5);
|
|
245
|
+
--spacing-0_5: calc(var(--spacing) * 0.5);
|
|
246
|
+
--spacing-1: calc(var(--spacing) * 1);
|
|
247
|
+
--spacing-1\.5: calc(var(--spacing) * 1.5);
|
|
248
|
+
--spacing-1_5: calc(var(--spacing) * 1.5);
|
|
249
|
+
--spacing-2: calc(var(--spacing) * 2);
|
|
250
|
+
--spacing-2\.5: calc(var(--spacing) * 2.5);
|
|
251
|
+
--spacing-2_5: calc(var(--spacing) * 2.5);
|
|
252
|
+
--spacing-3: calc(var(--spacing) * 3);
|
|
253
|
+
--spacing-3\.5: calc(var(--spacing) * 3.5);
|
|
254
|
+
--spacing-3_5: calc(var(--spacing) * 3.5);
|
|
255
|
+
--spacing-4: calc(var(--spacing) * 4);
|
|
256
|
+
--spacing-5: calc(var(--spacing) * 5);
|
|
257
|
+
--spacing-6: calc(var(--spacing) * 6);
|
|
258
|
+
--spacing-7: calc(var(--spacing) * 7);
|
|
259
|
+
--spacing-8: calc(var(--spacing) * 8);
|
|
260
|
+
--spacing-9: calc(var(--spacing) * 9);
|
|
261
|
+
--spacing-10: calc(var(--spacing) * 10);
|
|
262
|
+
--spacing-12: calc(var(--spacing) * 12);
|
|
263
|
+
--spacing-16: calc(var(--spacing) * 16);
|
|
264
|
+
--spacing-20: calc(var(--spacing) * 20);
|
|
265
|
+
--spacing-24: calc(var(--spacing) * 24);
|
|
266
|
+
--spacing-28: calc(var(--spacing) * 28);
|
|
267
|
+
--spacing-32: calc(var(--spacing) * 32);
|
|
268
|
+
--spacing-40: calc(var(--spacing) * 40);
|
|
269
|
+
--spacing-44: calc(var(--spacing) * 44);
|
|
270
|
+
--spacing-48: calc(var(--spacing) * 48);
|
|
271
|
+
--spacing-56: calc(var(--spacing) * 56);
|
|
272
|
+
--spacing-64: calc(var(--spacing) * 64);
|
|
273
|
+
--spacing-72: calc(var(--spacing) * 72);
|
|
274
|
+
--spacing-80: calc(var(--spacing) * 80);
|
|
275
|
+
--spacing-96: calc(var(--spacing) * 96);
|
|
276
|
+
--spacing-1\/2: calc(1 / 2 * 100%);
|
|
277
|
+
--spacing-3\/4: calc(3 / 4 * 100%);
|
|
278
|
+
--spacing-px: 1px;
|
|
279
|
+
--spacing-auto: auto;
|
|
280
|
+
--spacing-fit: fit-content;
|
|
281
|
+
--spacing-full: 100%;
|
|
282
|
+
--spacing-none: 1;
|
|
283
|
+
--spacing-xs: var(--container-xs);
|
|
284
|
+
--spacing-sm: var(--container-sm);
|
|
285
|
+
--spacing-md: var(--container-md);
|
|
286
|
+
--spacing-lg: var(--container-lg);
|
|
287
|
+
--spacing-4xl: var(--container-4xl);
|
|
288
|
+
--spacing-screen-lg: var(--breakpoint-lg);
|
|
289
|
+
--container-xs: 20rem;
|
|
290
|
+
--container-sm: 24rem;
|
|
291
|
+
--container-md: 28rem;
|
|
292
|
+
--container-lg: 32rem;
|
|
293
|
+
--container-4xl: 56rem;
|
|
294
|
+
--breakpoint-lg: 64rem;
|
|
295
|
+
--text-xs: 0.75rem;
|
|
296
|
+
--text-xs--line-height: calc(1 / 0.75);
|
|
297
|
+
--text-sm: 0.875rem;
|
|
298
|
+
--text-sm--line-height: calc(1.25 / 0.875);
|
|
299
|
+
--text-base: 1rem;
|
|
300
|
+
--text-base--line-height: calc(1.5 / 1);
|
|
301
|
+
--text-lg: 1.125rem;
|
|
302
|
+
--text-lg--line-height: calc(1.75 / 1.125);
|
|
303
|
+
--font-weight-normal: 400;
|
|
304
|
+
--font-weight-medium: 500;
|
|
305
|
+
--font-weight-semibold: 600;
|
|
306
|
+
--font-weight-bold: 700;
|
|
307
|
+
--tracking-wide: 0.025em;
|
|
308
|
+
--tracking-widest: 0.1em;
|
|
309
|
+
--leading-relaxed: 1.625;
|
|
310
|
+
--ease-out: cubic-bezier(0, 0, 0.2, 1);
|
|
311
|
+
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
|
312
|
+
--animate-spin: spin 1s linear infinite;
|
|
313
|
+
--animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
314
|
+
--blur: 8px;
|
|
315
|
+
--blur-sm: 8px;
|
|
316
|
+
--aspect-video: 16 / 9;
|
|
317
|
+
--default-transition-duration: 150ms;
|
|
318
|
+
--default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/*
|
|
322
|
+
* A host's base rules aimed at elements (`button { font-family: … }`) reach
|
|
323
|
+
* the dev tools' controls directly, not through the scope. Inside it every
|
|
324
|
+
* element takes its type from its parent instead (code stays monospace). This
|
|
325
|
+
* sits in the base layer, so utilities such as `font-mono` still apply.
|
|
326
|
+
*/
|
|
327
|
+
@layer base {
|
|
328
|
+
.primitive-devtools * {
|
|
329
|
+
font-family: inherit;
|
|
330
|
+
letter-spacing: inherit;
|
|
331
|
+
}
|
|
332
|
+
.primitive-devtools code,
|
|
333
|
+
.primitive-devtools kbd,
|
|
334
|
+
.primitive-devtools samp,
|
|
335
|
+
.primitive-devtools pre {
|
|
336
|
+
font-family: var(--font-mono);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
157
340
|
@layer base {
|
|
158
341
|
* {
|
|
159
342
|
@apply border-border outline-ring/50;
|
package/dist/lib-CFnieS8T.cjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
let e=require("js-bao-wss-client");var t={debug:0,info:1,warn:2,error:3,none:4},n=`warn`,r=class e{#e;scope;constructor(e,t){this.#e=e,this.scope=t}get level(){return this.#e.level}set level(e){this.setLevel(e)}debug(...e){this.#t(`debug`,e)}log(...e){this.#t(`info`,e,`log`)}warn(...e){this.#t(`warn`,e)}error(...e){this.#t(`error`,e)}shouldLog(e){return t[e]>=t[this.level]}getLevel(){return this.level}setLevel(e){e in t&&(this.#e.level=e)}forScope(t){let n=t.trim(),r=n?[...this.scope,n]:this.scope;return new e(this.#e,r)}#t(e,t,n){if(!this.shouldLog(e))return;let r=n??(e===`info`?`log`:e),i=this.scope.length?`[${this.scope.join(`:`)}]`:void 0,a=i?[i,...t]:t;console[r](...a)}},i={level:n},a=new r(i,[]).forScope(`PrimitiveApp`);function o(e){i.level=e}var s=a.forScope(`JsBaoClientService`);function c(){if(typeof window>`u`)return!1;let e=window.location.hostname;return e===`localhost`||e===`127.0.0.1`||e===`[::1]`||e.endsWith(`.localhost`)||e.endsWith(`.local`)}var l=new class{client=null;clientInitializationPromise=null;config=null;initialize(e){s.debug(`Initializing with config:`,{appId:e.appId?`${e.appId.substring(0,10)}...`:`MISSING`,apiUrl:e.apiUrl,wsUrl:e.wsUrl,oauthRedirectUri:e.oauthRedirectUri});let t=[];(!e.appId||e.appId===`MISSING_APP_ID`)&&t.push(`appId`),(!e.apiUrl||e.apiUrl===`MISSING_API_URL`)&&t.push(`apiUrl`),(!e.wsUrl||e.wsUrl===`MISSING_WS_URL`)&&t.push(`wsUrl`),(!e.oauthRedirectUri||e.oauthRedirectUri===`MISSING_OAUTH_REDIRECT_URI`)&&t.push(`oauthRedirectUri`),t.length>0&&(s.error(`❌ Configuration validation failed!`),s.error(`Missing or invalid fields:`,t),s.error(`This will cause OAuth and API calls to fail.`),s.error(`Identity (appId/apiUrl/wsUrl) comes from .primitive/config.json via the primitiveEnv() Vite plugin — check that the project has one and that an environment is selected ('primitive env use <name>'). Callback and logging settings come from your .env files.`)),this.config=e}getConfig(){return this.config}async getClientAsync(){if(s.debug(`Getting client async`),this.clientInitializationPromise)return this.clientInitializationPromise;if(!this.config)throw Error(`JsBaoClientService not initialized. Call initialize() first.`);return this.clientInitializationPromise=(async()=>{s.debug(`=== INITIALIZING CLIENT ===`),s.debug(`Configuration:`,this.config);let t=await(0,e.initializeClient)(this.config);if(t.on(`status`,e=>{s.debug(`Client status changed:`,e)}),t.on(`error`,e=>{s.error(`Client error:`,e)}),this.client=t,c()&&(window.__primitiveAppClient=t,this.config?.models&&Array.isArray(this.config.models))){let e={};for(let t of this.config.models){let n=t.schema?.name;if(n){let r=n.charAt(0).toUpperCase()+n.slice(1);e[r]=t}}window.__primitiveAppModels=e,s.debug(`Registered models on window:`,Object.keys(e))}return s.debug(`=== CLIENT INITIALIZATION COMPLETE ===`),t})(),this.clientInitializationPromise}setExternalClient(e){s.debug(`Setting external client from host app`),this.client=e,this.clientInitializationPromise=Promise.resolve(e)}async clearClient(){s.debug(`Clearing client singleton...`),this.client&&(this.client.disconnect().catch(e=>{s.warn(`Background disconnect failed (this is usually harmless):`,e)}),this.client=null,this.clientInitializationPromise=null,c()&&(window.__primitiveAppClient=void 0,window.__primitiveAppModels=void 0))}};function u(e){l.initialize(e)}var d=a.forScope(`TestHarness`),f=`===TEST===`;async function p(e={}){let{networkSync:t=!1}=e,n=await l.getClientAsync(),r=`${f} ${`${Date.now()}-${Math.random().toString(36).substring(2,11)}`}`;if(t){let{metadata:e}=await n.documents.create({title:r}),t=e.documentId,{doc:i}=await n.documents.open(t);if(!i)throw Error(`[TestHarness] Failed to open synced test document`);return n.setDefaultDocumentId(t),d.debug(`Created synced test document`,{docId:t}),m.set(t,{client:n,docId:t,networkSync:!0}),{docId:t}}let{metadata:i}=await n.documents.create({title:r,localOnly:!0}),a=i.documentId,{doc:o}=await n.documents.open(a,{waitForLoad:`local`,enableNetworkSync:!1});if(!o)throw Error(`[TestHarness] Failed to open test document`);return n.setDefaultDocumentId(a),d.debug(`Created test document`,{docId:a}),m.set(a,{client:n,docId:a,networkSync:!1}),{docId:a}}var m=new Map;async function h(e){let t=m.get(e.docId);if(!t){d.warn(`destroyTestDocument called with unknown handle`,{docId:e.docId});return}m.delete(e.docId);try{t.networkSync?await t.client.documents.delete(t.docId,{forceCloseIfOpen:!0}):(await t.client.documents.close(t.docId),await t.client.documents.evict(t.docId,{force:!0}))}catch(e){d.error(`Failed to destroy test document`,{docId:t.docId,err:e})}}async function g(){try{let e=await l.getClientAsync();d.debug(`[deleteAllTestDocuments] Starting cleanup...`),await e.syncMetadata({scope:`all`});let t=(await e.me.ownedDocuments()).filter(e=>e.title?.startsWith(f));if(t.length===0)return 0;d.debug(`[deleteAllTestDocuments] Found test documents to delete`,{count:t.length});let n=0;for(let r of t)try{e.documents.isOpen(r.documentId)&&await e.documents.close(r.documentId),await e.documents.evict(r.documentId,{force:!0}),n++}catch(e){d.error(`[deleteAllTestDocuments] Failed to delete test document`,{documentId:r.documentId,err:e})}return d.debug(`[deleteAllTestDocuments] Cleanup complete`,{evictedCount:n}),n}catch(e){return d.error(`[deleteAllTestDocuments] Top-level error during cleanup`,{err:e}),0}}function _(e){return e.flatMap(e=>e.tests.map(t=>({id:t.id,name:t.name,group:e.name,environment:t.environment??e.environment,run:t.run})))}Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,"c",{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return _}});
|