@glasshome/widget-sdk 1.8.1 → 1.9.1

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/ui.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Host UI primitives, re-exported so the SDK is the single gated door.
3
+ *
4
+ * The host serves `@glasshome/ui/solid` through its import map with no compat
5
+ * check of its own, so a widget importing it directly is exposed to ui drift
6
+ * across the Hub auto-update boundary. Routed through here, the same
7
+ * primitives sit behind `sdkVersion` — the one contract `checkSdkCompat`
8
+ * enforces (same model as the sync-layer hooks).
9
+ *
10
+ * The set is exactly what shipped widgets use; extending it is an additive
11
+ * SDK minor. Direct `@glasshome/ui` imports keep working but are deprecated
12
+ * (`direct-ui-import` in the registry), removed in 2.0.0.
13
+ *
14
+ * `@glasshome/ui/solid` is a vite external of this package: these re-exports
15
+ * resolve to the host-provided singleton at runtime, never a bundled copy.
16
+ */
17
+ export { Badge, Button, type Color, ColorSlider, ColorWheel, Input, Label, parseColor, ResponsiveDialog, ResponsiveDialogContent, ResponsiveDialogDescription, ResponsiveDialogHeader, ResponsiveDialogTitle, SchemaForm, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Slider, Switch, } from "@glasshome/ui/solid";
@@ -11,18 +11,6 @@ export interface GlasshomeWidgetOptions {
11
11
  * author decide which states matter rather than discovering the loss never.
12
12
  */
13
13
  export declare const MAX_EXAMPLES = 20;
14
- /**
15
- * Configuration-drift guard (D-11). Reads the built bundle, derives the JSON
16
- * Schema from its configSchema, and compares against the recorded
17
- * `.schema-hash`. A shape change without a configVersion bump fails the build:
18
- * tsc cannot catch this class of break because the old persisted config still
19
- * parses, only its meaning shifts. Legacy plain-hash records (written by
20
- * pre-1.7 builds) cannot prove a missing bump, so they only warn, then upgrade
21
- * to the JSON record format.
22
- *
23
- * When `manifestPath` is given (single-widget projects), the generated JSON
24
- * Schema is also written into `manifest.json` as `schema`.
25
- */
26
14
  export declare function runSchemaGuard(args: {
27
15
  outFile: string;
28
16
  hashFile: string;
@@ -37,6 +25,30 @@ export declare function runSchemaGuard(args: {
37
25
  * must be bundled, because leaving it external is a runtime 404.
38
26
  */
39
27
  export declare function isWidgetExternal(id: string): boolean;
28
+ /**
29
+ * True when a widget source file imports `@glasshome/ui` directly. The regex is
30
+ * the registry's `sourcePattern` for `direct-ui-import`, so the build warning and
31
+ * the widget-cli lint can never disagree on what counts as a direct import.
32
+ * node_modules is excluded: dependencies and the SDK's own generated entries in
33
+ * BUILD_CACHE_DIR (the theme `@import`) are the SDK's business, not the widget's.
34
+ */
35
+ export declare function isDirectUiImportSource(id: string, code: string): boolean;
36
+ /**
37
+ * Warns (never fails) when widget source imports @glasshome/ui directly.
38
+ * Warn-only counterpart to syncLayerImportGuard: direct imports keep working
39
+ * until 2.0, but they bypass the sdkVersion gate, so ui can drift against
40
+ * published widgets with nothing checking compatibility. Detection scans
41
+ * module source in `transform` because externalized specifiers never reach
42
+ * `resolveId` (rollup consults `external` for the bare id first).
43
+ *
44
+ * `warned` carries the files already reported across every build in one run, so
45
+ * a module shared by N widgets is named once and not once per bundle it lands in.
46
+ */
47
+ export declare function createUiImportTracker(warned?: Set<string>): {
48
+ scan(id: string, code: string): void;
49
+ /** Offending files this run has not reported yet; marks them reported. */
50
+ take(): string[];
51
+ };
40
52
  interface DiscoveredWidget {
41
53
  name: string;
42
54
  entry: string;
@@ -1,18 +1,19 @@
1
- import { formatSchemaError as e, isHostProvidedModule as t, widgetManifestSchema as n } from "@glasshome/widget-contract";
2
- import { spawnSync as r } from "node:child_process";
3
- import { createHash as i } from "node:crypto";
4
- import { existsSync as a, mkdirSync as o, readFileSync as s, readdirSync as c, rmSync as l, statSync as u, writeFileSync as d } from "node:fs";
5
- import { createRequire as f } from "node:module";
6
- import { dirname as p, join as m, resolve as h, sep as g } from "node:path";
7
- import { fileURLToPath as _ } from "node:url";
8
- import v from "@tailwindcss/vite";
1
+ import { deprecations as e, formatDeprecation as t } from "../deprecations.js";
2
+ import { formatSchemaError as n, isHostProvidedModule as r, widgetManifestSchema as i } from "@glasshome/widget-contract";
3
+ import { spawnSync as a } from "node:child_process";
4
+ import { createHash as o } from "node:crypto";
5
+ import { existsSync as s, mkdirSync as c, readFileSync as l, readdirSync as u, rmSync as d, statSync as f, writeFileSync as p } from "node:fs";
6
+ import { createRequire as m } from "node:module";
7
+ import { dirname as h, join as g, relative as _, resolve as v, sep as y } from "node:path";
8
+ import { fileURLToPath as b } from "node:url";
9
+ import x from "@tailwindcss/vite";
9
10
  //#region src/vite/index.ts
10
- function y(e) {
11
+ function S(e) {
11
12
  let t = JSON.stringify(e, Object.keys(e).sort());
12
- return i("sha256").update(t).digest("hex").slice(0, 16);
13
+ return o("sha256").update(t).digest("hex").slice(0, 16);
13
14
  }
14
- var b = 20;
15
- async function x(e, t) {
15
+ var C = 20;
16
+ async function w(e, t) {
16
17
  if (e === void 0) return;
17
18
  let n;
18
19
  try {
@@ -32,13 +33,21 @@ async function x(e, t) {
32
33
  let a = i.error.issues.map((e) => ` examples${e.path.length ? `[${e.path.join("][")}]` : ""}: ${e.message}`).join("\n");
33
34
  throw Error(`[widget-sdk] Invalid \`examples\` for "${t}":\n${a}\nEach example needs a \`config\` object and a \`size\` of whole positive tiles, and at most 20 are rendered.`);
34
35
  }
35
- function S(e) {
36
- let t = p(_(import.meta.url)), n = [m(t, "introspect.js"), m(t, "introspect.ts")].find((e) => a(e));
36
+ function T(e, t) {
37
+ if (!e?.length) return;
38
+ let n = e.map((e) => {
39
+ let t = e.label ? `"${e.label}"` : `#${e.index}`;
40
+ return [` examples[${e.index}] ${t}:`, ...e.problems.map((e) => ` ${e}`)].join("\n");
41
+ }).join("\n");
42
+ throw Error(`[widget-sdk] Example config rejected by "${t}"'s own configSchema:\n${n}\nEach example's \`config\` must be a config the widget would actually accept, or its preview renders empty.`);
43
+ }
44
+ function E(e) {
45
+ let t = h(b(import.meta.url)), n = [g(t, "introspect.js"), g(t, "introspect.ts")].find((e) => s(e));
37
46
  if (!n) return {
38
47
  ok: !1,
39
48
  reason: `introspect not found next to ${t}`
40
49
  };
41
- let i = r(process.execPath, [
50
+ let r = a(process.execPath, [
42
51
  "--conditions",
43
52
  "browser",
44
53
  n,
@@ -47,18 +56,18 @@ function S(e) {
47
56
  encoding: "utf-8",
48
57
  timeout: 3e4
49
58
  });
50
- if (i.error) return {
59
+ if (r.error) return {
51
60
  ok: !1,
52
- reason: i.error.message
61
+ reason: r.error.message
53
62
  };
54
- if (i.status !== 0) return {
63
+ if (r.status !== 0) return {
55
64
  ok: !1,
56
- reason: (i.stderr || "").trim().split("\n")[0] || `exit ${i.status}`
65
+ reason: (r.stderr || "").trim().split("\n")[0] || `exit ${r.status}`
57
66
  };
58
67
  try {
59
68
  return {
60
69
  ok: !0,
61
- value: JSON.parse(i.stdout)
70
+ value: JSON.parse(r.stdout)
62
71
  };
63
72
  } catch {
64
73
  return {
@@ -67,49 +76,60 @@ function S(e) {
67
76
  };
68
77
  }
69
78
  }
70
- async function C(e) {
71
- if (!a(e.outFile)) return;
72
- let t = S(e.outFile);
73
- if (!t.ok) {
74
- console.warn(`[widget-sdk] Could not read "${e.widgetName}" to check it: ${t.reason}\n Its examples and config schema were NOT validated.`);
75
- return;
76
- }
77
- let n = t.value;
78
- await x(n.manifest?.examples, n.manifest?.name ?? e.widgetName);
79
- let r = n.jsonSchema;
80
- if (!r) return;
81
- if (e.manifestPath && a(e.manifestPath)) {
82
- let t = JSON.parse(s(e.manifestPath, "utf-8"));
83
- t.schema = r, d(e.manifestPath, JSON.stringify(t, null, 2));
84
- }
85
- let i = y(r), o = n.manifest?.configVersion ?? null, c = n.manifest?.name ?? e.widgetName;
86
- if (a(e.hashFile)) {
87
- let t = s(e.hashFile, "utf-8").trim(), n = null;
79
+ var D = [
80
+ "schema",
81
+ "defaultConfig",
82
+ "examples",
83
+ "configVersion"
84
+ ];
85
+ function O(e, t, n) {
86
+ let r = l(e, "utf-8"), i = JSON.parse(r), a = {
87
+ ...t.manifest ?? {},
88
+ schema: n
89
+ };
90
+ for (let e of D) a[e] !== void 0 && (i[e] = a[e]);
91
+ let o = `${JSON.stringify(i, null, 2)}\n`;
92
+ o !== r && p(e, o);
93
+ }
94
+ async function k(e) {
95
+ if (!s(e.outFile)) return;
96
+ let t = E(e.outFile);
97
+ if (!t.ok) throw Error(`[widget-sdk] Could not read "${e.widgetName}" to check it: ${t.reason}\n Its examples and config schema could not be validated, so the build cannot continue.
98
+ This usually means the bundle throws while being imported.`);
99
+ let n = t.value, r = n.manifest?.name ?? e.widgetName;
100
+ await w(n.manifest?.examples, r), T(n.exampleConfigIssues, r);
101
+ let i = n.jsonSchema;
102
+ if (!i) return;
103
+ e.manifestPath && s(e.manifestPath) && O(e.manifestPath, n, i);
104
+ let a = S(i), o = n.manifest?.configVersion ?? null, c = n.manifest?.name ?? e.widgetName;
105
+ if (s(e.hashFile)) {
106
+ let t = l(e.hashFile, "utf-8").trim(), n = null;
88
107
  if (t.startsWith("{")) try {
89
108
  n = JSON.parse(t);
90
109
  } catch {
91
110
  n = null;
92
111
  }
93
112
  if (n) {
94
- if (n.hash !== i && n.configVersion === o) throw Error(`[widget-sdk] Config schema shape changed for "${c}" without a configVersion bump. Bump configVersion in defineWidget (currently ${o ?? "unset"}) or revert the schema change, then rebuild. Recorded in ${e.hashFile}`);
95
- } else t !== i && console.warn(`[widget-sdk] Schema shape changed for "${c}" — verify configVersion was bumped`);
113
+ if (n.hash !== a && n.configVersion === o) throw Error(`[widget-sdk] Config schema shape changed for "${c}" without a configVersion bump. Bump configVersion in defineWidget (currently ${o ?? "unset"}) or revert the schema change, then rebuild. Recorded in ${e.hashFile}`);
114
+ } else t !== a && console.warn(`[widget-sdk] Schema shape changed for "${c}" — verify configVersion was bumped`);
96
115
  }
97
- d(e.hashFile, `${JSON.stringify({
98
- hash: i,
116
+ p(e.hashFile, `${JSON.stringify({
117
+ hash: a,
99
118
  configVersion: o
100
119
  })}\n`);
101
120
  }
102
- var w = "virtual:glasshome-widget", T = "\0virtual:glasshome-widget", E = "/@glasshome/preview";
103
- function D(e) {
104
- return g === "\\" ? e.split(g).join("/") : e;
121
+ var A = "virtual:glasshome-widget", j = "\0virtual:glasshome-widget", M = "/@glasshome/preview";
122
+ function N(e) {
123
+ return y === "\\" ? e.split(y).join("/") : e;
105
124
  }
106
- function O() {
107
- return h(p(_(import.meta.url)), "../../preview");
125
+ function P() {
126
+ let e = b(import.meta.url);
127
+ return v(h(e), "../../preview");
108
128
  }
109
- function k(e) {
110
- return t(e);
129
+ function F(e) {
130
+ return r(e);
111
131
  }
112
- function A() {
132
+ function I() {
113
133
  return {
114
134
  name: "glasshome-widget:sync-layer-guard",
115
135
  apply: "build",
@@ -119,15 +139,52 @@ function A() {
119
139
  }
120
140
  };
121
141
  }
122
- var j = "node_modules/.cache/glasshome-widgets";
123
- function M(e) {
142
+ var L = /\.(ts|tsx|js|jsx)$/;
143
+ function R(t, n) {
144
+ let r = N(t).split("?")[0] ?? "";
145
+ if (r.includes("/node_modules/") || !L.test(r)) return !1;
146
+ let i = e.find((e) => e.id === "direct-ui-import");
147
+ return i?.sourcePattern ? new RegExp(i.sourcePattern).test(n) : !1;
148
+ }
149
+ function z(e = /* @__PURE__ */ new Set()) {
150
+ let t = /* @__PURE__ */ new Set();
151
+ return {
152
+ scan(e, n) {
153
+ R(e, n) && t.add(N(_(process.cwd(), e.split("?")[0] ?? e)));
154
+ },
155
+ take() {
156
+ let n = [...t].filter((t) => !e.has(t));
157
+ for (let t of n) e.add(t);
158
+ return n;
159
+ }
160
+ };
161
+ }
162
+ function B(n) {
163
+ let r = z(n);
164
+ return {
165
+ name: "glasshome-widget:ui-import-guard",
166
+ apply: "build",
167
+ enforce: "pre",
168
+ transform(e, t) {
169
+ return r.scan(t, e), null;
170
+ },
171
+ buildEnd() {
172
+ let n = r.take();
173
+ if (n.length === 0) return;
174
+ let i = e.find((e) => e.id === "direct-ui-import"), a = i ? t(i) : "[@glasshome/widget-sdk] Direct @glasshome/ui imports are deprecated; import the same export from \"@glasshome/widget-sdk\".", o = n.map((e) => ` ${e}`).join("\n");
175
+ console.warn(`${a}\n Direct @glasshome/ui import(s) in:\n${o}`);
176
+ }
177
+ };
178
+ }
179
+ var V = "node_modules/.cache/glasshome-widgets";
180
+ function H(e) {
124
181
  try {
125
- return f(m(process.cwd(), "package.json")).resolve(e);
182
+ return m(g(process.cwd(), "package.json")).resolve(e);
126
183
  } catch {
127
184
  return null;
128
185
  }
129
186
  }
130
- var N = [
187
+ var U = [
131
188
  "--radius",
132
189
  "--background",
133
190
  "--foreground",
@@ -137,128 +194,131 @@ var N = [
137
194
  "--muted",
138
195
  "--accent"
139
196
  ];
140
- function P(e, t) {
141
- let n = m(e, `${t}.css`);
142
- if (!a(n)) return;
143
- let r = s(n, "utf-8");
197
+ function W(e, t) {
198
+ let n = g(e, `${t}.css`);
199
+ if (!s(n)) return;
200
+ let r = l(n, "utf-8");
144
201
  for (let e of r.matchAll(/:host[^{]*\{([^}]*)\}/g)) {
145
- let n = e[1] ?? "", r = N.find((e) => n.includes(`${e}:`));
202
+ let n = e[1] ?? "", r = U.find((e) => n.includes(`${e}:`));
146
203
  if (r) throw Error(`[glasshome-widget] "${t}.css" defines theme variable "${r}" on :host. Theme variables must inherit from the document so widgets follow the household theme — never re-scope them into the widget's shadow root.`);
147
204
  }
148
205
  }
149
- function F(e, t, n) {
150
- let r = h(e, j);
151
- o(r, { recursive: !0 });
152
- let i = M("@glasshome/ui/styles");
206
+ function G(e, t, n) {
207
+ let r = v(e, V);
208
+ c(r, { recursive: !0 });
209
+ let i = H("@glasshome/ui/styles");
153
210
  if (!i) throw Error("[widget-sdk] @glasshome/ui is required to build widgets (it provides the theme every GlassHome widget ships with). Add it to your widget's dependencies.");
154
- let s = h(p(i), "../.."), c = M("@glasshome/widget-sdk/tailwind-sources"), l = c ? p(c) : null, u = [
155
- m(s, "src"),
156
- m(s, "dist"),
157
- ...l ? [m(l, "src"), m(l, "dist")] : [],
158
- p(n)
159
- ].filter((e) => a(e)), f = h(r, `${t}.tailwind.css`);
160
- d(f, [
211
+ let a = v(h(i), "../.."), o = H("@glasshome/widget-sdk/tailwind-sources"), l = o ? h(o) : null, u = [
212
+ g(a, "src"),
213
+ g(a, "dist"),
214
+ ...l ? [g(l, "src"), g(l, "dist")] : [],
215
+ h(n)
216
+ ].filter((e) => s(e)), d = v(r, `${t}.tailwind.css`);
217
+ p(d, [
161
218
  "@import \"tailwindcss\" source(none);",
162
219
  "@import \"tw-animate-css\";",
163
220
  "@import \"@glasshome/ui/styles/theme\";",
164
- ...u.map((e) => `@source "${D(e)}";`),
221
+ ...u.map((e) => `@source "${N(e)}";`),
165
222
  "@custom-variant dark {",
166
223
  " &:is(.dark *) { @slot }",
167
224
  " :host(.dark) & { @slot }",
168
225
  "}",
169
226
  ""
170
227
  ].join("\n"));
171
- let g = h(r, `${t}.entry.ts`);
172
- return d(g, [
173
- `import "${D(f)}";`,
174
- `export { default } from "${D(n)}";`,
228
+ let f = v(r, `${t}.entry.ts`);
229
+ return p(f, [
230
+ `import "${N(d)}";`,
231
+ `export { default } from "${N(n)}";`,
175
232
  ""
176
- ].join("\n")), g;
233
+ ].join("\n")), f;
177
234
  }
178
- function I() {
179
- let e = v();
235
+ function K() {
236
+ let e = x();
180
237
  for (let t of e) t.apply ??= "build";
181
238
  return e;
182
239
  }
183
- function L(e) {
240
+ function q(e) {
184
241
  let t = [];
185
- if (!a(e)) return t;
186
- for (let n of c(e)) {
187
- let r = h(e, n);
188
- if (!u(r).isDirectory()) continue;
189
- let i = h(r, "index.tsx"), o = h(r, "manifest.json");
190
- a(i) && a(o) && t.push({
242
+ if (!s(e)) return t;
243
+ for (let n of u(e)) {
244
+ let r = v(e, n);
245
+ if (!f(r).isDirectory()) continue;
246
+ let i = v(r, "index.tsx"), a = v(r, "manifest.json");
247
+ s(i) && s(a) && t.push({
191
248
  name: n,
192
249
  entry: i
193
250
  });
194
251
  }
195
252
  return t;
196
253
  }
197
- function R(t, r) {
198
- let i = [];
199
- if (a(t)) for (let o of c(t)) {
200
- if (!u(m(t, o)).isDirectory()) continue;
201
- let c = m(t, o, "manifest.json");
202
- if (!a(c)) continue;
203
- let l = n.safeParse(JSON.parse(s(c, "utf-8")));
204
- if (!l.success) throw Error(`[registry] Invalid manifest for "${o}": ${e(l.error)}`);
205
- let d = a(m(r, `${o}.css`));
206
- i.push({
207
- ...l.data,
208
- bundleUrl: `./${o}.js`,
209
- ...d ? { cssUrl: `./${o}.css` } : {}
254
+ function J(e, t) {
255
+ let r = [];
256
+ if (s(e)) for (let a of u(e)) {
257
+ if (!f(g(e, a)).isDirectory()) continue;
258
+ let o = g(e, a, "manifest.json");
259
+ if (!s(o)) continue;
260
+ let c = i.safeParse(JSON.parse(l(o, "utf-8")));
261
+ if (!c.success) throw Error(`[registry] Invalid manifest for "${a}": ${n(c.error)}`);
262
+ let u = s(g(t, `${a}.css`));
263
+ r.push({
264
+ ...c.data,
265
+ bundleUrl: `./${a}.js`,
266
+ ...u ? { cssUrl: `./${a}.css` } : {}
210
267
  });
211
268
  }
212
- let l = {
269
+ let a = {
213
270
  version: 1,
214
271
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
215
272
  baseUrl: "./",
216
- widgets: i
273
+ widgets: r
217
274
  };
218
- a(r) || o(r, { recursive: !0 }), d(m(r, "registry.json"), JSON.stringify(l, null, 2)), console.log(`[registry] Generated registry.json with ${i.length} widget(s)`);
275
+ s(t) || c(t, { recursive: !0 }), p(g(t, "registry.json"), JSON.stringify(a, null, 2)), console.log(`[registry] Generated registry.json with ${r.length} widget(s)`);
219
276
  }
220
- async function z(e) {
221
- let { build: t } = await import("vite"), n = process.cwd(), r = h(n, e?.srcDir ?? "src"), i = h(n, e?.outDir ?? "dist"), s = L(r);
222
- if (s.length === 0) {
277
+ async function Y(e) {
278
+ let { build: t } = await import("vite"), n = process.cwd(), r = v(n, e?.srcDir ?? "src"), i = v(n, e?.outDir ?? "dist"), a = q(r);
279
+ if (a.length === 0) {
223
280
  console.warn("[glasshome-widgets] No widgets found in", r);
224
281
  return;
225
282
  }
226
283
  if (e?.only) {
227
284
  let t = new Set(e.only);
228
- s = s.filter((e) => t.has(e.name));
285
+ a = a.filter((e) => t.has(e.name));
229
286
  }
230
- e?.only || a(i) && l(i, { recursive: !0 }), a(i) || o(i, { recursive: !0 });
231
- for (let r of s) await t({
287
+ e?.only || s(i) && d(i, { recursive: !0 }), s(i) || c(i, { recursive: !0 });
288
+ let o = /* @__PURE__ */ new Set();
289
+ for (let r of a) await t({
232
290
  configFile: !1,
233
291
  root: n,
234
292
  plugins: [
235
- ...I(),
293
+ ...K(),
236
294
  ...e?.plugins ?? [],
237
- A()
295
+ I(),
296
+ B(o)
238
297
  ],
239
298
  ...e?.viteConfig,
240
299
  build: {
241
300
  lib: {
242
- entry: F(n, r.name, r.entry),
301
+ entry: G(n, r.name, r.entry),
243
302
  formats: ["es"],
244
303
  fileName: r.name,
245
304
  cssFileName: r.name
246
305
  },
247
- rollupOptions: { external: k },
306
+ rollupOptions: { external: F },
248
307
  outDir: i,
249
308
  emptyOutDir: !1,
250
309
  copyPublicDir: !1,
251
310
  ...e?.viteConfig?.build
252
311
  },
253
312
  logLevel: "warn"
254
- }), P(i, r.name), await C({
255
- outFile: m(i, `${r.name}.js`),
256
- hashFile: m(p(r.entry), ".schema-hash"),
257
- widgetName: r.name
313
+ }), W(i, r.name), await k({
314
+ outFile: g(i, `${r.name}.js`),
315
+ hashFile: g(h(r.entry), ".schema-hash"),
316
+ widgetName: r.name,
317
+ manifestPath: g(h(r.entry), "manifest.json")
258
318
  });
259
- R(r, i);
319
+ J(r, i);
260
320
  }
261
- function B(e) {
321
+ function X(e) {
262
322
  let t = e?.entry ?? "src/index.tsx", n = {
263
323
  name: "glasshome-widget:build",
264
324
  apply: "build",
@@ -266,12 +326,12 @@ function B(e) {
266
326
  let e = process.cwd();
267
327
  return { build: {
268
328
  lib: {
269
- entry: F(e, "index", h(e, t)),
329
+ entry: G(e, "index", v(e, t)),
270
330
  formats: ["es"],
271
331
  fileName: "index",
272
332
  cssFileName: "index"
273
333
  },
274
- rollupOptions: { external: k }
334
+ rollupOptions: { external: F }
275
335
  } };
276
336
  }
277
337
  }, r = {
@@ -279,19 +339,19 @@ function B(e) {
279
339
  apply: "serve",
280
340
  enforce: "pre",
281
341
  config() {
282
- let e = O(), t = process.cwd();
342
+ let e = P(), t = process.cwd();
283
343
  return { server: { fs: { allow: [
284
344
  e,
285
345
  t,
286
- h(t, "..", "..")
346
+ v(t, "..", "..")
287
347
  ] } } };
288
348
  },
289
349
  configureServer(e) {
290
- let t = m(O(), "preview.html");
291
- e.middlewares.use(async (n, r, i) => {
292
- if (n.url === "/" || n.url === "/index.html") try {
293
- let i = s(t, "utf-8");
294
- i = await e.transformIndexHtml(n.url, i), r.setHeader("Content-Type", "text/html"), r.statusCode = 200, r.end(i);
350
+ let t = P(), n = g(t, "preview.html");
351
+ e.middlewares.use(async (t, r, i) => {
352
+ if (t.url === "/" || t.url === "/index.html") try {
353
+ let i = l(n, "utf-8");
354
+ i = await e.transformIndexHtml(t.url, i), r.setHeader("Content-Type", "text/html"), r.statusCode = 200, r.end(i);
295
355
  } catch (e) {
296
356
  i(e);
297
357
  }
@@ -299,33 +359,37 @@ function B(e) {
299
359
  });
300
360
  },
301
361
  resolveId(e) {
302
- if (e === E) return D(m(O(), "host.tsx"));
303
- if (e === w) return T;
362
+ if (e === M) {
363
+ let e = P();
364
+ return N(g(e, "host.tsx"));
365
+ }
366
+ if (e === A) return j;
304
367
  },
305
368
  load(e) {
306
- if (e === T) return `export { default } from "${D(h(process.cwd(), t))}";`;
369
+ if (e === j) return `export { default } from "${N(v(process.cwd(), t))}";`;
307
370
  }
308
371
  }, i = {
309
372
  name: "glasshome-widget:schema",
310
373
  apply: "build",
311
374
  async closeBundle() {
312
- P(h(process.cwd(), "dist"), "index"), await C({
313
- outFile: h(process.cwd(), "dist", "index.js"),
314
- hashFile: h(process.cwd(), ".schema-hash"),
375
+ W(v(process.cwd(), "dist"), "index"), await k({
376
+ outFile: v(process.cwd(), "dist", "index.js"),
377
+ hashFile: v(process.cwd(), ".schema-hash"),
315
378
  widgetName: "index",
316
- manifestPath: h(process.cwd(), "manifest.json")
379
+ manifestPath: v(process.cwd(), "manifest.json")
317
380
  });
318
381
  }
319
382
  };
320
383
  return [
321
- ...I(),
384
+ ...K(),
322
385
  n,
323
- A(),
386
+ I(),
387
+ B(),
324
388
  i,
325
389
  r
326
390
  ];
327
391
  }
328
- function V(e) {
392
+ function Z(e) {
329
393
  let t = e?.srcDir ?? "src", n = e?.outDir ?? "dist", r = [];
330
394
  return [{
331
395
  name: "glasshome-widgets:build",
@@ -344,7 +408,7 @@ function V(e) {
344
408
  if (e === "\0glasshome-noop") return "export {}";
345
409
  },
346
410
  async closeBundle() {
347
- await z({
411
+ await Y({
348
412
  srcDir: t,
349
413
  outDir: n,
350
414
  plugins: r
@@ -353,4 +417,4 @@ function V(e) {
353
417
  }];
354
418
  }
355
419
  //#endregion
356
- export { b as MAX_EXAMPLES, z as buildWidgets, L as discoverWidgets, R as generateRegistry, B as glasshomeWidget, V as glasshomeWidgets, k as isWidgetExternal, C as runSchemaGuard };
420
+ export { C as MAX_EXAMPLES, Y as buildWidgets, z as createUiImportTracker, q as discoverWidgets, J as generateRegistry, X as glasshomeWidget, Z as glasshomeWidgets, R as isDirectUiImportSource, F as isWidgetExternal, k as runSchemaGuard };
@@ -14,14 +14,8 @@
14
14
  * Usage: bun --conditions browser introspect.js <bundle.js>
15
15
  * Prints: { manifest, jsonSchema } on stdout, or exits non-zero with a reason.
16
16
  */
17
- interface Introspection {
18
- manifest: {
19
- name?: string;
20
- configVersion?: number;
21
- examples?: unknown;
22
- } | null;
23
- /** JSON Schema derived from the widget's configSchema, when it has one. */
24
- jsonSchema: object | null;
17
+ export interface ExampleConfigIssue {
18
+ index: number;
19
+ label?: string;
20
+ problems: string[];
25
21
  }
26
- declare function installDom(): Promise<void>;
27
- declare function main(): Promise<void>;