@glasshome/widget-sdk 1.22.1 → 1.23.0
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/framework/index.d.ts +2 -1
- package/dist/framework/utils/index.d.ts +0 -1
- package/dist/index.js +637 -682
- package/dist/schemas.js +1 -2
- package/dist/vite/in-process-introspector.d.ts +2 -0
- package/dist/vite/index.d.ts +4 -1
- package/dist/vite/index.js +153 -138
- package/dist/vite/introspect-session.d.ts +13 -1
- package/package.json +4 -4
- package/dist/framework/utils/clipboard.d.ts +0 -9
package/dist/schemas.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { e as GridSizeSchema, t as PublishBodySchema, n as PublishConfirmSchema, r as PublishRequestSchema, d as WidgetManifestSchema, i as capabilitiesSchema, a as capabilityGrantSchema, o as formatSchemaError, s as parseGridSize, c as publishManifestSchema, l as serializeGridSize, u as widgetManifestSchema };
|
|
1
|
+
export { GridSizeSchema, PublishBodySchema, PublishConfirmSchema, PublishRequestSchema, widgetManifestSchema as WidgetManifestSchema, capabilitiesSchema, capabilityGrantSchema, formatSchemaError, parseGridSize, publishManifestSchema, serializeGridSize, widgetManifestSchema } from "@glasshome/widget-contract";
|
package/dist/vite/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type CapabilityGrant } from "@glasshome/widget-contract";
|
|
2
2
|
import type { InlineConfig, Plugin } from "vite";
|
|
3
3
|
import type { ExampleConfigIssue, WidgetIntrospection } from "./introspect-core";
|
|
4
|
-
import { createIntrospectSession, type IntrospectSession, type IntrospectSessionOptions, introspectOnce } from "./introspect-session";
|
|
4
|
+
import { createIntrospectSession, type IntrospectResult, type IntrospectSession, type IntrospectSessionOptions, introspectOnce } from "./introspect-session";
|
|
5
5
|
export { createIntrospectSession, introspectOnce };
|
|
6
6
|
export type { ExampleConfigIssue, IntrospectSession, IntrospectSessionOptions, WidgetIntrospection, };
|
|
7
7
|
export interface GlasshomeWidgetOptions {
|
|
@@ -21,6 +21,7 @@ export declare function sdkImportsOf(code: string): Set<string>;
|
|
|
21
21
|
/** SDK hooks that read a fixed entity on the widget's behalf, so the widget must declare that read. */
|
|
22
22
|
export declare const HOOK_READS: Record<string, string>;
|
|
23
23
|
export declare function assertHookReadsDeclared(code: string, capabilities: readonly CapabilityGrant[], widgetName: string): void;
|
|
24
|
+
export type Introspector = (outFile: string) => IntrospectResult | Promise<IntrospectResult>;
|
|
24
25
|
export declare function runSchemaGuard(args: {
|
|
25
26
|
outFile: string;
|
|
26
27
|
hashFile: string;
|
|
@@ -28,6 +29,8 @@ export declare function runSchemaGuard(args: {
|
|
|
28
29
|
manifestPath?: string;
|
|
29
30
|
/** Persistent worker to reuse. Only `bun widget connect`'s watch loop passes one. */
|
|
30
31
|
session?: IntrospectSession;
|
|
32
|
+
/** Reads the bundle when no session is given. Defaults to one subprocess per call. */
|
|
33
|
+
introspect?: Introspector;
|
|
31
34
|
}): Promise<void>;
|
|
32
35
|
/**
|
|
33
36
|
* Packages provided by the host import map — widgets must not bundle these.
|
package/dist/vite/index.js
CHANGED
|
@@ -6,40 +6,46 @@ import { createRequire as m } from "node:module";
|
|
|
6
6
|
import { dirname as h, join as g, relative as _, resolve as v, sep as y } from "node:path";
|
|
7
7
|
import { fileURLToPath as b } from "node:url";
|
|
8
8
|
import ee from "@tailwindcss/vite";
|
|
9
|
-
import { spawn as te, spawnSync as
|
|
10
|
-
//#region
|
|
11
|
-
var
|
|
12
|
-
|
|
9
|
+
import { spawn as te, spawnSync as x } from "node:child_process";
|
|
10
|
+
//#region node_modules/@glasshome/widget-contract/dist/clock.mjs
|
|
11
|
+
var S = (e) => e, C = (e) => e, ne = {
|
|
12
|
+
now: () => Date.now(),
|
|
13
|
+
setTimeout: (e, t) => S(globalThis.setTimeout(e, t)),
|
|
14
|
+
clearTimeout: (e) => globalThis.clearTimeout(C(e)),
|
|
15
|
+
setInterval: (e, t) => S(globalThis.setInterval(e, t)),
|
|
16
|
+
clearInterval: (e) => globalThis.clearInterval(C(e))
|
|
17
|
+
}, re = 262144e3, w = 3e4, ie = 3e3;
|
|
18
|
+
function T(e) {
|
|
13
19
|
let t = h(b(import.meta.url));
|
|
14
20
|
return [g(t, `${e}.js`), g(t, `${e}.ts`)].find((e) => s(e)) ?? null;
|
|
15
21
|
}
|
|
16
|
-
function
|
|
17
|
-
let
|
|
18
|
-
if (!
|
|
22
|
+
function E(e, t) {
|
|
23
|
+
let n = T("introspect");
|
|
24
|
+
if (!n) return {
|
|
19
25
|
ok: !1,
|
|
20
26
|
reason: "introspect not found next to the sdk"
|
|
21
27
|
};
|
|
22
|
-
let
|
|
28
|
+
let r = x(process.execPath, [
|
|
23
29
|
"--conditions",
|
|
24
30
|
"browser",
|
|
25
|
-
|
|
31
|
+
n,
|
|
26
32
|
e
|
|
27
33
|
], {
|
|
28
34
|
encoding: "utf-8",
|
|
29
|
-
timeout:
|
|
35
|
+
timeout: t?.timeoutMs ?? w
|
|
30
36
|
});
|
|
31
|
-
if (
|
|
37
|
+
if (r.error) return {
|
|
32
38
|
ok: !1,
|
|
33
|
-
reason:
|
|
39
|
+
reason: r.error.message
|
|
34
40
|
};
|
|
35
|
-
if (
|
|
41
|
+
if (r.status !== 0) return {
|
|
36
42
|
ok: !1,
|
|
37
|
-
reason: (
|
|
43
|
+
reason: (r.stderr || "").trim().split("\n")[0] || `exit ${r.status}`
|
|
38
44
|
};
|
|
39
45
|
try {
|
|
40
46
|
return {
|
|
41
47
|
ok: !0,
|
|
42
|
-
value: JSON.parse(
|
|
48
|
+
value: JSON.parse(r.stdout)
|
|
43
49
|
};
|
|
44
50
|
} catch {
|
|
45
51
|
return {
|
|
@@ -48,27 +54,63 @@ function w(e) {
|
|
|
48
54
|
};
|
|
49
55
|
}
|
|
50
56
|
}
|
|
51
|
-
function
|
|
57
|
+
function ae(e) {
|
|
58
|
+
let t = te(process.execPath, [
|
|
59
|
+
"--conditions",
|
|
60
|
+
"browser",
|
|
61
|
+
e
|
|
62
|
+
], { stdio: [
|
|
63
|
+
"pipe",
|
|
64
|
+
"pipe",
|
|
65
|
+
"inherit"
|
|
66
|
+
] });
|
|
67
|
+
return {
|
|
68
|
+
write(e) {
|
|
69
|
+
return t.stdin?.writable ? (t.stdin.write(e), !0) : !1;
|
|
70
|
+
},
|
|
71
|
+
onLine(e) {
|
|
72
|
+
let n = "";
|
|
73
|
+
t.stdout?.setEncoding("utf-8"), t.stdout?.on("data", (t) => {
|
|
74
|
+
n += t;
|
|
75
|
+
let r = n.indexOf("\n");
|
|
76
|
+
for (; r >= 0;) {
|
|
77
|
+
let t = n.slice(0, r).trim();
|
|
78
|
+
n = n.slice(r + 1), t && e(t), r = n.indexOf("\n");
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
},
|
|
82
|
+
onExit(e) {
|
|
83
|
+
t.on("error", (t) => e(t.message)), t.on("exit", (t, n) => e(`introspect worker exited (${n ?? `code ${t}`})`));
|
|
84
|
+
},
|
|
85
|
+
kill() {
|
|
86
|
+
t.kill();
|
|
87
|
+
},
|
|
88
|
+
get pid() {
|
|
89
|
+
return t.pid ?? null;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function oe(e) {
|
|
52
94
|
return {
|
|
53
|
-
introspect: async (
|
|
95
|
+
introspect: async (t) => E(t, { timeoutMs: e }),
|
|
54
96
|
dispose: async () => {},
|
|
55
97
|
childPid: null
|
|
56
98
|
};
|
|
57
99
|
}
|
|
58
|
-
function
|
|
59
|
-
if (process.env.GLASSHOME_WIDGET_NO_WORKER === "1") return
|
|
60
|
-
let t = e?.rssLimitBytes ??
|
|
61
|
-
function
|
|
100
|
+
function se(e) {
|
|
101
|
+
if (process.env.GLASSHOME_WIDGET_NO_WORKER === "1") return oe(e?.timeoutMs);
|
|
102
|
+
let t = e?.rssLimitBytes ?? re, n = e?.timeoutMs ?? w, r = e?.slowMs ?? ie, i = e?.clock ?? ne, a = e?.spawnWorker ?? ae, o = null, s = !1, c = 0, l = Promise.resolve();
|
|
103
|
+
function u(e, t) {
|
|
62
104
|
for (let n of e.pending.values()) n({
|
|
63
105
|
ok: !1,
|
|
64
106
|
reason: t
|
|
65
107
|
});
|
|
66
108
|
e.pending.clear();
|
|
67
109
|
}
|
|
68
|
-
function
|
|
69
|
-
|
|
110
|
+
function d(e, t) {
|
|
111
|
+
o === e && (o = null), u(e, t), e.proc.kill();
|
|
70
112
|
}
|
|
71
|
-
function
|
|
113
|
+
function f(e, n) {
|
|
72
114
|
let i;
|
|
73
115
|
try {
|
|
74
116
|
i = JSON.parse(n);
|
|
@@ -85,56 +127,38 @@ function ae(e) {
|
|
|
85
127
|
reason: i.reason ?? "introspection failed"
|
|
86
128
|
}));
|
|
87
129
|
}
|
|
88
|
-
function
|
|
89
|
-
let t =
|
|
90
|
-
|
|
91
|
-
"browser",
|
|
92
|
-
e
|
|
93
|
-
], { stdio: [
|
|
94
|
-
"pipe",
|
|
95
|
-
"pipe",
|
|
96
|
-
"inherit"
|
|
97
|
-
] }), a = {
|
|
98
|
-
proc: n,
|
|
130
|
+
function p(e) {
|
|
131
|
+
let t = i.now(), n = {
|
|
132
|
+
proc: a(e),
|
|
99
133
|
ready: Promise.resolve(),
|
|
100
134
|
pending: /* @__PURE__ */ new Map(),
|
|
101
135
|
retireAfterRequest: !1
|
|
102
136
|
};
|
|
103
|
-
return
|
|
104
|
-
let s =
|
|
105
|
-
n.
|
|
106
|
-
s
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
let n = Date.now() - t;
|
|
114
|
-
n > r && console.warn(`[widget-sdk] introspect worker took ${n}ms to boot`), e();
|
|
115
|
-
} else u(a, n);
|
|
116
|
-
}
|
|
117
|
-
i = s.indexOf("\n");
|
|
118
|
-
}
|
|
137
|
+
return n.ready = new Promise((e, a) => {
|
|
138
|
+
let s = !1;
|
|
139
|
+
n.proc.onLine((a) => {
|
|
140
|
+
if (!s && a.includes("\"ready\"")) {
|
|
141
|
+
s = !0;
|
|
142
|
+
let n = i.now() - t;
|
|
143
|
+
n > r && console.warn(`[widget-sdk] introspect worker took ${n}ms to boot`), e();
|
|
144
|
+
} else f(n, a);
|
|
145
|
+
}), n.proc.onExit((e) => {
|
|
146
|
+
s || a(Error(e)), o === n && (o = null), u(n, e);
|
|
119
147
|
});
|
|
120
|
-
|
|
121
|
-
l || o(Error(e)), i === a && (i = null), c(a, e);
|
|
122
|
-
};
|
|
123
|
-
n.on("error", (e) => d(e.message)), n.on("exit", (e, t) => d(`introspect worker exited (${t ?? `code ${e}`})`));
|
|
124
|
-
}), a;
|
|
148
|
+
}), n;
|
|
125
149
|
}
|
|
126
|
-
async function
|
|
127
|
-
if (
|
|
150
|
+
async function m(e) {
|
|
151
|
+
if (s) return {
|
|
128
152
|
ok: !1,
|
|
129
153
|
reason: "introspect session disposed"
|
|
130
154
|
};
|
|
131
|
-
let t =
|
|
155
|
+
let t = T("introspect-worker");
|
|
132
156
|
if (!t) return {
|
|
133
157
|
ok: !1,
|
|
134
158
|
reason: "introspect-worker not found next to the sdk"
|
|
135
159
|
};
|
|
136
|
-
|
|
137
|
-
let r =
|
|
160
|
+
o?.retireAfterRequest && d(o, "worker was replaced");
|
|
161
|
+
let r = o ??= p(t);
|
|
138
162
|
try {
|
|
139
163
|
await r.ready;
|
|
140
164
|
} catch (e) {
|
|
@@ -143,28 +167,24 @@ function ae(e) {
|
|
|
143
167
|
reason: e instanceof Error ? e.message : String(e)
|
|
144
168
|
};
|
|
145
169
|
}
|
|
146
|
-
|
|
147
|
-
ok: !1,
|
|
148
|
-
reason: "introspect worker is not writable"
|
|
149
|
-
};
|
|
150
|
-
let s = ++o;
|
|
170
|
+
let a = ++c;
|
|
151
171
|
return new Promise((t) => {
|
|
152
|
-
let
|
|
153
|
-
r.pending.delete(
|
|
172
|
+
let o = i.setTimeout(() => {
|
|
173
|
+
r.pending.delete(a), d(r, `introspection timed out after ${n}ms`), t({
|
|
154
174
|
ok: !1,
|
|
155
175
|
reason: `introspection timed out after ${n}ms`
|
|
156
176
|
});
|
|
157
177
|
}, n);
|
|
158
|
-
r.pending.set(
|
|
159
|
-
clearTimeout(
|
|
178
|
+
r.pending.set(a, (e) => {
|
|
179
|
+
i.clearTimeout(o), t(e);
|
|
160
180
|
});
|
|
161
181
|
try {
|
|
162
|
-
r.proc.
|
|
163
|
-
id:
|
|
182
|
+
if (!r.proc.write(`${JSON.stringify({
|
|
183
|
+
id: a,
|
|
164
184
|
outFile: e
|
|
165
|
-
})}\n`);
|
|
185
|
+
})}\n`)) throw Error("introspect worker is not writable");
|
|
166
186
|
} catch (e) {
|
|
167
|
-
clearTimeout(
|
|
187
|
+
i.clearTimeout(o), r.pending.delete(a), r.retireAfterRequest = !0, t({
|
|
168
188
|
ok: !1,
|
|
169
189
|
reason: e instanceof Error ? e.message : String(e)
|
|
170
190
|
});
|
|
@@ -173,33 +193,33 @@ function ae(e) {
|
|
|
173
193
|
}
|
|
174
194
|
return {
|
|
175
195
|
introspect(e) {
|
|
176
|
-
let t =
|
|
177
|
-
return
|
|
196
|
+
let t = l.then(() => m(e));
|
|
197
|
+
return l = t.catch(() => void 0), t;
|
|
178
198
|
},
|
|
179
199
|
async dispose() {
|
|
180
|
-
|
|
200
|
+
s = !0, o && d(o, "introspect session disposed");
|
|
181
201
|
},
|
|
182
202
|
get childPid() {
|
|
183
|
-
return
|
|
203
|
+
return o?.proc.pid ?? null;
|
|
184
204
|
}
|
|
185
205
|
};
|
|
186
206
|
}
|
|
187
207
|
//#endregion
|
|
188
208
|
//#region src/vite/index.ts
|
|
189
|
-
var
|
|
190
|
-
function
|
|
191
|
-
if (Array.isArray(e)) return `[${e.map(
|
|
209
|
+
var D = 2;
|
|
210
|
+
function O(e) {
|
|
211
|
+
if (Array.isArray(e)) return `[${e.map(O).join(",")}]`;
|
|
192
212
|
if (typeof e == "object" && e) {
|
|
193
213
|
let t = e;
|
|
194
|
-
return `{${Object.keys(t).sort().filter((e) => t[e] !== void 0).map((e) => `${JSON.stringify(e)}:${
|
|
214
|
+
return `{${Object.keys(t).sort().filter((e) => t[e] !== void 0).map((e) => `${JSON.stringify(e)}:${O(t[e])}`).join(",")}}`;
|
|
195
215
|
}
|
|
196
216
|
return JSON.stringify(e) ?? "null";
|
|
197
217
|
}
|
|
198
|
-
function
|
|
199
|
-
return o("sha256").update(
|
|
218
|
+
function ce(e) {
|
|
219
|
+
return o("sha256").update(O(e)).digest("hex").slice(0, 16);
|
|
200
220
|
}
|
|
201
|
-
var
|
|
202
|
-
async function
|
|
221
|
+
var le = 20;
|
|
222
|
+
async function ue(e, t) {
|
|
203
223
|
if (e === void 0) return;
|
|
204
224
|
let n;
|
|
205
225
|
try {
|
|
@@ -219,7 +239,7 @@ async function D(e, t) {
|
|
|
219
239
|
let a = i.error.issues.map((e) => ` examples${e.path.length ? `[${e.path.join("][")}]` : ""}: ${e.message}`).join("\n");
|
|
220
240
|
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.`);
|
|
221
241
|
}
|
|
222
|
-
function
|
|
242
|
+
function de(e, t) {
|
|
223
243
|
if (!e?.length) return;
|
|
224
244
|
let n = e.map((e) => {
|
|
225
245
|
let t = e.label ? `"${e.label}"` : `#${e.index}`;
|
|
@@ -227,7 +247,7 @@ function O(e, t) {
|
|
|
227
247
|
}).join("\n");
|
|
228
248
|
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.`);
|
|
229
249
|
}
|
|
230
|
-
var
|
|
250
|
+
var fe = [
|
|
231
251
|
"schema",
|
|
232
252
|
"defaultConfig",
|
|
233
253
|
"examples",
|
|
@@ -240,28 +260,23 @@ var ce = [
|
|
|
240
260
|
"minSize",
|
|
241
261
|
"maxSize"
|
|
242
262
|
];
|
|
243
|
-
function
|
|
263
|
+
function pe(e, t, n) {
|
|
244
264
|
let r = l(e, "utf-8"), i = JSON.parse(r), a = {
|
|
245
265
|
...t.manifest ?? {},
|
|
246
266
|
schema: n
|
|
247
267
|
};
|
|
248
|
-
for (let e of
|
|
268
|
+
for (let e of fe) a[e] !== void 0 && (i[e] = a[e]);
|
|
249
269
|
let o = `${JSON.stringify(i, null, 2)}\n`;
|
|
250
270
|
o !== r && p(e, o);
|
|
251
271
|
}
|
|
252
|
-
var
|
|
272
|
+
var me = /import\s*(\{[^}]*\}|\*\s*as\s+[\w$]+)\s*from\s*["']@glasshome\/widget-sdk["']/g, he = /import\(\s*["']@glasshome\/widget-sdk["']\s*\)/;
|
|
253
273
|
function k(e) {
|
|
254
274
|
let t = /* @__PURE__ */ new Set();
|
|
255
|
-
|
|
256
|
-
for (let [, n = ""] of e.matchAll(
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
}
|
|
261
|
-
for (let e of n.slice(1, -1).split(",")) {
|
|
262
|
-
let n = e.trim().split(/\s+as\s+/)[0];
|
|
263
|
-
n && t.add(n);
|
|
264
|
-
}
|
|
275
|
+
he.test(e) && t.add("*");
|
|
276
|
+
for (let [, n = ""] of e.matchAll(me)) if (!n.startsWith("{")) t.add("*");
|
|
277
|
+
else for (let e of n.slice(1, -1).split(",")) {
|
|
278
|
+
let n = e.trim().split(/\s+as\s+/)[0];
|
|
279
|
+
n && t.add(n);
|
|
265
280
|
}
|
|
266
281
|
return t;
|
|
267
282
|
}
|
|
@@ -276,16 +291,16 @@ function j(e, t, n) {
|
|
|
276
291
|
}
|
|
277
292
|
async function M(e) {
|
|
278
293
|
if (!s(e.outFile)) return;
|
|
279
|
-
let t = e.session ? await e.session.introspect(e.outFile) :
|
|
294
|
+
let t = e.session ? await e.session.introspect(e.outFile) : await (e.introspect ?? E)(e.outFile);
|
|
280
295
|
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.
|
|
281
296
|
This usually means the bundle throws while being imported.`);
|
|
282
297
|
let n = t.value, r = n.manifest?.name ?? e.widgetName;
|
|
283
|
-
await
|
|
298
|
+
await ue(n.manifest?.examples, r), de(n.exampleConfigIssues, r);
|
|
284
299
|
let i = n.jsonSchema, a = e.manifestPath && s(e.manifestPath) ? e.manifestPath : null;
|
|
285
|
-
i && a &&
|
|
300
|
+
i && a && pe(a, n, i);
|
|
286
301
|
let o = a ? JSON.parse(l(a, "utf-8")).capabilities : n.manifest?.capabilities;
|
|
287
302
|
if (j(l(e.outFile, "utf-8"), o ?? [], r), !i) return;
|
|
288
|
-
let c =
|
|
303
|
+
let c = ce(i), u = n.manifest?.configVersion ?? null, d = n.manifest?.name ?? e.widgetName, f = s(e.hashFile) ? l(e.hashFile, "utf-8") : null;
|
|
289
304
|
if (f !== null) {
|
|
290
305
|
let t = f.trim(), n = null;
|
|
291
306
|
if (t.startsWith("{")) try {
|
|
@@ -293,32 +308,32 @@ async function M(e) {
|
|
|
293
308
|
} catch {
|
|
294
309
|
n = null;
|
|
295
310
|
}
|
|
296
|
-
if (n && n.hashVersion ===
|
|
311
|
+
if (n && n.hashVersion === D) {
|
|
297
312
|
if (n.hash !== c && n.configVersion === u) throw Error(`[widget-sdk] Config schema shape changed for "${d}" without a configVersion bump. Bump configVersion in defineWidget (currently ${u ?? "unset"}) or revert the schema change, then rebuild. Recorded in ${e.hashFile}`);
|
|
298
|
-
} else console.warn(`[widget-sdk] Schema shape record for "${d}" was written by an older SDK, so it cannot be compared. Re-recording it under hash format ${
|
|
313
|
+
} else console.warn(`[widget-sdk] Schema shape record for "${d}" was written by an older SDK, so it cannot be compared. Re-recording it under hash format ${D}. This build is not checked for a missing configVersion bump; the next one is. (${e.hashFile})`);
|
|
299
314
|
}
|
|
300
315
|
let m = `${JSON.stringify({
|
|
301
316
|
hash: c,
|
|
302
317
|
configVersion: u,
|
|
303
|
-
hashVersion:
|
|
318
|
+
hashVersion: D
|
|
304
319
|
})}\n`;
|
|
305
320
|
m !== f && p(e.hashFile, m);
|
|
306
321
|
}
|
|
307
|
-
var
|
|
308
|
-
function
|
|
322
|
+
var ge = "virtual:glasshome-widget", N = "\0virtual:glasshome-widget", P = "/@glasshome/preview";
|
|
323
|
+
function F(e) {
|
|
309
324
|
return y === "\\" ? e.split(y).join("/") : e;
|
|
310
325
|
}
|
|
311
|
-
function
|
|
326
|
+
function I() {
|
|
312
327
|
let e = b(import.meta.url);
|
|
313
328
|
return v(h(e), "../../preview");
|
|
314
329
|
}
|
|
315
|
-
function
|
|
330
|
+
function L(e) {
|
|
316
331
|
return r(e);
|
|
317
332
|
}
|
|
318
|
-
var
|
|
333
|
+
var R = /\.(ts|tsx|js|jsx)$/, _e = /from\s+["']@glasshome\/sync-layer(\/[^"']*)?["']/;
|
|
319
334
|
function z(e, t) {
|
|
320
|
-
let n =
|
|
321
|
-
return n.includes("/node_modules/") || !
|
|
335
|
+
let n = F(e).split("?")[0] ?? "";
|
|
336
|
+
return n.includes("/node_modules/") || !R.test(n) ? !1 : _e.test(t);
|
|
322
337
|
}
|
|
323
338
|
function B() {
|
|
324
339
|
return {
|
|
@@ -326,14 +341,14 @@ function B() {
|
|
|
326
341
|
apply: "build",
|
|
327
342
|
enforce: "pre",
|
|
328
343
|
transform(e, t) {
|
|
329
|
-
if (z(t, e)) throw Error(`Widgets must not import "@glasshome/sync-layer" directly (imported by ${
|
|
344
|
+
if (z(t, e)) throw Error(`Widgets must not import "@glasshome/sync-layer" directly (imported by ${F(_(process.cwd(), t.split("?")[0] ?? t))}). Import the equivalent hook from "@glasshome/widget-sdk" instead (e.g. useEntity, useEntities, useService).`);
|
|
330
345
|
return null;
|
|
331
346
|
}
|
|
332
347
|
};
|
|
333
348
|
}
|
|
334
349
|
function V(t, n) {
|
|
335
|
-
let r =
|
|
336
|
-
if (r.includes("/node_modules/") || !
|
|
350
|
+
let r = F(t).split("?")[0] ?? "";
|
|
351
|
+
if (r.includes("/node_modules/") || !R.test(r)) return !1;
|
|
337
352
|
let i = e.find((e) => e.id === "direct-ui-import");
|
|
338
353
|
return i?.sourcePattern ? new RegExp(i.sourcePattern).test(n) : !1;
|
|
339
354
|
}
|
|
@@ -341,7 +356,7 @@ function H(e = /* @__PURE__ */ new Set()) {
|
|
|
341
356
|
let t = /* @__PURE__ */ new Set();
|
|
342
357
|
return {
|
|
343
358
|
scan(e, n) {
|
|
344
|
-
V(e, n) && t.add(
|
|
359
|
+
V(e, n) && t.add(F(_(process.cwd(), e.split("?")[0] ?? e)));
|
|
345
360
|
},
|
|
346
361
|
take() {
|
|
347
362
|
let n = [...t].filter((t) => !e.has(t));
|
|
@@ -367,7 +382,7 @@ function U(n) {
|
|
|
367
382
|
}
|
|
368
383
|
};
|
|
369
384
|
}
|
|
370
|
-
var
|
|
385
|
+
var ve = "node_modules/.cache/glasshome-widgets";
|
|
371
386
|
function W(e) {
|
|
372
387
|
try {
|
|
373
388
|
return m(g(process.cwd(), "package.json")).resolve(e);
|
|
@@ -375,7 +390,7 @@ function W(e) {
|
|
|
375
390
|
return null;
|
|
376
391
|
}
|
|
377
392
|
}
|
|
378
|
-
var
|
|
393
|
+
var ye = [
|
|
379
394
|
"--radius",
|
|
380
395
|
"--background",
|
|
381
396
|
"--foreground",
|
|
@@ -394,7 +409,7 @@ function K(e, t) {
|
|
|
394
409
|
let r = l(n, "utf-8"), i = G(r);
|
|
395
410
|
i !== r && p(n, i);
|
|
396
411
|
for (let e of i.matchAll(/:host[^{]*\{([^}]*)\}/g)) {
|
|
397
|
-
let n = e[1] ?? "", r =
|
|
412
|
+
let n = e[1] ?? "", r = ye.find((e) => n.includes(`${e}:`));
|
|
398
413
|
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.`);
|
|
399
414
|
}
|
|
400
415
|
}
|
|
@@ -403,7 +418,7 @@ function q(e, t) {
|
|
|
403
418
|
return [r, ...u(n, { withFileTypes: !0 }).filter((e) => e.isDirectory()).map((e) => g(n, e.name)).filter((e) => !i.has(e))];
|
|
404
419
|
}
|
|
405
420
|
function J(e, t, n, r) {
|
|
406
|
-
let i = v(e,
|
|
421
|
+
let i = v(e, ve);
|
|
407
422
|
c(i, { recursive: !0 });
|
|
408
423
|
let a = W("@glasshome/ui/styles");
|
|
409
424
|
if (!a) 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.");
|
|
@@ -417,7 +432,7 @@ function J(e, t, n, r) {
|
|
|
417
432
|
"@import \"tailwindcss\" source(none);",
|
|
418
433
|
"@import \"tw-animate-css\";",
|
|
419
434
|
"@import \"@glasshome/ui/styles/theme\";",
|
|
420
|
-
...d.map((e) => `@source "${
|
|
435
|
+
...d.map((e) => `@source "${F(e)}";`),
|
|
421
436
|
"@custom-variant dark {",
|
|
422
437
|
" &:is(.dark *) { @slot }",
|
|
423
438
|
" :host(.dark) & { @slot }",
|
|
@@ -426,8 +441,8 @@ function J(e, t, n, r) {
|
|
|
426
441
|
].join("\n"));
|
|
427
442
|
let m = v(i, `${t}.entry.ts`);
|
|
428
443
|
return p(m, [
|
|
429
|
-
`import "${
|
|
430
|
-
`export { default } from "${
|
|
444
|
+
`import "${F(f)}";`,
|
|
445
|
+
`export { default } from "${F(n)}";`,
|
|
431
446
|
""
|
|
432
447
|
].join("\n")), m;
|
|
433
448
|
}
|
|
@@ -510,7 +525,7 @@ async function $(e) {
|
|
|
510
525
|
fileName: s.name,
|
|
511
526
|
cssFileName: s.name
|
|
512
527
|
},
|
|
513
|
-
rollupOptions: { external:
|
|
528
|
+
rollupOptions: { external: L },
|
|
514
529
|
outDir: i,
|
|
515
530
|
emptyOutDir: !1,
|
|
516
531
|
copyPublicDir: !1,
|
|
@@ -526,7 +541,7 @@ async function $(e) {
|
|
|
526
541
|
});
|
|
527
542
|
Q(r, i);
|
|
528
543
|
}
|
|
529
|
-
function
|
|
544
|
+
function be(e) {
|
|
530
545
|
let t = e?.entry ?? "src/index.tsx", n = {
|
|
531
546
|
name: "glasshome-widget:build",
|
|
532
547
|
apply: "build",
|
|
@@ -541,7 +556,7 @@ function ge(e) {
|
|
|
541
556
|
fileName: "index",
|
|
542
557
|
cssFileName: "index"
|
|
543
558
|
},
|
|
544
|
-
rollupOptions: { external:
|
|
559
|
+
rollupOptions: { external: L }
|
|
545
560
|
}
|
|
546
561
|
};
|
|
547
562
|
}
|
|
@@ -550,7 +565,7 @@ function ge(e) {
|
|
|
550
565
|
apply: "serve",
|
|
551
566
|
enforce: "pre",
|
|
552
567
|
config() {
|
|
553
|
-
let e =
|
|
568
|
+
let e = I(), t = process.cwd();
|
|
554
569
|
return { server: { fs: { allow: [
|
|
555
570
|
e,
|
|
556
571
|
t,
|
|
@@ -558,7 +573,7 @@ function ge(e) {
|
|
|
558
573
|
] } } };
|
|
559
574
|
},
|
|
560
575
|
configureServer(e) {
|
|
561
|
-
let t =
|
|
576
|
+
let t = I(), n = g(t, "preview.html");
|
|
562
577
|
e.middlewares.use(async (t, r, i) => {
|
|
563
578
|
if (t.url === "/" || t.url === "/index.html") try {
|
|
564
579
|
let i = l(n, "utf-8");
|
|
@@ -570,14 +585,14 @@ function ge(e) {
|
|
|
570
585
|
});
|
|
571
586
|
},
|
|
572
587
|
resolveId(e) {
|
|
573
|
-
if (e ===
|
|
574
|
-
let e =
|
|
575
|
-
return
|
|
588
|
+
if (e === P) {
|
|
589
|
+
let e = I();
|
|
590
|
+
return F(g(e, "host.tsx"));
|
|
576
591
|
}
|
|
577
|
-
if (e ===
|
|
592
|
+
if (e === ge) return N;
|
|
578
593
|
},
|
|
579
594
|
load(e) {
|
|
580
|
-
if (e === N) return `export { default } from "${
|
|
595
|
+
if (e === N) return `export { default } from "${F(v(process.cwd(), t))}";`;
|
|
581
596
|
}
|
|
582
597
|
}, i = {
|
|
583
598
|
name: "glasshome-widget:schema",
|
|
@@ -600,7 +615,7 @@ function ge(e) {
|
|
|
600
615
|
r
|
|
601
616
|
];
|
|
602
617
|
}
|
|
603
|
-
function
|
|
618
|
+
function xe(e) {
|
|
604
619
|
let t = e?.srcDir ?? "src", n = e?.outDir ?? "dist", r = [];
|
|
605
620
|
return [{
|
|
606
621
|
name: "glasshome-widgets:build",
|
|
@@ -628,4 +643,4 @@ function _e(e) {
|
|
|
628
643
|
}];
|
|
629
644
|
}
|
|
630
645
|
//#endregion
|
|
631
|
-
export { A as HOOK_READS,
|
|
646
|
+
export { A as HOOK_READS, le as MAX_EXAMPLES, j as assertHookReadsDeclared, $ as buildWidgets, se as createIntrospectSession, H as createUiImportTracker, Z as discoverWidgets, G as dropSelfReferencingVars, Q as generateRegistry, be as glasshomeWidget, xe as glasshomeWidgets, E as introspectOnce, z as isDirectSyncLayerImportSource, V as isDirectUiImportSource, L as isWidgetExternal, M as runSchemaGuard, k as sdkImportsOf, q as widgetProjectScanDirs };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Clock } from "@glasshome/widget-contract/clock";
|
|
1
2
|
import type { WidgetIntrospection } from "./introspect-core";
|
|
2
3
|
export type IntrospectResult = {
|
|
3
4
|
ok: true;
|
|
@@ -13,6 +14,15 @@ export interface IntrospectSessionOptions {
|
|
|
13
14
|
timeoutMs?: number;
|
|
14
15
|
/** Log spawn and import durations above this. */
|
|
15
16
|
slowMs?: number;
|
|
17
|
+
clock?: Clock;
|
|
18
|
+
spawnWorker?: (probe: string) => WorkerTransport;
|
|
19
|
+
}
|
|
20
|
+
export interface WorkerTransport {
|
|
21
|
+
write(line: string): boolean;
|
|
22
|
+
onLine(cb: (line: string) => void): void;
|
|
23
|
+
onExit(cb: (reason: string) => void): void;
|
|
24
|
+
kill(): void;
|
|
25
|
+
readonly pid: number | null;
|
|
16
26
|
}
|
|
17
27
|
export interface IntrospectSession {
|
|
18
28
|
introspect(outFile: string): Promise<IntrospectResult>;
|
|
@@ -20,7 +30,9 @@ export interface IntrospectSession {
|
|
|
20
30
|
readonly childPid: number | null;
|
|
21
31
|
}
|
|
22
32
|
/** One process per check. The path `build`, `capture` and the fallback take. */
|
|
23
|
-
export declare function introspectOnce(outFile: string
|
|
33
|
+
export declare function introspectOnce(outFile: string, options?: {
|
|
34
|
+
timeoutMs?: number;
|
|
35
|
+
}): IntrospectResult;
|
|
24
36
|
/**
|
|
25
37
|
* A worker reused across rebuilds, for callers that own a session.
|
|
26
38
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glasshome/widget-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.23.0",
|
|
4
4
|
"description": "SDK for building GlassHome dashboard widgets with SolidJS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dashboard",
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"lint": "oxlint --type-aware . && oxfmt --check ."
|
|
76
76
|
},
|
|
77
77
|
"dependencies": {
|
|
78
|
-
"@glasshome/widget-contract": "0.
|
|
78
|
+
"@glasshome/widget-contract": "0.4.0",
|
|
79
79
|
"@tailwindcss/vite": "^4.1.13",
|
|
80
80
|
"clsx": "^2.1.1",
|
|
81
81
|
"happy-dom": "^20.0.0",
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
"zod": "^4.1.13"
|
|
86
86
|
},
|
|
87
87
|
"devDependencies": {
|
|
88
|
-
"@glasshome/ui": "1.
|
|
88
|
+
"@glasshome/ui": "1.33.0",
|
|
89
89
|
"@solidjs/testing-library": "^0.8.10",
|
|
90
90
|
"@types/bun": "^1.4.0",
|
|
91
91
|
"@types/node": "^25.2.2",
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
},
|
|
101
101
|
"peerDependencies": {
|
|
102
102
|
"@glasshome/sync-layer": "0.9.1",
|
|
103
|
-
"@glasshome/ui": "1.
|
|
103
|
+
"@glasshome/ui": "1.30.0",
|
|
104
104
|
"solid-js": "^1.9.11"
|
|
105
105
|
},
|
|
106
106
|
"engines": {
|