@imfusion/web-ui 0.10.1-dev.34.gb01a818e → 0.10.1-dev.41.g467e0e1a
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/CHANGELOG.md +28 -2
- package/README.md +19 -16
- package/dist/components/app-shell/app-shell.d.ts +35 -23
- package/dist/components/select/select.d.ts +7 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/use-disclosure.d.ts +17 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1849 -1746
- package/dist/paths-CZtwNknt.js +132 -0
- package/dist/style.css +1 -1
- package/dist/vite/local-web-ui-link.d.ts +7 -3
- package/dist/vite.js +38 -22
- package/dist/web-ui-cli.js +154 -122
- package/package.json +2 -2
- package/src/docgen/doc.gen.json +25 -66
- package/src/llms/skills/imf-web-ui/SKILL.md +15 -13
- package/src/llms/skills/imf-web-ui-audit/SKILL.md +2 -1
- package/src/llms/skills/imf-web-ui-conventions/SKILL.md +24 -23
- package/src/llms/skills/imf-web-ui-conventions/templates/AUDIT_CHECKLIST.md +1 -1
- package/src/llms/skills/imf-web-ui-conventions/topics/data.md +4 -2
- package/src/llms/skills/imf-web-ui-conventions/topics/tooling.md +32 -4
- package/src/llms/skills/imf-web-ui-setup/SKILL.md +8 -1
- package/dist/paths-B5Ht3ETc.js +0 -26
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { Plugin, UserConfig } from 'vite';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Returns `undefined` for an installed package that `web-ui link` has not claimed. A linked package is excluded from
|
|
4
|
+
* dependency pre-bundling so its rebuilt files are served directly. A checkout outside `node_modules` gets peer dedupe.
|
|
5
|
+
*/
|
|
3
6
|
export declare function localWebUILinkConfig(root: string): UserConfig | undefined;
|
|
4
7
|
/**
|
|
5
|
-
* Lets a consumer
|
|
6
|
-
*
|
|
8
|
+
* Lets a consumer keep `localWebUILink()` registered for good. With no link it does nothing for an installed package.
|
|
9
|
+
* After `npx web-ui link <checkout>` it serves the linked build and reloads the page on each rebuild. Server rendering
|
|
10
|
+
* is not covered.
|
|
7
11
|
*/
|
|
8
12
|
export declare function localWebUILink(): Plugin;
|
package/dist/vite.js
CHANGED
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
import { n as e } from "./paths-
|
|
2
|
-
import { readFileSync as
|
|
3
|
-
import { dirname as
|
|
4
|
-
import { fileURLToPath as
|
|
1
|
+
import { n as e, s as t } from "./paths-CZtwNknt.js";
|
|
2
|
+
import { existsSync as n, readFileSync as r, readdirSync as i, realpathSync as a, statSync as o, watch as s } from "node:fs";
|
|
3
|
+
import { dirname as c, join as l, resolve as u, sep as d } from "node:path";
|
|
4
|
+
import { fileURLToPath as f } from "node:url";
|
|
5
5
|
//#region src/vite/brand-assets.ts
|
|
6
|
-
var
|
|
6
|
+
var p = c(f(import.meta.resolve("@imfusion/web-ui/assets/favicon/favicon.svg"))), m = i(p).map((e) => ({
|
|
7
7
|
name: e,
|
|
8
|
-
source:
|
|
9
|
-
})),
|
|
8
|
+
source: r(l(p, e))
|
|
9
|
+
})), h = {
|
|
10
10
|
".ico": "image/x-icon",
|
|
11
11
|
".png": "image/png",
|
|
12
12
|
".svg": "image/svg+xml"
|
|
13
13
|
};
|
|
14
|
-
function
|
|
15
|
-
return
|
|
14
|
+
function g(e) {
|
|
15
|
+
return h[e.slice(e.lastIndexOf("."))] ?? "application/octet-stream";
|
|
16
16
|
}
|
|
17
|
-
function
|
|
17
|
+
function _() {
|
|
18
18
|
return {
|
|
19
19
|
name: "imf-ui:brand-assets",
|
|
20
20
|
configureServer(e) {
|
|
21
21
|
e.middlewares.use((e, t, n) => {
|
|
22
|
-
let r =
|
|
22
|
+
let r = m.find(({ name: t }) => e.url?.split("?")[0] === `/${t}`);
|
|
23
23
|
if (!r) {
|
|
24
24
|
n();
|
|
25
25
|
return;
|
|
26
26
|
}
|
|
27
|
-
t.setHeader("Content-Type",
|
|
27
|
+
t.setHeader("Content-Type", g(r.name)), t.end(r.source);
|
|
28
28
|
});
|
|
29
29
|
},
|
|
30
30
|
generateBundle() {
|
|
31
|
-
for (let e of
|
|
31
|
+
for (let e of m) this.emitFile({
|
|
32
32
|
fileName: e.name,
|
|
33
33
|
source: e.source,
|
|
34
34
|
type: "asset"
|
|
@@ -38,33 +38,49 @@ function p() {
|
|
|
38
38
|
}
|
|
39
39
|
//#endregion
|
|
40
40
|
//#region src/vite/local-web-ui-link.ts
|
|
41
|
-
function
|
|
42
|
-
if (
|
|
43
|
-
|
|
41
|
+
function v(e) {
|
|
42
|
+
if (t(e)) return { optimizeDeps: {
|
|
43
|
+
exclude: ["@imfusion/web-ui"],
|
|
44
|
+
include: ["use-sync-external-store/shim", "use-sync-external-store/shim/with-selector"]
|
|
45
|
+
} };
|
|
46
|
+
if (a(e).split(d).includes("node_modules")) return;
|
|
47
|
+
let n = JSON.parse(r(u(e, "package.json"), "utf-8")), i = typeof n == "object" && n ? Reflect.get(n, "peerDependencies") : {};
|
|
44
48
|
if (typeof i != "object" || !i) throw Error(`${e}/package.json has no peerDependencies`);
|
|
45
49
|
return { resolve: { dedupe: Object.keys(i) } };
|
|
46
50
|
}
|
|
47
|
-
function
|
|
51
|
+
function y() {
|
|
48
52
|
return {
|
|
49
53
|
name: "imf-ui:local-web-ui-link",
|
|
50
|
-
config: () =>
|
|
54
|
+
config: () => v(e),
|
|
55
|
+
configureServer(r) {
|
|
56
|
+
if (!t(e)) return;
|
|
57
|
+
let i = u(e, "dist"), a = /* @__PURE__ */ new Set(), c, l = s(i, { recursive: !0 }, (e, t) => {
|
|
58
|
+
t && a.add(u(i, t)), clearTimeout(c), c = setTimeout(() => {
|
|
59
|
+
for (let e of a) n(e) && o(e).isFile() && r.watcher.emit("change", e);
|
|
60
|
+
a.clear();
|
|
61
|
+
}, 100);
|
|
62
|
+
});
|
|
63
|
+
r.httpServer?.once("close", () => {
|
|
64
|
+
clearTimeout(c), l.close();
|
|
65
|
+
});
|
|
66
|
+
}
|
|
51
67
|
};
|
|
52
68
|
}
|
|
53
69
|
//#endregion
|
|
54
70
|
//#region src/vite/readable-css-module-names.ts
|
|
55
|
-
function
|
|
71
|
+
function b(e, t) {
|
|
56
72
|
let { lightningcss: n, modules: r, transformer: i } = e.css ?? {}, a = n?.cssModules;
|
|
57
73
|
if (typeof a != "boolean" && r !== !1 && !a?.pattern && !(typeof r == "object" && r.generateScopedName)) return i === "postcss" ? { css: { modules: { generateScopedName: t } } } : { css: {
|
|
58
74
|
transformer: "lightningcss",
|
|
59
75
|
lightningcss: { cssModules: { pattern: t } }
|
|
60
76
|
} };
|
|
61
77
|
}
|
|
62
|
-
function
|
|
78
|
+
function x({ prefix: e }) {
|
|
63
79
|
let t = `${e}-[name]-[local]`;
|
|
64
80
|
return {
|
|
65
81
|
name: "imf-ui:readable-css-module-names",
|
|
66
|
-
config: (e) =>
|
|
82
|
+
config: (e) => b(e, t)
|
|
67
83
|
};
|
|
68
84
|
}
|
|
69
85
|
//#endregion
|
|
70
|
-
export {
|
|
86
|
+
export { _ as imfusionBrandAssets, y as localWebUILink, x as readableCssModuleNames };
|
package/dist/web-ui-cli.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import { chmodSync as
|
|
4
|
-
import { dirname as
|
|
5
|
-
import { Command as
|
|
6
|
-
import * as
|
|
7
|
-
var
|
|
2
|
+
import { a as e, c as t, i as n, n as r, o as i, r as a, t as o } from "./paths-CZtwNknt.js";
|
|
3
|
+
import { chmodSync as s, cpSync as c, existsSync as l, lstatSync as u, mkdirSync as d, readFileSync as f, readdirSync as p, readlinkSync as ee, realpathSync as m, rmSync as h, symlinkSync as te, writeFileSync as g } from "node:fs";
|
|
4
|
+
import { dirname as ne, relative as _, resolve as v } from "node:path";
|
|
5
|
+
import { Command as re, Option as ie } from "commander";
|
|
6
|
+
import * as y from "@clack/prompts";
|
|
7
|
+
var b = {
|
|
8
8
|
harnesses: {
|
|
9
9
|
claude: {
|
|
10
10
|
label: "Claude Code",
|
|
@@ -24,91 +24,91 @@ var y = {
|
|
|
24
24
|
skillsDir: ".agents/skills",
|
|
25
25
|
linkDir: ".claude/skills",
|
|
26
26
|
versionMarker: ".imf-web-ui-skill-version.json"
|
|
27
|
-
},
|
|
28
|
-
function
|
|
29
|
-
let t = e.indexOf(
|
|
30
|
-
return t === -1 || n === -1 ? null : e.slice(t, n +
|
|
27
|
+
}, ae = `<!-- ${b.namespace}:begin`, x = `<!-- ${b.namespace}:end -->`, oe = v(r, b.templatesDir, "AGENTS.md"), S = v(a, "AGENTS.md");
|
|
28
|
+
function C(e) {
|
|
29
|
+
let t = e.indexOf(ae), n = e.indexOf(x);
|
|
30
|
+
return t === -1 || n === -1 ? null : e.slice(t, n + x.length);
|
|
31
31
|
}
|
|
32
|
-
function
|
|
33
|
-
if (!
|
|
34
|
-
let e =
|
|
32
|
+
function se() {
|
|
33
|
+
if (!l(S)) return "absent";
|
|
34
|
+
let e = C(f(oe, "utf-8"));
|
|
35
35
|
if (!e) return "absent";
|
|
36
|
-
let t =
|
|
37
|
-
return r === t ? "unchanged" : (
|
|
36
|
+
let t = f(S, "utf-8"), n = C(t), r = n ? t.replace(n, e) : `${t.trimEnd()}\n\n${e}\n`;
|
|
37
|
+
return r === t ? "unchanged" : (g(S, r), n ? "updated" : "added");
|
|
38
38
|
}
|
|
39
39
|
//#endregion
|
|
40
40
|
//#region src/cli/skills.ts
|
|
41
|
-
var
|
|
41
|
+
var w = Object.keys(b.harnesses).filter((e) => e in b.harnesses), ce = [...w, "all"];
|
|
42
42
|
function T(e) {
|
|
43
|
-
return e === "all" ?
|
|
43
|
+
return e === "all" ? w : [e];
|
|
44
44
|
}
|
|
45
45
|
function E(e) {
|
|
46
|
-
return `./${
|
|
46
|
+
return `./${_(a, e)}`;
|
|
47
47
|
}
|
|
48
|
-
var D =
|
|
49
|
-
if (typeof N != "object" || !N || !("version" in N) || typeof N.version != "string") throw Error(`${
|
|
48
|
+
var D = b.namespace, O = b.versionMarker, k = v(r, b.skillsSource), A = v(a, b.skillsDir), j = v(a, b.linkDir), M = class extends Error {}, N = JSON.parse(f(v(r, "package.json"), "utf-8"));
|
|
49
|
+
if (typeof N != "object" || !N || !("version" in N) || typeof N.version != "string") throw Error(`${v(r, "package.json")} has no string "version" field`);
|
|
50
50
|
var P = N.version;
|
|
51
51
|
function F(e) {
|
|
52
52
|
return e === D || e.startsWith(`${D}-`);
|
|
53
53
|
}
|
|
54
54
|
function I() {
|
|
55
|
-
return
|
|
55
|
+
return l(k) ? p(k, { withFileTypes: !0 }).filter((e) => e.isDirectory() && F(e.name)).map((e) => e.name).sort() : [];
|
|
56
56
|
}
|
|
57
|
-
function
|
|
58
|
-
let t =
|
|
59
|
-
if (!
|
|
57
|
+
function le(e) {
|
|
58
|
+
let t = v(A, e, O);
|
|
59
|
+
if (!l(t)) return null;
|
|
60
60
|
try {
|
|
61
|
-
let e = JSON.parse(
|
|
61
|
+
let e = JSON.parse(f(t, "utf-8"));
|
|
62
62
|
if (typeof e != "object" || !e) return null;
|
|
63
63
|
let n = "harnesses" in e && Array.isArray(e.harnesses) ? e.harnesses : null;
|
|
64
|
-
return n ?
|
|
64
|
+
return n ? w.filter((e) => n.includes(e)) : null;
|
|
65
65
|
} catch {
|
|
66
66
|
return null;
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
function L(e) {
|
|
70
70
|
for (let t of e) {
|
|
71
|
-
let e =
|
|
71
|
+
let e = le(t);
|
|
72
72
|
if (e && e.length > 0) return e;
|
|
73
73
|
}
|
|
74
74
|
return null;
|
|
75
75
|
}
|
|
76
76
|
function R(e, t, n) {
|
|
77
|
-
if (
|
|
77
|
+
if (l(e)) for (let r of p(e).filter(F)) t.has(r) || (h(v(e, r), {
|
|
78
78
|
recursive: !0,
|
|
79
79
|
force: !0
|
|
80
|
-
}),
|
|
80
|
+
}), y.log.info(`Removed skill: ${r} (${n})`));
|
|
81
81
|
}
|
|
82
|
-
function
|
|
83
|
-
return
|
|
82
|
+
function ue() {
|
|
83
|
+
return l(j) && l(A) && m(j) === m(A);
|
|
84
84
|
}
|
|
85
|
-
function
|
|
86
|
-
let t =
|
|
87
|
-
r?.isSymbolicLink() &&
|
|
85
|
+
function de(e) {
|
|
86
|
+
let t = v(j, e), n = _(j, v(A, e)), r = u(t, { throwIfNoEntry: !1 });
|
|
87
|
+
r?.isSymbolicLink() && ee(t) === n || (r && h(t, {
|
|
88
88
|
recursive: !0,
|
|
89
89
|
force: !0
|
|
90
|
-
}),
|
|
90
|
+
}), d(j, { recursive: !0 }), te(n, t));
|
|
91
91
|
}
|
|
92
|
-
function
|
|
92
|
+
function fe(e, t) {
|
|
93
93
|
try {
|
|
94
|
-
|
|
95
|
-
let
|
|
96
|
-
for (let
|
|
97
|
-
let e =
|
|
98
|
-
|
|
94
|
+
d(A, { recursive: !0 });
|
|
95
|
+
let n = [];
|
|
96
|
+
for (let r of e) {
|
|
97
|
+
let e = v(A, r);
|
|
98
|
+
h(e, {
|
|
99
99
|
recursive: !0,
|
|
100
100
|
force: !0
|
|
101
|
-
}),
|
|
102
|
-
let
|
|
103
|
-
|
|
101
|
+
}), c(v(k, r), e, { recursive: !0 });
|
|
102
|
+
let i = v(e, O);
|
|
103
|
+
g(i, JSON.stringify({
|
|
104
104
|
version: P,
|
|
105
105
|
harnesses: t
|
|
106
|
-
}, null, 2) + "\n"),
|
|
106
|
+
}, null, 2) + "\n"), n.push(i);
|
|
107
107
|
}
|
|
108
|
-
if (n
|
|
108
|
+
if (o(n), R(A, new Set(e), "no longer in this bundle"), y.log.success(`Skills -> ${E(A)}/${D}*`), ue()) return;
|
|
109
109
|
if (t.includes("claude")) {
|
|
110
|
-
for (let t of e)
|
|
111
|
-
R(j, new Set(e), "no longer in this bundle"),
|
|
110
|
+
for (let t of e) de(t);
|
|
111
|
+
R(j, new Set(e), "no longer in this bundle"), y.log.success(`Claude Code -> ${E(j)}/${D}* (symlinks -> ${E(A)})`);
|
|
112
112
|
} else R(j, /* @__PURE__ */ new Set(), "claude not selected");
|
|
113
113
|
} catch (e) {
|
|
114
114
|
throw e instanceof Error ? new M(e.message) : e;
|
|
@@ -116,68 +116,68 @@ function se(e, t) {
|
|
|
116
116
|
}
|
|
117
117
|
//#endregion
|
|
118
118
|
//#region src/cli/hooks.ts
|
|
119
|
-
var
|
|
120
|
-
function
|
|
121
|
-
if (typeof e != "object" || !e || Array.isArray(e)) throw new
|
|
119
|
+
var z = v(r, b.templatesDir), B = v(z, "hooks"), V = v(a, b.hooksDir), H = class extends Error {};
|
|
120
|
+
function pe(e, t) {
|
|
121
|
+
if (typeof e != "object" || !e || Array.isArray(e)) throw new H(`${t} is not a JSON object.`);
|
|
122
122
|
let n = { ...e };
|
|
123
123
|
if ("hooks" in n) {
|
|
124
|
-
if (typeof n.hooks != "object" || n.hooks === null || Array.isArray(n.hooks)) throw new
|
|
125
|
-
for (let [e, r] of Object.entries(n.hooks)) if (!Array.isArray(r)) throw new
|
|
124
|
+
if (typeof n.hooks != "object" || n.hooks === null || Array.isArray(n.hooks)) throw new H(`${t}: "hooks" is not a JSON object.`);
|
|
125
|
+
for (let [e, r] of Object.entries(n.hooks)) if (!Array.isArray(r)) throw new H(`${t}: "hooks.${e}" is not a JSON array.`);
|
|
126
126
|
}
|
|
127
127
|
return n;
|
|
128
128
|
}
|
|
129
|
-
function
|
|
129
|
+
function U(e) {
|
|
130
130
|
let t;
|
|
131
131
|
try {
|
|
132
|
-
t = JSON.parse(
|
|
132
|
+
t = JSON.parse(f(e, "utf-8"));
|
|
133
133
|
} catch {
|
|
134
|
-
throw new
|
|
134
|
+
throw new H(`${e} is not valid JSON.`);
|
|
135
135
|
}
|
|
136
|
-
return
|
|
136
|
+
return pe(t, e);
|
|
137
137
|
}
|
|
138
|
-
function
|
|
139
|
-
let e =
|
|
140
|
-
|
|
138
|
+
function me() {
|
|
139
|
+
let e = p(B).filter((e) => e.endsWith(".sh"));
|
|
140
|
+
d(V, { recursive: !0 });
|
|
141
141
|
for (let t of e) {
|
|
142
|
-
let e =
|
|
143
|
-
|
|
142
|
+
let e = v(V, t);
|
|
143
|
+
c(v(B, t), e, { force: !0 }), s(e, 493);
|
|
144
144
|
}
|
|
145
|
-
let t =
|
|
146
|
-
for (let e of t)
|
|
145
|
+
let t = p(V).filter((t) => t.endsWith(".sh") && !e.includes(t));
|
|
146
|
+
for (let e of t) h(v(V, e), { force: !0 });
|
|
147
147
|
return {
|
|
148
148
|
installed: e,
|
|
149
149
|
removed: t
|
|
150
150
|
};
|
|
151
151
|
}
|
|
152
|
-
var
|
|
153
|
-
function
|
|
152
|
+
var W = `${b.hooksDir}/`;
|
|
153
|
+
function G(e) {
|
|
154
154
|
if (typeof e != "string") return null;
|
|
155
|
-
let t = e.lastIndexOf(
|
|
155
|
+
let t = e.lastIndexOf(W);
|
|
156
156
|
if (t === -1) return null;
|
|
157
|
-
let n = /^([\w.-]+)["']?$/.exec(e.slice(t +
|
|
157
|
+
let n = /^([\w.-]+)["']?$/.exec(e.slice(t + W.length));
|
|
158
158
|
return n ? n[1] : null;
|
|
159
159
|
}
|
|
160
|
-
function
|
|
160
|
+
function K(e) {
|
|
161
161
|
return typeof e == "object" && !!e && "hooks" in e && Array.isArray(e.hooks);
|
|
162
162
|
}
|
|
163
|
-
function
|
|
164
|
-
return
|
|
163
|
+
function q(e) {
|
|
164
|
+
return K(e) ? e.hooks : null;
|
|
165
165
|
}
|
|
166
|
-
function
|
|
166
|
+
function J(e) {
|
|
167
167
|
return typeof e == "object" && e && "command" in e ? e.command : void 0;
|
|
168
168
|
}
|
|
169
|
-
function
|
|
170
|
-
let t =
|
|
171
|
-
return t ? t.map((e) =>
|
|
169
|
+
function Y(e) {
|
|
170
|
+
let t = q(e);
|
|
171
|
+
return t ? t.map((e) => G(J(e))).filter((e) => e !== null) : [];
|
|
172
172
|
}
|
|
173
|
-
function
|
|
173
|
+
function he(e, t, n) {
|
|
174
174
|
e.hooks ??= {};
|
|
175
175
|
let r = 0, i = 0, a = [];
|
|
176
176
|
for (let [r, o] of Object.entries(e.hooks)) {
|
|
177
177
|
let s = 0, c = o.map((e) => {
|
|
178
|
-
if (!
|
|
178
|
+
if (!K(e)) return e;
|
|
179
179
|
let t = e.hooks, r = t.filter((e) => {
|
|
180
|
-
let t =
|
|
180
|
+
let t = G(J(e));
|
|
181
181
|
return t === null || n.includes(t);
|
|
182
182
|
});
|
|
183
183
|
return s += t.length - r.length, r.length === t.length ? e : {
|
|
@@ -185,7 +185,7 @@ function ue(e, t, n) {
|
|
|
185
185
|
hooks: r
|
|
186
186
|
};
|
|
187
187
|
}).filter((e) => {
|
|
188
|
-
let t =
|
|
188
|
+
let t = q(e);
|
|
189
189
|
return t === null || t.length > 0;
|
|
190
190
|
});
|
|
191
191
|
s !== 0 && (i += s, c.length === 0 && !(r in t) ? a.push(r) : e.hooks[r] = c);
|
|
@@ -194,8 +194,8 @@ function ue(e, t, n) {
|
|
|
194
194
|
for (let [n, i] of Object.entries(t)) {
|
|
195
195
|
e.hooks[n] ??= [];
|
|
196
196
|
for (let t of i) {
|
|
197
|
-
let i =
|
|
198
|
-
e.hooks[n].some((e) =>
|
|
197
|
+
let i = Y(t);
|
|
198
|
+
e.hooks[n].some((e) => Y(e).some((e) => i.includes(e))) || (e.hooks[n].push(t), r++);
|
|
199
199
|
}
|
|
200
200
|
}
|
|
201
201
|
return {
|
|
@@ -203,72 +203,72 @@ function ue(e, t, n) {
|
|
|
203
203
|
removed: i
|
|
204
204
|
};
|
|
205
205
|
}
|
|
206
|
-
function
|
|
207
|
-
let
|
|
208
|
-
for (let
|
|
209
|
-
let
|
|
210
|
-
if (
|
|
211
|
-
let e =
|
|
212
|
-
|
|
206
|
+
function ge(e) {
|
|
207
|
+
let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
|
|
208
|
+
for (let r of w) {
|
|
209
|
+
let i = v(a, b.harnesses[r].hookSettings);
|
|
210
|
+
if (l(i) && t.set(r, U(i)), e.includes(r)) {
|
|
211
|
+
let e = v(z, b.harnesses[r].hookTemplate);
|
|
212
|
+
n.set(r, U(e).hooks ?? {});
|
|
213
213
|
}
|
|
214
214
|
}
|
|
215
|
-
let { installed:
|
|
216
|
-
|
|
217
|
-
for (let
|
|
218
|
-
let
|
|
219
|
-
if (!
|
|
220
|
-
let
|
|
215
|
+
let { installed: r, removed: i } = me();
|
|
216
|
+
y.log.success(`Agent hooks -> ${E(V)} (${String(r.length)} scripts)`), i.length > 0 && y.log.info(`Removed stale hook script(s): ${i.join(", ")} (no longer shipped)`);
|
|
217
|
+
for (let i of w) {
|
|
218
|
+
let s = e.includes(i);
|
|
219
|
+
if (!s && !t.has(i)) continue;
|
|
220
|
+
let c = v(a, b.harnesses[i].hookSettings), l = n.get(i) ?? {}, u = t.get(i) ?? {}, f = he(u, l, s ? r : []);
|
|
221
221
|
if (f.added === 0 && f.removed === 0) {
|
|
222
|
-
|
|
222
|
+
s && y.log.info(`Hook registrations already present in ${E(c)}`);
|
|
223
223
|
continue;
|
|
224
224
|
}
|
|
225
|
-
|
|
225
|
+
d(ne(c), { recursive: !0 }), g(c, JSON.stringify(u, null, 2) + "\n"), o([c]);
|
|
226
226
|
let p = [f.added > 0 && `registered ${String(f.added)}`, f.removed > 0 && `removed ${String(f.removed)} stale`].filter(Boolean);
|
|
227
|
-
|
|
227
|
+
y.log.success(`${p.join(", ")} hook registration(s) in ${E(c)}`);
|
|
228
228
|
}
|
|
229
229
|
}
|
|
230
230
|
//#endregion
|
|
231
231
|
//#region src/cli/index.ts
|
|
232
|
-
function
|
|
233
|
-
return new
|
|
232
|
+
function X() {
|
|
233
|
+
return new ie("--harness <harness>", "claude, codex, or all").choices(ce);
|
|
234
234
|
}
|
|
235
|
-
async function
|
|
236
|
-
if (t) return
|
|
235
|
+
async function Z(e, t, n) {
|
|
236
|
+
if (t) return y.log.info(`Harness from --harness flag: ${t.join(", ")}`), t;
|
|
237
237
|
let r = L(e);
|
|
238
|
-
if (r && !n) return
|
|
238
|
+
if (r && !n) return y.log.info(`Refreshing the existing install: ${r.join(", ")} — pass --reconfigure to choose differently.`), r;
|
|
239
239
|
if (!process.stdin.isTTY) return console.error("Pass --harness=claude|codex|all — no terminal to prompt in."), process.exitCode = 1, null;
|
|
240
|
-
let i = await
|
|
240
|
+
let i = await y.multiselect({
|
|
241
241
|
message: "Install into which harness (or harnesses)?",
|
|
242
|
-
options:
|
|
242
|
+
options: w.map((e) => ({
|
|
243
243
|
value: e,
|
|
244
|
-
label:
|
|
244
|
+
label: b.harnesses[e].label
|
|
245
245
|
})),
|
|
246
246
|
required: !0
|
|
247
247
|
});
|
|
248
|
-
return
|
|
248
|
+
return y.isCancel(i) ? (y.cancel("Cancelled — nothing installed."), null) : i;
|
|
249
249
|
}
|
|
250
|
-
async function
|
|
250
|
+
async function _e(e) {
|
|
251
251
|
let t = e.harness ? T(e.harness) : null, n = I();
|
|
252
|
-
if (
|
|
253
|
-
|
|
252
|
+
if (y.intro(`@imfusion/web-ui install skills — ${String(n.length)} skills`), n.length === 0) {
|
|
253
|
+
y.log.error("No skills found. Reinstall @imfusion/web-ui and try again."), y.outro("Nothing installed."), process.exitCode = 1;
|
|
254
254
|
return;
|
|
255
255
|
}
|
|
256
|
-
let r = await
|
|
256
|
+
let r = await Z(n, t, e.reconfigure === !0);
|
|
257
257
|
if (!r) return;
|
|
258
|
-
|
|
258
|
+
y.log.message(`Skills in this bundle:\n${n.map((e) => ` - ${e}`).join("\n")}`);
|
|
259
259
|
try {
|
|
260
|
-
|
|
260
|
+
fe(n, r);
|
|
261
261
|
} catch (e) {
|
|
262
262
|
if (e instanceof M) {
|
|
263
|
-
|
|
263
|
+
y.log.error(e.message), y.outro("Install failed."), process.exitCode = 1;
|
|
264
264
|
return;
|
|
265
265
|
}
|
|
266
266
|
throw e;
|
|
267
267
|
}
|
|
268
|
-
let i =
|
|
269
|
-
(i === "updated" || i === "added") &&
|
|
268
|
+
let i = se();
|
|
269
|
+
(i === "updated" || i === "added") && y.log.success(`Refreshed the ${b.namespace} block in ./AGENTS.md`), y.outro(`Done — ${String(n.length)} skills installed.`);
|
|
270
270
|
}
|
|
271
|
-
function
|
|
271
|
+
function ve(e) {
|
|
272
272
|
let t = e.harness ? T(e.harness) : null, n = L(I());
|
|
273
273
|
if (!t && !n) {
|
|
274
274
|
console.error("No harness recorded. Pass --harness=claude|codex|all."), process.exitCode = 1;
|
|
@@ -280,22 +280,54 @@ function me(e) {
|
|
|
280
280
|
process.exitCode = 1;
|
|
281
281
|
return;
|
|
282
282
|
}
|
|
283
|
-
|
|
283
|
+
y.intro("@imfusion/web-ui install hooks");
|
|
284
|
+
try {
|
|
285
|
+
ge(r);
|
|
286
|
+
} catch (e) {
|
|
287
|
+
if (e instanceof H) {
|
|
288
|
+
console.error(e.message), process.exitCode = 1;
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
throw e;
|
|
292
|
+
}
|
|
293
|
+
y.outro("Done — agent hooks installed.");
|
|
294
|
+
}
|
|
295
|
+
function ye(r) {
|
|
296
|
+
let i = r ?? process.env.WEB_UI_CHECKOUT;
|
|
297
|
+
if (!i) {
|
|
298
|
+
console.error("Pass the checkout path, or set WEB_UI_CHECKOUT."), process.exitCode = 1;
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
let o = v(i);
|
|
302
|
+
try {
|
|
303
|
+
let t = e(a, o);
|
|
304
|
+
y.log.success(`Linked ${o} into ${E(t)}`);
|
|
305
|
+
} catch (e) {
|
|
306
|
+
if (e instanceof n) {
|
|
307
|
+
console.error(e.message), process.exitCode = 1;
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
throw e;
|
|
311
|
+
}
|
|
312
|
+
y.log.info("Syncing on every rebuild of dist/. Ctrl+C stops syncing; the app keeps the last synced build."), t(a, o, (e) => {
|
|
313
|
+
y.log.info(e);
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
function be() {
|
|
284
317
|
try {
|
|
285
|
-
|
|
318
|
+
for (let e of i(a)) y.log.message(e);
|
|
286
319
|
} catch (e) {
|
|
287
|
-
if (e instanceof
|
|
320
|
+
if (e instanceof n) {
|
|
288
321
|
console.error(e.message), process.exitCode = 1;
|
|
289
322
|
return;
|
|
290
323
|
}
|
|
291
324
|
throw e;
|
|
292
325
|
}
|
|
293
|
-
v.outro("Done — agent hooks installed.");
|
|
294
326
|
}
|
|
295
|
-
var Q = new
|
|
327
|
+
var Q = new re();
|
|
296
328
|
Q.name("web-ui").description("Command-line tools for @imfusion/web-ui").version(P);
|
|
297
329
|
var $ = Q.command("install").description("Install @imfusion/web-ui agent skills or hooks into a project");
|
|
298
|
-
$.command("skills").description("Install skills for the chosen harness").addOption(
|
|
330
|
+
$.command("skills").description("Install skills for the chosen harness").addOption(X()).option("--reconfigure", "Re-open the harness selection prompt on an existing install").action(_e), $.command("hooks").description("Install agent lifecycle hooks (requires skills already installed for the harness)").addOption(X()).action(ve), Q.command("link").description("Serve a local @imfusion/web-ui checkout from this project and sync it on every rebuild").argument("[path]", "checkout directory (default: WEB_UI_CHECKOUT)").action(ye), Q.command("unlink").description("Restore the published @imfusion/web-ui files in this project").action(be), $.action(() => {
|
|
299
331
|
$.help();
|
|
300
332
|
}), Q.action(() => {
|
|
301
333
|
Q.help();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@imfusion/web-ui",
|
|
3
|
-
"version": "0.10.1-dev.
|
|
3
|
+
"version": "0.10.1-dev.41.g467e0e1a",
|
|
4
4
|
"description": "The official Web UI component library for ImFusion web apps",
|
|
5
5
|
"author": "ImFusion GmbH",
|
|
6
6
|
"homepage": "https://imfusion.com",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
},
|
|
12
12
|
"type": "module",
|
|
13
13
|
"engines": {
|
|
14
|
-
"node": ">=
|
|
14
|
+
"node": "^22.22.1 || ^24.11 || >=26"
|
|
15
15
|
},
|
|
16
16
|
"imports": {
|
|
17
17
|
"#/*": "./src/*",
|