@glasshome/widget-sdk 1.8.0 → 1.8.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/index.js CHANGED
@@ -1314,7 +1314,7 @@ function rn() {
1314
1314
  //#region src/version.ts
1315
1315
  var an = {
1316
1316
  name: "@glasshome/widget-sdk",
1317
- version: "1.8.0",
1317
+ version: "1.8.1",
1318
1318
  description: "SDK for building GlassHome dashboard widgets with SolidJS",
1319
1319
  keywords: [
1320
1320
  "glasshome",
@@ -1377,11 +1377,12 @@ var an = {
1377
1377
  dependencies: {
1378
1378
  "@glasshome/widget-contract": "0.2.0",
1379
1379
  "@modular-forms/solid": "^0.25.1",
1380
+ "@tailwindcss/vite": "^4.1.13",
1380
1381
  clsx: "^2.1.1",
1382
+ "happy-dom": "^20.0.0",
1381
1383
  "tailwind-merge": "^3.5.0",
1382
- zod: "^4.1.13",
1383
- "@tailwindcss/vite": "^4.1.13",
1384
- tailwindcss: "^4.1.13"
1384
+ tailwindcss: "^4.1.13",
1385
+ zod: "^4.1.13"
1385
1386
  },
1386
1387
  devDependencies: {
1387
1388
  "@types/bun": "latest",
@@ -12,7 +12,7 @@ export interface GlasshomeWidgetOptions {
12
12
  */
13
13
  export declare const MAX_EXAMPLES = 20;
14
14
  /**
15
- * Configuration-drift guard (D-11). Imports the built bundle, derives the JSON
15
+ * Configuration-drift guard (D-11). Reads the built bundle, derives the JSON
16
16
  * Schema from its configSchema, and compares against the recorded
17
17
  * `.schema-hash`. A shape change without a configVersion bump fails the build:
18
18
  * tsc cannot catch this class of break because the old persisted config still
@@ -1,17 +1,18 @@
1
1
  import { formatSchemaError as e, isHostProvidedModule as t, widgetManifestSchema as n } from "@glasshome/widget-contract";
2
- import { createHash as r } from "node:crypto";
3
- import { existsSync as i, mkdirSync as a, readFileSync as o, readdirSync as s, rmSync as c, statSync as l, writeFileSync as u } from "node:fs";
4
- import { createRequire as d } from "node:module";
5
- import { dirname as f, join as p, resolve as m, sep as h } from "node:path";
6
- import { fileURLToPath as g } from "node:url";
7
- import _ from "@tailwindcss/vite";
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";
8
9
  //#region src/vite/index.ts
9
- function v(e) {
10
+ function y(e) {
10
11
  let t = JSON.stringify(e, Object.keys(e).sort());
11
- return r("sha256").update(t).digest("hex").slice(0, 16);
12
+ return i("sha256").update(t).digest("hex").slice(0, 16);
12
13
  }
13
- var y = 20;
14
- async function b(e, t) {
14
+ var b = 20;
15
+ async function x(e, t) {
15
16
  if (e === void 0) return;
16
17
  let n;
17
18
  try {
@@ -31,54 +32,84 @@ async function b(e, t) {
31
32
  let a = i.error.issues.map((e) => ` examples${e.path.length ? `[${e.path.join("][")}]` : ""}: ${e.message}`).join("\n");
32
33
  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.`);
33
34
  }
34
- async function x(e) {
35
- if (!i(e.outFile)) return;
36
- let t;
35
+ function S(e) {
36
+ let t = p(_(import.meta.url)), n = [m(t, "introspect.js"), m(t, "introspect.ts")].find((e) => a(e));
37
+ if (!n) return {
38
+ ok: !1,
39
+ reason: `introspect not found next to ${t}`
40
+ };
41
+ let i = r(process.execPath, [
42
+ "--conditions",
43
+ "browser",
44
+ n,
45
+ e
46
+ ], {
47
+ encoding: "utf-8",
48
+ timeout: 3e4
49
+ });
50
+ if (i.error) return {
51
+ ok: !1,
52
+ reason: i.error.message
53
+ };
54
+ if (i.status !== 0) return {
55
+ ok: !1,
56
+ reason: (i.stderr || "").trim().split("\n")[0] || `exit ${i.status}`
57
+ };
37
58
  try {
38
- t = (await import(`${e.outFile}?t=${Date.now()}`)).default;
59
+ return {
60
+ ok: !0,
61
+ value: JSON.parse(i.stdout)
62
+ };
39
63
  } catch {
40
- return;
64
+ return {
65
+ ok: !1,
66
+ reason: "introspect returned unparseable output"
67
+ };
41
68
  }
42
- if (await b(t?.manifest?.examples, t?.manifest?.name ?? e.widgetName), !t?.configSchema) return;
43
- let n;
44
- try {
45
- let { z: e } = await import("zod");
46
- n = e.toJSONSchema(t.configSchema, { unrepresentable: "any" });
47
- } catch {
69
+ }
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.`);
48
75
  return;
49
76
  }
50
- if (e.manifestPath && i(e.manifestPath)) {
51
- let t = JSON.parse(o(e.manifestPath, "utf-8"));
52
- t.schema = n, u(e.manifestPath, JSON.stringify(t, null, 2));
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));
53
84
  }
54
- let r = v(n), a = t.manifest?.configVersion ?? null, s = t.manifest?.name ?? e.widgetName;
55
- if (i(e.hashFile)) {
56
- let t = o(e.hashFile, "utf-8").trim(), n = null;
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;
57
88
  if (t.startsWith("{")) try {
58
89
  n = JSON.parse(t);
59
90
  } catch {
60
91
  n = null;
61
92
  }
62
93
  if (n) {
63
- if (n.hash !== r && n.configVersion === a) throw Error(`[widget-sdk] Config schema shape changed for "${s}" without a configVersion bump. Bump configVersion in defineWidget (currently ${a ?? "unset"}) or revert the schema change, then rebuild. Recorded in ${e.hashFile}`);
64
- } else t !== r && console.warn(`[widget-sdk] Schema shape changed for "${s}" — verify configVersion was bumped`);
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`);
65
96
  }
66
- u(e.hashFile, `${JSON.stringify({
67
- hash: r,
68
- configVersion: a
97
+ d(e.hashFile, `${JSON.stringify({
98
+ hash: i,
99
+ configVersion: o
69
100
  })}\n`);
70
101
  }
71
- var S = "virtual:glasshome-widget", C = "\0virtual:glasshome-widget", w = "/@glasshome/preview";
72
- function T(e) {
73
- return h === "\\" ? e.split(h).join("/") : e;
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;
74
105
  }
75
- function E() {
76
- return m(f(g(import.meta.url)), "../../preview");
106
+ function O() {
107
+ return h(p(_(import.meta.url)), "../../preview");
77
108
  }
78
- function D(e) {
109
+ function k(e) {
79
110
  return t(e);
80
111
  }
81
- function O() {
112
+ function A() {
82
113
  return {
83
114
  name: "glasshome-widget:sync-layer-guard",
84
115
  apply: "build",
@@ -88,15 +119,15 @@ function O() {
88
119
  }
89
120
  };
90
121
  }
91
- var k = "node_modules/.cache/glasshome-widgets";
92
- function A(e) {
122
+ var j = "node_modules/.cache/glasshome-widgets";
123
+ function M(e) {
93
124
  try {
94
- return d(p(process.cwd(), "package.json")).resolve(e);
125
+ return f(m(process.cwd(), "package.json")).resolve(e);
95
126
  } catch {
96
127
  return null;
97
128
  }
98
129
  }
99
- var j = [
130
+ var N = [
100
131
  "--radius",
101
132
  "--background",
102
133
  "--foreground",
@@ -106,88 +137,88 @@ var j = [
106
137
  "--muted",
107
138
  "--accent"
108
139
  ];
109
- function M(e, t) {
110
- let n = p(e, `${t}.css`);
111
- if (!i(n)) return;
112
- let r = o(n, "utf-8");
140
+ function P(e, t) {
141
+ let n = m(e, `${t}.css`);
142
+ if (!a(n)) return;
143
+ let r = s(n, "utf-8");
113
144
  for (let e of r.matchAll(/:host[^{]*\{([^}]*)\}/g)) {
114
- let n = e[1] ?? "", r = j.find((e) => n.includes(`${e}:`));
145
+ let n = e[1] ?? "", r = N.find((e) => n.includes(`${e}:`));
115
146
  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.`);
116
147
  }
117
148
  }
118
- function N(e, t, n) {
119
- let r = m(e, k);
120
- a(r, { recursive: !0 });
121
- let o = A("@glasshome/ui/styles");
122
- if (!o) 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.");
123
- let s = m(f(o), "../.."), c = A("@glasshome/widget-sdk/tailwind-sources"), l = c ? f(c) : null, d = [
124
- p(s, "src"),
125
- p(s, "dist"),
126
- ...l ? [p(l, "src"), p(l, "dist")] : [],
127
- f(n)
128
- ].filter((e) => i(e)), h = m(r, `${t}.tailwind.css`);
129
- u(h, [
149
+ function F(e, t, n) {
150
+ let r = h(e, j);
151
+ o(r, { recursive: !0 });
152
+ let i = M("@glasshome/ui/styles");
153
+ 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, [
130
161
  "@import \"tailwindcss\" source(none);",
131
162
  "@import \"tw-animate-css\";",
132
163
  "@import \"@glasshome/ui/styles/theme\";",
133
- ...d.map((e) => `@source "${T(e)}";`),
164
+ ...u.map((e) => `@source "${D(e)}";`),
134
165
  "@custom-variant dark {",
135
166
  " &:is(.dark *) { @slot }",
136
167
  " :host(.dark) & { @slot }",
137
168
  "}",
138
169
  ""
139
170
  ].join("\n"));
140
- let g = m(r, `${t}.entry.ts`);
141
- return u(g, [
142
- `import "${T(h)}";`,
143
- `export { default } from "${T(n)}";`,
171
+ let g = h(r, `${t}.entry.ts`);
172
+ return d(g, [
173
+ `import "${D(f)}";`,
174
+ `export { default } from "${D(n)}";`,
144
175
  ""
145
176
  ].join("\n")), g;
146
177
  }
147
- function P() {
148
- let e = _();
178
+ function I() {
179
+ let e = v();
149
180
  for (let t of e) t.apply ??= "build";
150
181
  return e;
151
182
  }
152
- function F(e) {
183
+ function L(e) {
153
184
  let t = [];
154
- if (!i(e)) return t;
155
- for (let n of s(e)) {
156
- let r = m(e, n);
157
- if (!l(r).isDirectory()) continue;
158
- let a = m(r, "index.tsx"), o = m(r, "manifest.json");
159
- i(a) && i(o) && t.push({
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({
160
191
  name: n,
161
- entry: a
192
+ entry: i
162
193
  });
163
194
  }
164
195
  return t;
165
196
  }
166
- function I(t, r) {
167
- let c = [];
168
- if (i(t)) for (let a of s(t)) {
169
- if (!l(p(t, a)).isDirectory()) continue;
170
- let s = p(t, a, "manifest.json");
171
- if (!i(s)) continue;
172
- let u = n.safeParse(JSON.parse(o(s, "utf-8")));
173
- if (!u.success) throw Error(`[registry] Invalid manifest for "${a}": ${e(u.error)}`);
174
- let d = i(p(r, `${a}.css`));
175
- c.push({
176
- ...u.data,
177
- bundleUrl: `./${a}.js`,
178
- ...d ? { cssUrl: `./${a}.css` } : {}
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` } : {}
179
210
  });
180
211
  }
181
- let d = {
212
+ let l = {
182
213
  version: 1,
183
214
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
184
215
  baseUrl: "./",
185
- widgets: c
216
+ widgets: i
186
217
  };
187
- i(r) || a(r, { recursive: !0 }), u(p(r, "registry.json"), JSON.stringify(d, null, 2)), console.log(`[registry] Generated registry.json with ${c.length} widget(s)`);
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)`);
188
219
  }
189
- async function L(e) {
190
- let { build: t } = await import("vite"), n = process.cwd(), r = m(n, e?.srcDir ?? "src"), o = m(n, e?.outDir ?? "dist"), s = F(r);
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);
191
222
  if (s.length === 0) {
192
223
  console.warn("[glasshome-widgets] No widgets found in", r);
193
224
  return;
@@ -196,38 +227,38 @@ async function L(e) {
196
227
  let t = new Set(e.only);
197
228
  s = s.filter((e) => t.has(e.name));
198
229
  }
199
- e?.only || i(o) && c(o, { recursive: !0 }), i(o) || a(o, { recursive: !0 });
230
+ e?.only || a(i) && l(i, { recursive: !0 }), a(i) || o(i, { recursive: !0 });
200
231
  for (let r of s) await t({
201
232
  configFile: !1,
202
233
  root: n,
203
234
  plugins: [
204
- ...P(),
235
+ ...I(),
205
236
  ...e?.plugins ?? [],
206
- O()
237
+ A()
207
238
  ],
208
239
  ...e?.viteConfig,
209
240
  build: {
210
241
  lib: {
211
- entry: N(n, r.name, r.entry),
242
+ entry: F(n, r.name, r.entry),
212
243
  formats: ["es"],
213
244
  fileName: r.name,
214
245
  cssFileName: r.name
215
246
  },
216
- rollupOptions: { external: D },
217
- outDir: o,
247
+ rollupOptions: { external: k },
248
+ outDir: i,
218
249
  emptyOutDir: !1,
219
250
  copyPublicDir: !1,
220
251
  ...e?.viteConfig?.build
221
252
  },
222
253
  logLevel: "warn"
223
- }), M(o, r.name), await x({
224
- outFile: p(o, `${r.name}.js`),
225
- hashFile: p(f(r.entry), ".schema-hash"),
254
+ }), P(i, r.name), await C({
255
+ outFile: m(i, `${r.name}.js`),
256
+ hashFile: m(p(r.entry), ".schema-hash"),
226
257
  widgetName: r.name
227
258
  });
228
- I(r, o);
259
+ R(r, i);
229
260
  }
230
- function R(e) {
261
+ function B(e) {
231
262
  let t = e?.entry ?? "src/index.tsx", n = {
232
263
  name: "glasshome-widget:build",
233
264
  apply: "build",
@@ -235,12 +266,12 @@ function R(e) {
235
266
  let e = process.cwd();
236
267
  return { build: {
237
268
  lib: {
238
- entry: N(e, "index", m(e, t)),
269
+ entry: F(e, "index", h(e, t)),
239
270
  formats: ["es"],
240
271
  fileName: "index",
241
272
  cssFileName: "index"
242
273
  },
243
- rollupOptions: { external: D }
274
+ rollupOptions: { external: k }
244
275
  } };
245
276
  }
246
277
  }, r = {
@@ -248,18 +279,18 @@ function R(e) {
248
279
  apply: "serve",
249
280
  enforce: "pre",
250
281
  config() {
251
- let e = E(), t = process.cwd();
282
+ let e = O(), t = process.cwd();
252
283
  return { server: { fs: { allow: [
253
284
  e,
254
285
  t,
255
- m(t, "..", "..")
286
+ h(t, "..", "..")
256
287
  ] } } };
257
288
  },
258
289
  configureServer(e) {
259
- let t = p(E(), "preview.html");
290
+ let t = m(O(), "preview.html");
260
291
  e.middlewares.use(async (n, r, i) => {
261
292
  if (n.url === "/" || n.url === "/index.html") try {
262
- let i = o(t, "utf-8");
293
+ let i = s(t, "utf-8");
263
294
  i = await e.transformIndexHtml(n.url, i), r.setHeader("Content-Type", "text/html"), r.statusCode = 200, r.end(i);
264
295
  } catch (e) {
265
296
  i(e);
@@ -268,33 +299,33 @@ function R(e) {
268
299
  });
269
300
  },
270
301
  resolveId(e) {
271
- if (e === w) return T(p(E(), "host.tsx"));
272
- if (e === S) return C;
302
+ if (e === E) return D(m(O(), "host.tsx"));
303
+ if (e === w) return T;
273
304
  },
274
305
  load(e) {
275
- if (e === C) return `export { default } from "${T(m(process.cwd(), t))}";`;
306
+ if (e === T) return `export { default } from "${D(h(process.cwd(), t))}";`;
276
307
  }
277
308
  }, i = {
278
309
  name: "glasshome-widget:schema",
279
310
  apply: "build",
280
311
  async closeBundle() {
281
- M(m(process.cwd(), "dist"), "index"), await x({
282
- outFile: m(process.cwd(), "dist", "index.js"),
283
- hashFile: m(process.cwd(), ".schema-hash"),
312
+ P(h(process.cwd(), "dist"), "index"), await C({
313
+ outFile: h(process.cwd(), "dist", "index.js"),
314
+ hashFile: h(process.cwd(), ".schema-hash"),
284
315
  widgetName: "index",
285
- manifestPath: m(process.cwd(), "manifest.json")
316
+ manifestPath: h(process.cwd(), "manifest.json")
286
317
  });
287
318
  }
288
319
  };
289
320
  return [
290
- ...P(),
321
+ ...I(),
291
322
  n,
292
- O(),
323
+ A(),
293
324
  i,
294
325
  r
295
326
  ];
296
327
  }
297
- function z(e) {
328
+ function V(e) {
298
329
  let t = e?.srcDir ?? "src", n = e?.outDir ?? "dist", r = [];
299
330
  return [{
300
331
  name: "glasshome-widgets:build",
@@ -313,7 +344,7 @@ function z(e) {
313
344
  if (e === "\0glasshome-noop") return "export {}";
314
345
  },
315
346
  async closeBundle() {
316
- await L({
347
+ await z({
317
348
  srcDir: t,
318
349
  outDir: n,
319
350
  plugins: r
@@ -322,4 +353,4 @@ function z(e) {
322
353
  }];
323
354
  }
324
355
  //#endregion
325
- export { y as MAX_EXAMPLES, L as buildWidgets, F as discoverWidgets, I as generateRegistry, R as glasshomeWidget, z as glasshomeWidgets, D as isWidgetExternal, x as runSchemaGuard };
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 };
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Reads a built widget bundle's definition and prints it as JSON.
3
+ *
4
+ * Runs as its own process because a widget bundle cannot be imported by the
5
+ * build: `solid-js/web` resolves to its server build under Node's conditions
6
+ * and throws "Client-only API called on the server side" the moment the module
7
+ * initialises, and forcing browser conditions then needs a DOM for the
8
+ * templates Solid creates at import time. The build spawns this with
9
+ * `--conditions browser` and a DOM in place, so the import succeeds.
10
+ *
11
+ * Until this existed the guard swallowed that import failure and silently did
12
+ * nothing — for every widget, on every build.
13
+ *
14
+ * Usage: bun --conditions browser introspect.js <bundle.js>
15
+ * Prints: { manifest, jsonSchema } on stdout, or exits non-zero with a reason.
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;
25
+ }
26
+ declare function installDom(): Promise<void>;
27
+ declare function main(): Promise<void>;
@@ -0,0 +1,37 @@
1
+ //#region src/vite/introspect.ts
2
+ async function e() {
3
+ let { Window: e } = await import("happy-dom"), t = new e({ url: "http://localhost" });
4
+ for (let e of [
5
+ "window",
6
+ "document",
7
+ "navigator",
8
+ "location",
9
+ "customElements",
10
+ "HTMLElement",
11
+ "Element",
12
+ "Node",
13
+ "CSS",
14
+ "getComputedStyle",
15
+ "requestAnimationFrame",
16
+ "cancelAnimationFrame",
17
+ "matchMedia"
18
+ ]) globalThis[e] === void 0 && (globalThis[e] = t[e]);
19
+ }
20
+ async function t() {
21
+ let t = process.argv[2];
22
+ t || (process.stderr.write("introspect: no bundle path given\n"), process.exit(2)), await e();
23
+ let n = (await import(t)).default, r = null;
24
+ if (n?.configSchema) {
25
+ let { z: e } = await import("zod");
26
+ r = e.toJSONSchema(n.configSchema, { unrepresentable: "any" });
27
+ }
28
+ let i = {
29
+ manifest: n?.manifest ?? null,
30
+ jsonSchema: r
31
+ };
32
+ process.stdout.write(JSON.stringify(i));
33
+ }
34
+ t().catch((e) => {
35
+ process.stderr.write(`${e instanceof Error ? e.message : String(e)}\n`), process.exit(1);
36
+ });
37
+ //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glasshome/widget-sdk",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "description": "SDK for building GlassHome dashboard widgets with SolidJS",
5
5
  "keywords": [
6
6
  "glasshome",
@@ -63,11 +63,12 @@
63
63
  "dependencies": {
64
64
  "@glasshome/widget-contract": "0.2.0",
65
65
  "@modular-forms/solid": "^0.25.1",
66
+ "@tailwindcss/vite": "^4.1.13",
66
67
  "clsx": "^2.1.1",
68
+ "happy-dom": "^20.0.0",
67
69
  "tailwind-merge": "^3.5.0",
68
- "zod": "^4.1.13",
69
- "@tailwindcss/vite": "^4.1.13",
70
- "tailwindcss": "^4.1.13"
70
+ "tailwindcss": "^4.1.13",
71
+ "zod": "^4.1.13"
71
72
  },
72
73
  "devDependencies": {
73
74
  "@types/bun": "latest",