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.
@@ -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 .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;
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
- async clearClient() {
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 d = a.forScope("TestHarness"), f = "===TEST===";
119
- async function p(e = {}) {
120
- let { networkSync: t = !1 } = e, n = await l.getClientAsync(), r = `${f} ${`${Date.now()}-${Math.random().toString(36).substring(2, 11)}`}`;
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), d.debug("Created synced test document", { docId: t }), m.set(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), d.debug("Created test document", { docId: a }), m.set(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 m = /* @__PURE__ */ new Map();
145
- async function h(e) {
146
- let t = m.get(e.docId);
216
+ var b = /* @__PURE__ */ new Map();
217
+ async function x(e) {
218
+ let t = b.get(e.docId);
147
219
  if (!t) {
148
- d.warn("destroyTestDocument called with unknown handle", { docId: e.docId });
220
+ _.warn("destroyTestDocument called with unknown handle", { docId: e.docId });
149
221
  return;
150
222
  }
151
- m.delete(e.docId);
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
- d.error("Failed to destroy test document", {
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 g() {
233
+ async function S() {
162
234
  try {
163
235
  let e = await l.getClientAsync();
164
- d.debug("[deleteAllTestDocuments] Starting cleanup..."), await e.syncMetadata({ scope: "all" });
165
- let t = (await e.me.ownedDocuments()).filter((e) => e.title?.startsWith(f));
166
- if (t.length === 0) return 0;
167
- d.debug("[deleteAllTestDocuments] Found test documents to delete", { count: t.length });
168
- let n = 0;
169
- for (let r of t) try {
170
- e.documents.isOpen(r.documentId) && await e.documents.close(r.documentId), await e.documents.evict(r.documentId, { force: !0 }), n++;
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
- d.error("[deleteAllTestDocuments] Failed to delete test document", {
173
- documentId: r.documentId,
244
+ _.error("[deleteAllTestDocuments] Failed to delete test document", {
245
+ documentId: t.documentId,
174
246
  err: e
175
247
  });
176
248
  }
177
- return d.debug("[deleteAllTestDocuments] Cleanup complete", { evictedCount: n }), n;
249
+ return _.debug("[deleteAllTestDocuments] Cleanup complete", { evictedCount: r }), r;
178
250
  } catch (e) {
179
- return d.error("[deleteAllTestDocuments] Top-level error during cleanup", { err: e }), 0;
251
+ return _.error("[deleteAllTestDocuments] Top-level error during cleanup", { err: e }), 0;
180
252
  }
181
253
  }
182
- function _(e) {
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 { u as a, o as c, h as i, p as n, l as o, g as r, a as s, _ as t };
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 };
@@ -1,2 +1,2 @@
1
- [data-v-0ba29a35] tr[data-slot=table-row]{border-bottom-width:0}[data-v-0ba29a35] th[data-slot=table-head],[data-v-0ba29a35] 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)}
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
- * `.primitive/config.json` — the one place a backend URL and app ID are typed.
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
  }
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../rolldown-runtime-BNMv73og.cjs"),t=require("../lib-CFnieS8T.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.o.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.o.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;
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;
@@ -1,4 +1,4 @@
1
- import { o as e, r as t } from "../lib-B7ZH2Pdd.js";
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
- e.initialize({
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
- }), e.setExternalClient(T);
76
+ }), t.setExternalClient(T);
77
77
  }, 12e4), a(async () => {
78
78
  if (T) {
79
79
  if (_) try {
80
- await t();
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.2",
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": "^2.0.4",
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
- :root {
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;
@@ -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 _}});