@loomweaver/mcp 0.7.2 → 0.7.4
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/README.md +0 -4
- package/dist/main.mjs +360 -213
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,10 +14,6 @@ is not inside this repo (a chat assistant, a remote client) can scaffold and val
|
|
|
14
14
|
|
|
15
15
|
## Consume from npm (product repos)
|
|
16
16
|
|
|
17
|
-
> **Availability:** the `@loomweaver/*` packages are not on the public npm registry yet — the first
|
|
18
|
-
> public release publishes them. Until then they come from LoomWeaver's own package feed, and
|
|
19
|
-
> `npx` needs that registry configured for the `@loomweaver` scope.
|
|
20
|
-
|
|
21
17
|
`@loomweaver/mcp` ships as a self-contained bundle (devkit + the MCP SDK are inlined — no transitive
|
|
22
18
|
install). A product repo that already consumes `@loomweaver/shell` / `@loomweaver/plugin-sdk` just adds the
|
|
23
19
|
server to its `.mcp.json`; `npx` fetches the bundle and starts the stdio server:
|
package/dist/main.mjs
CHANGED
|
@@ -31012,6 +31012,36 @@ function generate(recipe, input) {
|
|
|
31012
31012
|
}
|
|
31013
31013
|
return files;
|
|
31014
31014
|
}
|
|
31015
|
+
function amendments(recipe, input) {
|
|
31016
|
+
return recipe.amend?.(input) ?? [];
|
|
31017
|
+
}
|
|
31018
|
+
|
|
31019
|
+
// ../devkit/src/lib/amend/describe.ts
|
|
31020
|
+
function describeAmendment(amendment) {
|
|
31021
|
+
if (amendment.kind === "postcss") {
|
|
31022
|
+
return `Write ${amendment.file} beside your package.json, naming ${amendment.plugin}. Without it the stylesheet is read as plain CSS: no utility class is emitted, the workbench renders unstyled, and the build still reports success.`;
|
|
31023
|
+
}
|
|
31024
|
+
if (amendment.kind === "stylesheet-source") {
|
|
31025
|
+
return `Add an @source entry for '${amendment.sourceRoot}' to the application's entry stylesheet, resolved from that stylesheet. Without it none of that code's utilities are emitted.`;
|
|
31026
|
+
}
|
|
31027
|
+
if (amendment.kind === "compose-plugin") {
|
|
31028
|
+
return `Register ${amendment.id} in the composition root: import { ${amendment.symbol} }, provideTranslationNamespaces('${amendment.id}'), provideCapabilityGrants({ ${amendment.id}: [${amendment.capabilities.map((capability) => `'${capability}'`).join(
|
|
31029
|
+
", "
|
|
31030
|
+
)}] }) and ...providePlugins(${amendment.symbol}). Without it none of its contributions appear.`;
|
|
31031
|
+
}
|
|
31032
|
+
return [
|
|
31033
|
+
...amendment.styles.length > 0 ? [`name ${amendment.styles.join(", ")} in styles`] : [],
|
|
31034
|
+
...amendment.assets.length > 0 ? [
|
|
31035
|
+
`add assets for ${amendment.assets.map((asset) => asset.input).join(", ")} (the shell fetches its own strings at runtime, so without that glob every label in the chrome renders as its raw translation key)`
|
|
31036
|
+
] : [],
|
|
31037
|
+
...amendment.serviceWorker ? [
|
|
31038
|
+
`set serviceWorker to ${amendment.serviceWorker} in the production configuration (provideShell registers a worker that 404s otherwise)`
|
|
31039
|
+
] : [],
|
|
31040
|
+
...amendment.inlineCritical === void 0 ? [] : [
|
|
31041
|
+
`set optimization.styles.inlineCritical to ${amendment.inlineCritical} in the production configuration (the generated content-security policy blocks the inline handler Angular's critical-CSS pass attaches, so a release build renders unstyled)`
|
|
31042
|
+
]
|
|
31043
|
+
].map((step, index) => `${index + 1}. ${step}`).join(" ");
|
|
31044
|
+
}
|
|
31015
31045
|
|
|
31016
31046
|
// ../devkit/src/lib/generate/casing.ts
|
|
31017
31047
|
function isKebabId(value) {
|
|
@@ -31834,6 +31864,40 @@ var framePlugin = {
|
|
|
31834
31864
|
}
|
|
31835
31865
|
};
|
|
31836
31866
|
|
|
31867
|
+
// ../devkit/src/recipes/angular-distribution/amendments.ts
|
|
31868
|
+
function distributionAmendments(d) {
|
|
31869
|
+
return [
|
|
31870
|
+
...d.styles === "tailwind" ? [
|
|
31871
|
+
{
|
|
31872
|
+
kind: "postcss",
|
|
31873
|
+
file: ".postcssrc.json",
|
|
31874
|
+
plugin: "@tailwindcss/postcss"
|
|
31875
|
+
}
|
|
31876
|
+
] : [],
|
|
31877
|
+
{
|
|
31878
|
+
kind: "build-target",
|
|
31879
|
+
styles: ["src/styles.css"],
|
|
31880
|
+
assets: [
|
|
31881
|
+
{ glob: "**/*", input: "public", from: "project" },
|
|
31882
|
+
{
|
|
31883
|
+
glob: "**/*",
|
|
31884
|
+
input: "node_modules/@loomweaver/shell/i18n",
|
|
31885
|
+
from: "workspace",
|
|
31886
|
+
output: "i18n"
|
|
31887
|
+
},
|
|
31888
|
+
{
|
|
31889
|
+
glob: "**/*",
|
|
31890
|
+
input: "node_modules/@loomweaver/frame-kit/dist",
|
|
31891
|
+
from: "workspace",
|
|
31892
|
+
output: "frame-kit"
|
|
31893
|
+
}
|
|
31894
|
+
],
|
|
31895
|
+
serviceWorker: "ngsw-config.json",
|
|
31896
|
+
inlineCritical: false
|
|
31897
|
+
}
|
|
31898
|
+
];
|
|
31899
|
+
}
|
|
31900
|
+
|
|
31837
31901
|
// ../devkit/src/recipes/shell-regions.ts
|
|
31838
31902
|
var SHELL_REGIONS = [
|
|
31839
31903
|
"{ id: 'top-bar', type: 'bar', dock: 'top' }",
|
|
@@ -31851,6 +31915,219 @@ function renderRegions(indent) {
|
|
|
31851
31915
|
var PLACEHOLDER_LOGO_SVG = `<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="512" height="512" viewBox="87.5 -53 1129.9 1129.9"><g paint-order="stroke"><path d="m0 0 12.6-10.6-9.2-8-14.5 12.1q-.7.8 1.2 1.5A17 17 0 0 1-2.4-.5Q-1 .7 0 0" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:#2e96c9;fill-rule:nonzero;opacity:1" transform="matrix(15.6303 0 0 -15.6303 265.2 368.8)"/><path d="m0 0 19-16c.6-.5.5-1.6-.2-2.3q-2.8-3-7.5-4.5c-1.2-.4-2.8-.1-3.4.4l-17 14.3z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:#2e96c9;fill-rule:nonzero;opacity:1" transform="matrix(15.6303 0 0 -15.6303 593.2 644.5)"/><path d="m0 0 5.8-4.9-9.2-8-2.8 2.3q-.9 1 0 2.5l4 7.4Q-1 .7 0 0" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:#c59a2f;fill-rule:nonzero;opacity:1" transform="matrix(15.6303 0 0 -15.6303 386.3 170)"/><path d="m0 0 12.4-10.4-9.2-8.1L-9.2-8.1Z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:#c59a2f;fill-rule:nonzero;opacity:1" transform="matrix(15.6303 0 0 -15.6303 608.2 356.6)"/><path d="m0 0 5-4.2c.6-.5.6-1.6 0-2.5l-4-7.4q-1-1.4-2.1-.7l-8 6.7z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:#c59a2f;fill-rule:nonzero;opacity:1" transform="matrix(15.6303 0 0 -15.6303 933.4 630)"/><path d="m0 0 14.6-12.3-9.2-8L-11-6.6c-.6.5-.6 1.6.2 2.4Q-8-1.2-3.3.3C-2.2.7-.6.5 0 0" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:#2e96c9;fill-rule:nonzero;opacity:1" transform="matrix(15.6303 0 0 -15.6303 589.5 28.9)"/><path d="m0 0 17-14.3q.8-.8-1.3-1.4a17 17 0 0 1-7.5-4.5c-.7-.8-1.8-1-2.4-.5l-15 12.6Z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:#2e96c9;fill-rule:nonzero;opacity:1" transform="matrix(15.6303 0 0 -15.6303 948.5 330.8)"/><path d="m0 0 8.4-7-13.6-12-8.4 7z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:#2e96c9;fill-rule:nonzero;opacity:1" transform="matrix(15.6303 0 0 -15.6303 514.5 213.2)"/><path d="m0 0 5.7-4.8q1.3-1 .4-2L3-9.5l-8.4 7 3 2.7A2 2 0 0 0 0 0" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:#2e96c9;fill-rule:nonzero;opacity:1" transform="matrix(15.6303 0 0 -15.6303 743 48)"/><path d="m0 0 8.4-7-2.2-2q-1-.7-2.3.2L-2-4q-1 1.2-.2 2z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:#2e96c9;fill-rule:nonzero;opacity:1" transform="matrix(15.6303 0 0 -15.6303 158.6 526.5)"/><path d="m0 0 8.4-7L-5-18.9c-.5-.5-1.6-.4-2.3.2l-5.8 4.8q-1 1-.3 2z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:#2e96c9;fill-rule:nonzero;opacity:1" transform="matrix(15.6303 0 0 -15.6303 492.8 507)"/><path d="m0 0 5.7-4.8q1.3-1 .4-2l-14.7-13-8.4 7.1L-2.3.3C-1.8.6-.7.5 0 0" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:#2e96c9;fill-rule:nonzero;opacity:1" transform="matrix(15.6303 0 0 -15.6303 902.6 182)"/><path d="m0 0 5.9-5Q7-6 6.2-7l-3-2.7-8.7 7.2L-2.4.3Q-1.4.9 0 0" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:#2e96c9;fill-rule:nonzero;opacity:1" transform="matrix(15.6303 0 0 -15.6303 1065.8 319.3)"/><path d="m0 0 8.6-7.2-13.6-12-8.6 7.2z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:#2e96c9;fill-rule:nonzero;opacity:1" transform="matrix(15.6303 0 0 -15.6303 836.9 484.2)"/><path d="m0 0 8.6-7.2-2.2-2q-1-.6-2.4.3l-5.9 5Q-3-3-2.2-2z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:#2e96c9;fill-rule:nonzero;opacity:1" transform="matrix(15.6303 0 0 -15.6303 481 797.5)"/><g transform="matrix(15.6303 0 0 -15.6303 877.6 706.6)"><linearGradient id="a" x1="0" x2="1" y1="0" y2="0" gradientTransform="rotate(135.7 64.4 103.4)scale(2.18666 -2.18666)" gradientUnits="userSpaceOnUse"><stop offset="0%" style="stop-color:#c59a2f;stop-opacity:1"/><stop offset="100%" style="stop-color:#614d06;stop-opacity:1"/></linearGradient><path d="m176.7 129.6 2-1.7 9.2 8-2 1.8z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:url(#a);fill-rule:nonzero;opacity:1" transform="translate(-182.3 -132.8)"/></g><g transform="matrix(15.6303 0 0 -15.6303 711.4 567.2)"><linearGradient id="b" x1="0" x2="1" y1="0" y2="0" gradientTransform="rotate(135.7 56.7 106)scale(-2.18726 2.18726)" gradientUnits="userSpaceOnUse"><stop offset="0%" style="stop-color:#c59a2f;stop-opacity:1"/><stop offset="100%" style="stop-color:#614d06;stop-opacity:1"/></linearGradient><path d="m166 138.5 2.1-1.7 9.2 8.1-2 1.7z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:url(#b);fill-rule:nonzero;opacity:1" transform="translate(-171.7 -141.7)"/></g><g transform="matrix(15.6303 0 0 -15.6303 532.5 867.7)"><linearGradient id="c" x1="0" x2="1" y1="0" y2="0" gradientTransform="rotate(45.7 -65.1 251)scale(2.11643 -2.11643)" gradientUnits="userSpaceOnUse"><stop offset="0%" style="stop-color:#2e96c9;stop-opacity:1"/><stop offset="100%" style="stop-color:#2479a3;stop-opacity:1"/></linearGradient><path d="m155 125.2 8.5-7.2 2 1.8-8.6 7.2z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:url(#c);fill-rule:nonzero;opacity:1" transform="translate(-160.2 -122.5)"/></g><g transform="matrix(15.6303 0 0 -15.6303 707.2 713.6)"><linearGradient id="d" x1="0" x2="1" y1="0" y2="0" gradientTransform="rotate(-134.3 114 30.2)scale(2.11524 -2.11524)" gradientUnits="userSpaceOnUse"><stop offset="0%" style="stop-color:#2e96c9;stop-opacity:1"/><stop offset="100%" style="stop-color:#2479a3;stop-opacity:1"/></linearGradient><path d="m166.1 135 8.6-7.1 2 1.7-8.6 7.2z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:url(#d);fill-rule:nonzero;opacity:1" transform="translate(-171.4 -132.3)"/></g><g transform="matrix(15.6303 0 0 -15.6303 888.2 554.5)"><linearGradient id="e" x1="0" x2="1" y1="0" y2="0" gradientTransform="rotate(45.7 -77.5 288)scale(2.11554 -2.11554)" gradientUnits="userSpaceOnUse"><stop offset="0%" style="stop-color:#2e96c9;stop-opacity:1"/><stop offset="100%" style="stop-color:#2479a3;stop-opacity:1"/></linearGradient><path d="m177.7 145.3 8.6-7.3 2 1.8-8.6 7.2z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:url(#e);fill-rule:nonzero;opacity:1" transform="translate(-183 -142.5)"/></g><g transform="matrix(15.6303 0 0 -15.6303 1062 401.2)"><linearGradient id="f" x1="0" x2="1" y1="0" y2="0" gradientTransform="rotate(45.7 -84.1 307.3)scale(-2.11583 2.11583)" gradientUnits="userSpaceOnUse"><stop offset="0%" style="stop-color:#2e96c9;stop-opacity:1"/><stop offset="100%" style="stop-color:#2479a3;stop-opacity:1"/></linearGradient><path d="m188.8 155 8.6-7.2 2 1.8-8.6 7.2z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:url(#f);fill-rule:nonzero;opacity:1" transform="translate(-194.1 -152.3)"/></g><g transform="matrix(15.6303 0 0 -15.6303 206.5 595.5)"><linearGradient id="g" x1="0" x2="1" y1="0" y2="0" gradientTransform="rotate(225.7 98.9 40.5)scale(-2.0962 2.0962)" gradientUnits="userSpaceOnUse"><stop offset="0%" style="stop-color:#2e96c9;stop-opacity:1"/><stop offset="100%" style="stop-color:#2479a3;stop-opacity:1"/></linearGradient><path d="m134.3 142.5 8.2-7 2 1.8-8.3 7z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:url(#g);fill-rule:nonzero;opacity:1" transform="translate(-139.4 -139.9)"/></g><g transform="matrix(15.6303 0 0 -15.6303 381 441.4)"><linearGradient id="h" x1="0" x2="1" y1="0" y2="0" gradientTransform="rotate(-134.3 107 43.3)scale(2.0962 -2.0962)" gradientUnits="userSpaceOnUse"><stop offset="0%" style="stop-color:#2e96c9;stop-opacity:1"/><stop offset="100%" style="stop-color:#2479a3;stop-opacity:1"/></linearGradient><path d="m145.4 152.3 8.3-6.9 2 1.8-8.3 6.9z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:url(#h);fill-rule:nonzero;opacity:1" transform="translate(-150.5 -149.8)"/></g><g transform="matrix(15.6303 0 0 -15.6303 562 282.3)"><linearGradient id="i" x1="0" x2="1" y1="0" y2="0" gradientTransform="rotate(225.7 114.5 45.7)scale(-2.0953 2.0953)" gradientUnits="userSpaceOnUse"><stop offset="0%" style="stop-color:#2e96c9;stop-opacity:1"/><stop offset="100%" style="stop-color:#2479a3;stop-opacity:1"/></linearGradient><path d="m157 162.5 8.2-7 2 1.8-8.2 7z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:url(#i);fill-rule:nonzero;opacity:1" transform="translate(-162.1 -160)"/></g><g transform="matrix(15.6303 0 0 -15.6303 736 129)"><linearGradient id="j" x1="0" x2="1" y1="0" y2="0" gradientTransform="rotate(45.7 -115.1 291)scale(-2.0956 2.0956)" gradientUnits="userSpaceOnUse"><stop offset="0%" style="stop-color:#2e96c9;stop-opacity:1"/><stop offset="100%" style="stop-color:#2479a3;stop-opacity:1"/></linearGradient><path d="m168.1 172.3 8.3-6.9 2 1.7-8.3 7z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:url(#j);fill-rule:nonzero;opacity:1" transform="translate(-173.2 -169.7)"/></g><g transform="matrix(15.6303 0 0 -15.6303 544.8 441.3)"><linearGradient id="k" x1="0" x2="1" y1="0" y2="0" gradientTransform="rotate(135.7 50.4 108)scale(2.18666 -2.18666)" gradientUnits="userSpaceOnUse"><stop offset="0%" style="stop-color:#c59a2f;stop-opacity:1"/><stop offset="100%" style="stop-color:#614d06;stop-opacity:1"/></linearGradient><path d="m155.9 147 2-1.6 9.2 8-2 1.8z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:url(#k);fill-rule:nonzero;opacity:1" transform="translate(-161.5 -150.3)"/></g><g transform="matrix(15.6303 0 0 -15.6303 390.7 294.8)"><linearGradient id="l" x1="0" x2="1" y1="0" y2="0" gradientTransform="rotate(135.7 42.9 110.5)scale(-2.17357 2.17357)" gradientUnits="userSpaceOnUse"><stop offset="0%" style="stop-color:#c59a2f;stop-opacity:1"/><stop offset="100%" style="stop-color:#614d06;stop-opacity:1"/></linearGradient><path d="m145.6 156 2-1.7 9 8-2 1.6z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:url(#l);fill-rule:nonzero;opacity:1" transform="translate(-151.2 -159.1)"/></g><g transform="matrix(15.6303 0 0 -15.6303 375.9 585.7)"><linearGradient id="m" x1="0" x2="1" y1="0" y2="0" gradientTransform="rotate(135.7 46.2 101)scale(-1.9968 1.9968)" gradientUnits="userSpaceOnUse"><stop offset="0%" style="stop-color:#2e96c9;stop-opacity:1"/><stop offset="100%" style="stop-color:#2479a3;stop-opacity:1"/></linearGradient><path d="m144.7 137.2 1.8-1.5 9.2 8.1-1.8 1.5z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:url(#m);fill-rule:nonzero;opacity:1" transform="translate(-150.2 -140.5)"/></g><g transform="matrix(15.6303 0 0 -15.6303 733.7 274)"><linearGradient id="n" x1="0" x2="1" y1="0" y2="0" gradientTransform="rotate(-44.3 284 -131.7)scale(1.9968 -1.9968)" gradientUnits="userSpaceOnUse"><stop offset="0%" style="stop-color:#2e96c9;stop-opacity:1"/><stop offset="100%" style="stop-color:#2479a3;stop-opacity:1"/></linearGradient><path d="m167.6 157.2 1.8-1.5 9.2 8-1.8 1.6z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:url(#n);fill-rule:nonzero;opacity:1" transform="translate(-173.1 -160.5)"/></g><g transform="matrix(15.6303 0 0 -15.6303 893.6 408.2)"><linearGradient id="o" x1="0" x2="1" y1="0" y2="0" gradientTransform="rotate(135.7 61 113.2)scale(1.9962 -1.9962)" gradientUnits="userSpaceOnUse"><stop offset="0%" style="stop-color:#2e96c9;stop-opacity:1"/><stop offset="100%" style="stop-color:#2479a3;stop-opacity:1"/></linearGradient><path d="m177.8 148.6 1.8-1.5 9.2 8-1.8 1.6z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:url(#o);fill-rule:nonzero;opacity:1" transform="translate(-183.3 -151.9)"/></g><g transform="matrix(15.6303 0 0 -15.6303 535.9 720)"><linearGradient id="p" x1="0" x2="1" y1="0" y2="0" gradientTransform="rotate(135.7 53.6 98.6)scale(1.9962 -1.9962)" gradientUnits="userSpaceOnUse"><stop offset="0%" style="stop-color:#2e96c9;stop-opacity:1"/><stop offset="100%" style="stop-color:#2479a3;stop-opacity:1"/></linearGradient><path d="m155 128.6 1.7-1.5 9.2 8.1-1.8 1.5z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:url(#p);fill-rule:nonzero;opacity:1" transform="translate(-160.4 -132)"/></g><g transform="matrix(15.6303 0 0 -15.6303 717.3 421.6)"><linearGradient id="q" x1="0" x2="1" y1="0" y2="0" gradientTransform="rotate(45.7 -93.5 280)scale(-2.095 2.095)" gradientUnits="userSpaceOnUse"><stop offset="0%" style="stop-color:#2e96c9;stop-opacity:1"/><stop offset="100%" style="stop-color:#2479a3;stop-opacity:1"/></linearGradient><path d="m167 153.6 8.2-7 2 1.8-8.3 7z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:url(#q);fill-rule:nonzero;opacity:1" transform="translate(-172 -151)"/></g><g transform="matrix(15.6303 0 0 -15.6303 542.1 575.9)"><linearGradient id="r" x1="0" x2="1" y1="0" y2="0" gradientTransform="rotate(45.7 -87 261)scale(2.0956 -2.0956)" gradientUnits="userSpaceOnUse"><stop offset="0%" style="stop-color:#2e96c9;stop-opacity:1"/><stop offset="100%" style="stop-color:#2479a3;stop-opacity:1"/></linearGradient><path d="m155.7 143.8 8.3-7 2 1.8-8.3 6.9z" style="stroke:none;stroke-width:1;stroke-dasharray:none;stroke-linecap:butt;stroke-dashoffset:0;stroke-linejoin:miter;stroke-miterlimit:4;fill:url(#r);fill-rule:nonzero;opacity:1" transform="translate(-160.8 -141.2)"/></g></g></svg>
|
|
31852
31916
|
`;
|
|
31853
31917
|
|
|
31918
|
+
// ../devkit/src/recipes/angular-distribution/readme.ts
|
|
31919
|
+
function stylesNotes(d) {
|
|
31920
|
+
if (d.styles === "precompiled") {
|
|
31921
|
+
return [
|
|
31922
|
+
"`src/styles.css` imports the stylesheet **we** compiled \u2014 tokens, the `.lw-*` class contracts",
|
|
31923
|
+
"and every utility the shell's own templates use, 67 KB minified and 11 KB over the wire. There",
|
|
31924
|
+
"is nothing to install and nothing to configure: no `tailwindcss`, no `.postcssrc.json`, no",
|
|
31925
|
+
"`@source` paths to miscount.",
|
|
31926
|
+
"",
|
|
31927
|
+
"What you give up is writing Tailwind utilities in *your own* templates. The `--lw-*` tokens stay",
|
|
31928
|
+
"available to any CSS you write, so re-theming stays a token remap rather than a fight.",
|
|
31929
|
+
"",
|
|
31930
|
+
"If you bring a CSS framework of your own, **import it into a cascade layer** \u2014 the file says how,",
|
|
31931
|
+
"and it is the one decision that determines whether the chrome survives the introduction. Prefer",
|
|
31932
|
+
"Tailwind after all? Re-run the scaffold with `--styles tailwind`."
|
|
31933
|
+
];
|
|
31934
|
+
}
|
|
31935
|
+
return [
|
|
31936
|
+
"`src/styles.css` compiles the shell's source theme with Tailwind 4, which is also what lets you",
|
|
31937
|
+
"write Tailwind utilities in your own templates. The scaffold wrote `.postcssrc.json` beside your",
|
|
31938
|
+
"`package.json` for you, because without it the stylesheet is read as plain CSS: no utility class",
|
|
31939
|
+
"is emitted, the workbench renders unstyled, and the build still reports success. The packages are",
|
|
31940
|
+
"the one thing left, because a scaffold does not install:",
|
|
31941
|
+
"",
|
|
31942
|
+
"```sh",
|
|
31943
|
+
"npm install -D tailwindcss @tailwindcss/postcss @tailwindcss/typography",
|
|
31944
|
+
"```",
|
|
31945
|
+
"",
|
|
31946
|
+
"Use **semantic tokens only** in your own templates (`bg-surface`, `text-content`, `text-brand`,",
|
|
31947
|
+
"`border-border`), never raw palette colours.",
|
|
31948
|
+
"",
|
|
31949
|
+
"**Count the `../` hops in the `@source` line.** It is resolved from the stylesheet, not from the",
|
|
31950
|
+
"workspace root, and the scaffold derived it from where this project sits. Move the project and",
|
|
31951
|
+
"nothing errors \u2014 Tailwind simply emits none of the shell's classes and the app renders unstyled.",
|
|
31952
|
+
"",
|
|
31953
|
+
"Want none of this? Re-run the scaffold with `--styles precompiled` and you get a one-line",
|
|
31954
|
+
"stylesheet that needs no Tailwind at all \u2014 the right choice if your product is themed with",
|
|
31955
|
+
"Bootstrap, Bulma or hand-written CSS."
|
|
31956
|
+
];
|
|
31957
|
+
}
|
|
31958
|
+
function readme2(d) {
|
|
31959
|
+
return [
|
|
31960
|
+
`# ${d.title} \u2014 a LoomWeaver distribution`,
|
|
31961
|
+
"",
|
|
31962
|
+
`The composition root that assembles the platform into a shippable product. It renders the bare`,
|
|
31963
|
+
`shell out of the box; add your weavers and branding below. Your own README is untouched \u2014 the`,
|
|
31964
|
+
`scaffold writes its notes here so it can never overwrite prose you wrote.`,
|
|
31965
|
+
"",
|
|
31966
|
+
"## Run it",
|
|
31967
|
+
"",
|
|
31968
|
+
"In an Nx workspace (the generator wired the project):",
|
|
31969
|
+
"",
|
|
31970
|
+
"```sh",
|
|
31971
|
+
`nx serve ${d.name}`,
|
|
31972
|
+
"```",
|
|
31973
|
+
"",
|
|
31974
|
+
"Scaffolded over the CLI or MCP, these files are sources without build wiring \u2014 drop them into",
|
|
31975
|
+
"an application you already serve (`ng new`, or an Nx application). They keep Angular's own",
|
|
31976
|
+
"shape: `main.ts` bootstraps `App`, `App` renders `<lw-shell />`, and everything this product is",
|
|
31977
|
+
"made of lives in `app.config.ts`. Nothing of the generated app is deleted. Over an existing",
|
|
31978
|
+
"application `--force` replaces exactly the files above \u2014 all of them bootstrap wiring, none of",
|
|
31979
|
+
"them content you authored. Under Nx it additionally merges the build targets into that",
|
|
31980
|
+
"project's `project.json`, keeping the targets, `implicitDependencies` and tags it already had.",
|
|
31981
|
+
"",
|
|
31982
|
+
"Two leftovers from `ng new` are no longer referenced and can go: `src/app/app.routes.ts` (the",
|
|
31983
|
+
"shell owns content routing via `provideShellRouter()`) and `src/app/app.css`. The generated",
|
|
31984
|
+
"`src/app/app.spec.ts` now fails \u2014 `App` pulls the whole shell into a bare `TestBed` \u2014 so delete",
|
|
31985
|
+
"it and test your own components instead of the composition root.",
|
|
31986
|
+
"",
|
|
31987
|
+
"The project is generated **untagged**: Nx tags belong to your `depConstraints`, and inventing",
|
|
31988
|
+
"one would fail a lint policy you never opted this project into. If your workspace enforces",
|
|
31989
|
+
"module boundaries, give it tags your constraints allow \u2014 `--tags` at generation time, or",
|
|
31990
|
+
"`tags` in `project.json` afterwards.",
|
|
31991
|
+
"",
|
|
31992
|
+
"## Compose weavers + branding (in `src/app/app.config.ts`)",
|
|
31993
|
+
"",
|
|
31994
|
+
"The layout is already there. Adding a weaver is three providers plus its import \u2014 note the",
|
|
31995
|
+
"**spread**, since `providePlugins` is variadic and returns an array:",
|
|
31996
|
+
"",
|
|
31997
|
+
"```ts",
|
|
31998
|
+
"import { providePlugins, provideCapabilityGrants, provideTranslationNamespaces } from '@loomweaver/shell';",
|
|
31999
|
+
"import { notesPlugin } from '@acme/notes-weaver'; // Nx: the workspace alias; otherwise a relative path",
|
|
32000
|
+
"",
|
|
32001
|
+
" provideTranslationNamespaces('notes'),",
|
|
32002
|
+
" provideCapabilityGrants({ notes: ['contributions', 'ui', 'navigation'] }),",
|
|
32003
|
+
" ...providePlugins(notesPlugin),",
|
|
32004
|
+
"```",
|
|
32005
|
+
"",
|
|
32006
|
+
"Grant exactly what the weaver's manifest declares \u2014 the broker is default-deny, so an ungranted",
|
|
32007
|
+
"plugin throws `CapabilityError` instead of quietly doing less. A weaver also needs its",
|
|
32008
|
+
"translations served: add an assets glob for its `src/lib/i18n` under `i18n/<id>` (the Nx",
|
|
32009
|
+
"generator does this for you).",
|
|
32010
|
+
"",
|
|
32011
|
+
"`public/logo.svg` is the LoomWeaver mark, dropped in as a placeholder so the top bar renders",
|
|
32012
|
+
"something from the first run instead of a broken image. Replace it with your own \u2014 any square",
|
|
32013
|
+
"image will do; `logoUrl` resolves against your served root. `tagline` is a",
|
|
32014
|
+
"translation key that falls back to rendering itself, so the literal above works but makes",
|
|
32015
|
+
"Transloco log a missing-translation warning in dev; point it at a key of your own to silence it.",
|
|
32016
|
+
"",
|
|
32017
|
+
"That same file is also the **app icon**: the browser tab reads it, and the manifest names it so",
|
|
32018
|
+
"the app has an icon at all. One gap is left on purpose, because a scaffold writes text and",
|
|
32019
|
+
"cannot invent your artwork: **Chromium only offers installation once the manifest names a 192",
|
|
32020
|
+
"and a 512 raster icon**, and iOS ignores manifest icons entirely in favour of",
|
|
32021
|
+
"`apple-touch-icon`. Drop `icon-192.png` and `icon-512.png` next to the logo, add them to the",
|
|
32022
|
+
"manifest's `icons` and add an `apple-touch-icon` link to `index.html`, and the app becomes",
|
|
32023
|
+
"installable. Until then it runs and caches offline, it simply is not offered for installation.",
|
|
32024
|
+
"",
|
|
32025
|
+
"## The two searches, and the badges that say so",
|
|
32026
|
+
"",
|
|
32027
|
+
"The shell seeds two searches and binds them itself: `mod+k` opens the command search, `mod+p`",
|
|
32028
|
+
"the search over open work (`mod` is \u2318 on macOS, Ctrl elsewhere). Both work whether or not you",
|
|
32029
|
+
"do anything. What the generated `app.config.ts` adds is only the way to *see* them: a badge in",
|
|
32030
|
+
"the top bar for the command search, one at the leading edge of the status bar for open work,",
|
|
32031
|
+
"each printing its own chord in the spelling of the platform it runs on.",
|
|
32032
|
+
"",
|
|
32033
|
+
"They are placed apart on purpose. Two identical-looking search badges side by side in the top",
|
|
32034
|
+
"bar read as a duplicate rather than as two different things.",
|
|
32035
|
+
"",
|
|
32036
|
+
"```ts",
|
|
32037
|
+
"provideCommandPaletteEntry(); // top bar, end slot, order 5",
|
|
32038
|
+
"provideQuickOpenEntry({ bar: 'top-bar', order: 4 }); // \u2026or put it wherever you want",
|
|
32039
|
+
"```",
|
|
32040
|
+
"",
|
|
32041
|
+
"A badge never outlives what it opens. Drop the search and its badge goes with it; the same",
|
|
32042
|
+
"happens for a session that may not run it. You will not be left with a control that does",
|
|
32043
|
+
"nothing. Switching shortcuts off is the one exception: the badge stays and still opens the",
|
|
32044
|
+
"search, it simply prints no chord, because nothing here advertises a key that does nothing.",
|
|
32045
|
+
"",
|
|
32046
|
+
"Four things you may want, and the line for each:",
|
|
32047
|
+
"",
|
|
32048
|
+
"```ts",
|
|
32049
|
+
"// 1. Keep the search, drop only the badge \u2014 it then opens by shortcut alone.",
|
|
32050
|
+
"provideShell({ omit: ['shell.commandPaletteEntry', 'shell.quickOpenEntry'] }),",
|
|
32051
|
+
"",
|
|
32052
|
+
"// 2. Drop the search itself. This takes mod+p with it: the chord is derived from the",
|
|
32053
|
+
"// registered command, so removing the command unbinds the key. The badge goes too.",
|
|
32054
|
+
"provideShell({ omit: ['shell.quickOpen'] }),",
|
|
32055
|
+
"",
|
|
32056
|
+
"// 3. Make mod+k run something of yours, keeping the shell's id. Last registration wins,",
|
|
32057
|
+
"// so your command replaces the built-in one and inherits its place everywhere.",
|
|
32058
|
+
"// Register it from your own plugin with the id 'shell.commandPalette'.",
|
|
32059
|
+
"",
|
|
32060
|
+
"// 4. Bind mod+k to a command of your own, under your own id.",
|
|
32061
|
+
"provideShell({ omit: ['shell.commandPalette'] }), // \u2026then declare shortcut: 'mod+k' on yours",
|
|
32062
|
+
"```",
|
|
32063
|
+
"",
|
|
32064
|
+
"What not to do is the fifth case: declaring `mod+k` on a command of your own while the",
|
|
32065
|
+
"built-in one is still registered. Two commands then hold one chord. The shell warns about it in",
|
|
32066
|
+
"the console and the later registration wins, but which registration is later is not something",
|
|
32067
|
+
"your composition root decides. Omit the built-in, or take its id. Never race it.",
|
|
32068
|
+
"",
|
|
32069
|
+
"## Styles",
|
|
32070
|
+
"",
|
|
32071
|
+
...stylesNotes(d),
|
|
32072
|
+
"",
|
|
32073
|
+
"## Build wiring",
|
|
32074
|
+
"",
|
|
32075
|
+
"The scaffold did this. Your build target now names the stylesheet, three asset globs, the",
|
|
32076
|
+
"service worker and one production setting, and the run that wrote these files listed each one it",
|
|
32077
|
+
"added. Anything you had already set was left exactly as you set it.",
|
|
32078
|
+
"",
|
|
32079
|
+
"What each is for, so that nobody removes one as clutter. The **`@loomweaver/shell/i18n` glob**",
|
|
32080
|
+
"serves the strings the shell fetches at runtime; without it every label in the chrome renders as",
|
|
32081
|
+
"its raw translation key and nothing errors. The **frame-kit** glob only matters if you host",
|
|
32082
|
+
"sandboxed (iframe) plugins \u2014 until you install that package the glob simply matches nothing.",
|
|
32083
|
+
"**`serviceWorker`** emits the worker that `provideShell()` already registers for you (inert in",
|
|
32084
|
+
"dev) \u2014 never add `provideServiceWorker` yourself, and if you would rather ship no worker at all,",
|
|
32085
|
+
"drop `ngsw-config.json` and pass `provideShell({ serviceWorker: false })`, because otherwise the",
|
|
32086
|
+
"registration 404s in production. **`optimization.styles.inlineCritical: false`** is not optional:",
|
|
32087
|
+
"the `index.html` above ships a strict `script-src 'self'`, and Angular's critical-CSS pass loads",
|
|
32088
|
+
"the stylesheet with an **inline** `onload` handler that the policy blocks \u2014 the app then renders",
|
|
32089
|
+
"completely unstyled, and only in production builds.",
|
|
32090
|
+
"",
|
|
32091
|
+
"One thing is still yours, because the scaffold cannot know your budget: a production build warns",
|
|
32092
|
+
"that the initial bundle exceeds Angular's 500 kB default. The shell is a whole application",
|
|
32093
|
+
"chrome, so raise the budgets in your build target.",
|
|
32094
|
+
"",
|
|
32095
|
+
"## Ship less than the whole workbench",
|
|
32096
|
+
"",
|
|
32097
|
+
"The shell arrives with every capability on: splitting, dragging tabs between panes, pinning,",
|
|
32098
|
+
"stacking views, pop-out windows, keyboard shortcuts, the curation checklists. A product whose",
|
|
32099
|
+
"users would be overwhelmed by that switches parts off in the same providers array:",
|
|
32100
|
+
"",
|
|
32101
|
+
"```ts",
|
|
32102
|
+
"import { provideShellFeatures } from '@loomweaver/shell';",
|
|
32103
|
+
"",
|
|
32104
|
+
" provideShellFeatures({",
|
|
32105
|
+
" content: { splitRight: false, splitDown: false, moveTabs: false },",
|
|
32106
|
+
" sidebar: { stackViews: false },",
|
|
32107
|
+
" windows: { popout: false },",
|
|
32108
|
+
" }),",
|
|
32109
|
+
"```",
|
|
32110
|
+
"",
|
|
32111
|
+
"A switch takes the **affordance and the gesture**: turning `splitRight` off removes the toolbar",
|
|
32112
|
+
"button, the drop edges *and* `mod+\\`, so the capability cannot come back through a second door.",
|
|
32113
|
+
"Fields merge group by group, so name only what you turn off. The groups are `content`,",
|
|
32114
|
+
"`sidebar`, `rail`, `workspaces`, `windows` and `commands`; everything is on by default except",
|
|
32115
|
+
"`content.escalate`, the unlabelled double-click cycle on a tab.",
|
|
32116
|
+
"",
|
|
32117
|
+
"That provider is for **gestures**. A command, a bar or rail item, a settings row or a menu entry",
|
|
32118
|
+
"is a *contribution* and goes instead \u2014 by id \u2014 into `provideShell({ omit: [...] })`. Where a",
|
|
32119
|
+
"capability is both, the feature switch wins and takes the menu entry with it.",
|
|
32120
|
+
"",
|
|
32121
|
+
"A product backend is optional: implement the settings-store / auth-source ports",
|
|
32122
|
+
"(`provideSettingsStore` / `provideAuthSource`, both against the `KeyValueStore` shape)",
|
|
32123
|
+
"with your own backend, or keep the local/anonymous defaults for a standalone UI.",
|
|
32124
|
+
"Working state stays on `WORKING_STATE_STORE` and never reaches your",
|
|
32125
|
+
"settings backend; back it separately with `provideWorkingStateStore` only if",
|
|
32126
|
+
"working state should travel across devices.",
|
|
32127
|
+
""
|
|
32128
|
+
].join("\n");
|
|
32129
|
+
}
|
|
32130
|
+
|
|
31854
32131
|
// ../devkit/src/recipes/angular-distribution/recipe.ts
|
|
31855
32132
|
var STYLES = ["tailwind", "precompiled"];
|
|
31856
32133
|
function resolveDistributionInput(input) {
|
|
@@ -31886,7 +32163,9 @@ bootstrapApplication(App, appConfig).catch((err) => console.error(err));
|
|
|
31886
32163
|
function appConfigTs(d) {
|
|
31887
32164
|
return `import { ApplicationConfig } from '@angular/core';
|
|
31888
32165
|
import {
|
|
32166
|
+
provideCommandPaletteEntry,
|
|
31889
32167
|
provideLayout,
|
|
32168
|
+
provideQuickOpenEntry,
|
|
31890
32169
|
provideShell,
|
|
31891
32170
|
provideShellRouter,
|
|
31892
32171
|
type ShellLayout,
|
|
@@ -31911,6 +32190,11 @@ export const appConfig: ApplicationConfig = {
|
|
|
31911
32190
|
provideShellRouter(),
|
|
31912
32191
|
provideShell(),
|
|
31913
32192
|
provideLayout(layout),
|
|
32193
|
+
/* The two searches the shell seeds: mod+k over commands, mod+p over open work. Both work
|
|
32194
|
+
without these two lines; these put the shortcut on screen for a user who does not know
|
|
32195
|
+
it. Delete either one, or pass { bar, slot, order } to place it elsewhere. */
|
|
32196
|
+
provideCommandPaletteEntry(),
|
|
32197
|
+
provideQuickOpenEntry(),
|
|
31914
32198
|
provideProductIdentity({
|
|
31915
32199
|
name: '${d.title}',
|
|
31916
32200
|
tagline: 'Built on LoomWeaver',
|
|
@@ -32068,194 +32352,11 @@ function manifest(d) {
|
|
|
32068
32352
|
2
|
|
32069
32353
|
);
|
|
32070
32354
|
}
|
|
32071
|
-
function stylesNotes(d) {
|
|
32072
|
-
if (d.styles === "precompiled") {
|
|
32073
|
-
return [
|
|
32074
|
-
"`src/styles.css` imports the stylesheet **we** compiled \u2014 tokens, the `.lw-*` class contracts",
|
|
32075
|
-
"and every utility the shell's own templates use, 67 KB minified and 11 KB over the wire. There",
|
|
32076
|
-
"is nothing to install and nothing to configure: no `tailwindcss`, no `.postcssrc.json`, no",
|
|
32077
|
-
"`@source` paths to miscount.",
|
|
32078
|
-
"",
|
|
32079
|
-
"What you give up is writing Tailwind utilities in *your own* templates. The `--lw-*` tokens stay",
|
|
32080
|
-
"available to any CSS you write, so re-theming stays a token remap rather than a fight.",
|
|
32081
|
-
"",
|
|
32082
|
-
"If you bring a CSS framework of your own, **import it into a cascade layer** \u2014 the file says how,",
|
|
32083
|
-
"and it is the one decision that determines whether the chrome survives the introduction. Prefer",
|
|
32084
|
-
"Tailwind after all? Re-run the scaffold with `--styles tailwind`."
|
|
32085
|
-
];
|
|
32086
|
-
}
|
|
32087
|
-
return [
|
|
32088
|
-
"`src/styles.css` compiles the shell's source theme with Tailwind 4, which is also what lets you",
|
|
32089
|
-
"write Tailwind utilities in your own templates. It needs two things the scaffold cannot add for",
|
|
32090
|
-
"you \u2014 the packages:",
|
|
32091
|
-
"",
|
|
32092
|
-
"```sh",
|
|
32093
|
-
"npm install -D tailwindcss @tailwindcss/postcss @tailwindcss/typography",
|
|
32094
|
-
"```",
|
|
32095
|
-
"",
|
|
32096
|
-
"and the PostCSS plugin, in a file next to your `package.json`:",
|
|
32097
|
-
"",
|
|
32098
|
-
"```jsonc",
|
|
32099
|
-
"// .postcssrc.json",
|
|
32100
|
-
'{ "plugins": { "@tailwindcss/postcss": {} } }',
|
|
32101
|
-
"```",
|
|
32102
|
-
"",
|
|
32103
|
-
"Use **semantic tokens only** in your own templates (`bg-surface`, `text-content`, `text-brand`,",
|
|
32104
|
-
"`border-border`), never raw palette colours.",
|
|
32105
|
-
"",
|
|
32106
|
-
"**Count the `../` hops in the `@source` line.** It is resolved from the stylesheet, not from the",
|
|
32107
|
-
"workspace root, and the scaffold derived it from where this project sits. Move the project and",
|
|
32108
|
-
"nothing errors \u2014 Tailwind simply emits none of the shell's classes and the app renders unstyled.",
|
|
32109
|
-
"",
|
|
32110
|
-
"Want none of this? Re-run the scaffold with `--styles precompiled` and you get a one-line",
|
|
32111
|
-
"stylesheet that needs no Tailwind at all \u2014 the right choice if your product is themed with",
|
|
32112
|
-
"Bootstrap, Bulma or hand-written CSS."
|
|
32113
|
-
];
|
|
32114
|
-
}
|
|
32115
|
-
function readme2(d) {
|
|
32116
|
-
return [
|
|
32117
|
-
`# ${d.title} \u2014 a LoomWeaver distribution`,
|
|
32118
|
-
"",
|
|
32119
|
-
`The composition root that assembles the platform into a shippable product. It renders the bare`,
|
|
32120
|
-
`shell out of the box; add your weavers and branding below. Your own README is untouched \u2014 the`,
|
|
32121
|
-
`scaffold writes its notes here so it can never overwrite prose you wrote.`,
|
|
32122
|
-
"",
|
|
32123
|
-
"## Run it",
|
|
32124
|
-
"",
|
|
32125
|
-
"In an Nx workspace (the generator wired the project):",
|
|
32126
|
-
"",
|
|
32127
|
-
"```sh",
|
|
32128
|
-
`nx serve ${d.name}`,
|
|
32129
|
-
"```",
|
|
32130
|
-
"",
|
|
32131
|
-
"Scaffolded over the CLI or MCP, these files are sources without build wiring \u2014 drop them into",
|
|
32132
|
-
"an application you already serve (`ng new`, or an Nx application). They keep Angular's own",
|
|
32133
|
-
"shape: `main.ts` bootstraps `App`, `App` renders `<lw-shell />`, and everything this product is",
|
|
32134
|
-
"made of lives in `app.config.ts`. Nothing of the generated app is deleted. Over an existing",
|
|
32135
|
-
"application `--force` replaces exactly the files above \u2014 all of them bootstrap wiring, none of",
|
|
32136
|
-
"them content you authored. Under Nx it additionally merges the build targets into that",
|
|
32137
|
-
"project's `project.json`, keeping the targets, `implicitDependencies` and tags it already had.",
|
|
32138
|
-
"",
|
|
32139
|
-
"Two leftovers from `ng new` are no longer referenced and can go: `src/app/app.routes.ts` (the",
|
|
32140
|
-
"shell owns content routing via `provideShellRouter()`) and `src/app/app.css`. The generated",
|
|
32141
|
-
"`src/app/app.spec.ts` now fails \u2014 `App` pulls the whole shell into a bare `TestBed` \u2014 so delete",
|
|
32142
|
-
"it and test your own components instead of the composition root.",
|
|
32143
|
-
"",
|
|
32144
|
-
"The project is generated **untagged**: Nx tags belong to your `depConstraints`, and inventing",
|
|
32145
|
-
"one would fail a lint policy you never opted this project into. If your workspace enforces",
|
|
32146
|
-
"module boundaries, give it tags your constraints allow \u2014 `--tags` at generation time, or",
|
|
32147
|
-
"`tags` in `project.json` afterwards.",
|
|
32148
|
-
"",
|
|
32149
|
-
"## Compose weavers + branding (in `src/app/app.config.ts`)",
|
|
32150
|
-
"",
|
|
32151
|
-
"The layout is already there. Adding a weaver is three providers plus its import \u2014 note the",
|
|
32152
|
-
"**spread**, since `providePlugins` is variadic and returns an array:",
|
|
32153
|
-
"",
|
|
32154
|
-
"```ts",
|
|
32155
|
-
"import { providePlugins, provideCapabilityGrants, provideTranslationNamespaces } from '@loomweaver/shell';",
|
|
32156
|
-
"import { notesPlugin } from '@acme/notes-weaver'; // Nx: the workspace alias; otherwise a relative path",
|
|
32157
|
-
"",
|
|
32158
|
-
" provideTranslationNamespaces('notes'),",
|
|
32159
|
-
" provideCapabilityGrants({ notes: ['contributions', 'ui', 'navigation'] }),",
|
|
32160
|
-
" ...providePlugins(notesPlugin),",
|
|
32161
|
-
"```",
|
|
32162
|
-
"",
|
|
32163
|
-
"Grant exactly what the weaver's manifest declares \u2014 the broker is default-deny, so an ungranted",
|
|
32164
|
-
"plugin throws `CapabilityError` instead of quietly doing less. A weaver also needs its",
|
|
32165
|
-
"translations served: add an assets glob for its `src/lib/i18n` under `i18n/<id>` (the Nx",
|
|
32166
|
-
"generator does this for you).",
|
|
32167
|
-
"",
|
|
32168
|
-
"`public/logo.svg` is the LoomWeaver mark, dropped in as a placeholder so the top bar renders",
|
|
32169
|
-
"something from the first run instead of a broken image. Replace it with your own \u2014 any square",
|
|
32170
|
-
"image will do; `logoUrl` resolves against your served root. `tagline` is a",
|
|
32171
|
-
"translation key that falls back to rendering itself, so the literal above works but makes",
|
|
32172
|
-
"Transloco log a missing-translation warning in dev; point it at a key of your own to silence it.",
|
|
32173
|
-
"",
|
|
32174
|
-
"That same file is also the **app icon**: the browser tab reads it, and the manifest names it so",
|
|
32175
|
-
"the app has an icon at all. One gap is left on purpose, because a scaffold writes text and",
|
|
32176
|
-
"cannot invent your artwork: **Chromium only offers installation once the manifest names a 192",
|
|
32177
|
-
"and a 512 raster icon**, and iOS ignores manifest icons entirely in favour of",
|
|
32178
|
-
"`apple-touch-icon`. Drop `icon-192.png` and `icon-512.png` next to the logo, add them to the",
|
|
32179
|
-
"manifest's `icons` and add an `apple-touch-icon` link to `index.html`, and the app becomes",
|
|
32180
|
-
"installable. Until then it runs and caches offline, it simply is not offered for installation.",
|
|
32181
|
-
"",
|
|
32182
|
-
"## Styles",
|
|
32183
|
-
"",
|
|
32184
|
-
...stylesNotes(d),
|
|
32185
|
-
"",
|
|
32186
|
-
"## Build wiring",
|
|
32187
|
-
"",
|
|
32188
|
-
"The Nx generator put all of this in `project.json`. Scaffolded over the CLI or MCP, add it to",
|
|
32189
|
-
"your build target yourself \u2014 `angular.json` under `projects.<name>.architect.build.options` with",
|
|
32190
|
-
"the Angular CLI, `project.json` under `targets.build.options` in Nx. Paths inside `assets` are",
|
|
32191
|
-
"resolved from the workspace root, so they read the same either way:",
|
|
32192
|
-
"",
|
|
32193
|
-
"```jsonc",
|
|
32194
|
-
'"styles": ["src/styles.css"],',
|
|
32195
|
-
'"assets": [',
|
|
32196
|
-
' { "glob": "**/*", "input": "public" },',
|
|
32197
|
-
' { "glob": "**/*", "input": "node_modules/@loomweaver/shell/i18n", "output": "i18n" },',
|
|
32198
|
-
' { "glob": "**/*", "input": "node_modules/@loomweaver/frame-kit/dist", "output": "frame-kit" }',
|
|
32199
|
-
"],",
|
|
32200
|
-
'"serviceWorker": "ngsw-config.json"',
|
|
32201
|
-
"```",
|
|
32202
|
-
"",
|
|
32203
|
-
"And in the **production** configuration of that same target:",
|
|
32204
|
-
"",
|
|
32205
|
-
"```jsonc",
|
|
32206
|
-
'"optimization": { "styles": { "inlineCritical": false } }',
|
|
32207
|
-
"```",
|
|
32208
|
-
"",
|
|
32209
|
-
"Each of those earns its place. The **`@loomweaver/shell/i18n` glob** is the one whose absence is easy",
|
|
32210
|
-
"to misread: the shell fetches its own UI strings at runtime, so without it every label in the",
|
|
32211
|
-
"chrome renders as its raw translation key and nothing errors. The **frame-kit** glob only",
|
|
32212
|
-
"matters if you host sandboxed (iframe) plugins \u2014 install that package then; until you do, the",
|
|
32213
|
-
"glob simply matches nothing. **`serviceWorker`** emits the worker that `provideShell()` already",
|
|
32214
|
-
"registers for you (inert in dev) \u2014 never add `provideServiceWorker` yourself, and if you would",
|
|
32215
|
-
"rather ship no worker at all, drop `ngsw-config.json` and pass",
|
|
32216
|
-
"`provideShell({ serviceWorker: false })`, because otherwise the registration 404s in production.",
|
|
32217
|
-
"**`inlineCritical: false`** is not optional here: the `index.html` above ships a strict",
|
|
32218
|
-
"`script-src 'self'`, and Angular's critical-CSS pass loads the stylesheet with an **inline**",
|
|
32219
|
-
"`onload` handler that the policy blocks \u2014 the app then renders completely unstyled, and only in",
|
|
32220
|
-
"production builds.",
|
|
32221
|
-
"",
|
|
32222
|
-
"## Ship less than the whole workbench",
|
|
32223
|
-
"",
|
|
32224
|
-
"The shell arrives with every capability on: splitting, dragging tabs between panes, pinning,",
|
|
32225
|
-
"stacking views, pop-out windows, keyboard shortcuts, the curation checklists. A product whose",
|
|
32226
|
-
"users would be overwhelmed by that switches parts off in the same providers array:",
|
|
32227
|
-
"",
|
|
32228
|
-
"```ts",
|
|
32229
|
-
"import { provideShellFeatures } from '@loomweaver/shell';",
|
|
32230
|
-
"",
|
|
32231
|
-
" provideShellFeatures({",
|
|
32232
|
-
" content: { splitRight: false, splitDown: false, moveTabs: false },",
|
|
32233
|
-
" sidebar: { stackViews: false },",
|
|
32234
|
-
" windows: { popout: false },",
|
|
32235
|
-
" }),",
|
|
32236
|
-
"```",
|
|
32237
|
-
"",
|
|
32238
|
-
"A switch takes the **affordance and the gesture**: turning `splitRight` off removes the toolbar",
|
|
32239
|
-
"button, the drop edges *and* `mod+\\`, so the capability cannot come back through a second door.",
|
|
32240
|
-
"Fields merge group by group, so name only what you turn off. The groups are `content`,",
|
|
32241
|
-
"`sidebar`, `rail`, `workspaces`, `windows` and `commands`; everything is on by default except",
|
|
32242
|
-
"`content.escalate`, the unlabelled double-click cycle on a tab.",
|
|
32243
|
-
"",
|
|
32244
|
-
"That provider is for **gestures**. A command, a bar or rail item, a settings row or a menu entry",
|
|
32245
|
-
"is a *contribution* and goes instead \u2014 by id \u2014 into `provideShell({ omit: [...] })`. Where a",
|
|
32246
|
-
"capability is both, the feature switch wins and takes the menu entry with it.",
|
|
32247
|
-
"",
|
|
32248
|
-
"A product backend is optional: implement the settings-store / auth-source ports",
|
|
32249
|
-
"(`provideSettingsStore` / `provideAuthSource`, both against the `KeyValueStore` shape)",
|
|
32250
|
-
"with your own backend, or keep the local/anonymous defaults for a standalone UI.",
|
|
32251
|
-
"Working state stays on `WORKING_STATE_STORE` and never reaches your",
|
|
32252
|
-
"settings backend; back it separately with `provideWorkingStateStore` only if",
|
|
32253
|
-
"working state should travel across devices.",
|
|
32254
|
-
""
|
|
32255
|
-
].join("\n");
|
|
32256
|
-
}
|
|
32257
32355
|
var angularDistribution = {
|
|
32258
32356
|
id: "angular-distribution",
|
|
32357
|
+
amend(input) {
|
|
32358
|
+
return distributionAmendments(resolveDistributionInput(input));
|
|
32359
|
+
},
|
|
32259
32360
|
build(input) {
|
|
32260
32361
|
const d = resolveDistributionInput(input);
|
|
32261
32362
|
return {
|
|
@@ -32546,6 +32647,67 @@ var layout = {
|
|
|
32546
32647
|
}
|
|
32547
32648
|
};
|
|
32548
32649
|
|
|
32650
|
+
// ../devkit/src/recipes/angular-weaver/amendments.ts
|
|
32651
|
+
function weaverAmendments(input, where) {
|
|
32652
|
+
const w = resolveWeaverInput(input);
|
|
32653
|
+
const directory = (where ?? "").replace(/^\.?\/*/, "").replace(/\/+$/, "");
|
|
32654
|
+
if (!directory) {
|
|
32655
|
+
return [];
|
|
32656
|
+
}
|
|
32657
|
+
return [
|
|
32658
|
+
{
|
|
32659
|
+
kind: "build-target",
|
|
32660
|
+
styles: [],
|
|
32661
|
+
assets: [
|
|
32662
|
+
{
|
|
32663
|
+
glob: "**/*.json",
|
|
32664
|
+
input: `${directory}/src/lib/i18n`,
|
|
32665
|
+
from: "workspace",
|
|
32666
|
+
output: `i18n/${w.id}`
|
|
32667
|
+
}
|
|
32668
|
+
]
|
|
32669
|
+
},
|
|
32670
|
+
{ kind: "stylesheet-source", sourceRoot: `${directory}/src` },
|
|
32671
|
+
{
|
|
32672
|
+
kind: "compose-plugin",
|
|
32673
|
+
id: w.id,
|
|
32674
|
+
symbol: `${w.propertyName}Plugin`,
|
|
32675
|
+
capabilities: w.capabilities,
|
|
32676
|
+
sourceRoot: `${directory}/src`
|
|
32677
|
+
}
|
|
32678
|
+
];
|
|
32679
|
+
}
|
|
32680
|
+
|
|
32681
|
+
// ../devkit/src/lib/scaffolds/inputs.ts
|
|
32682
|
+
function weaverInput(values) {
|
|
32683
|
+
return {
|
|
32684
|
+
id: str(values, "id") ?? "",
|
|
32685
|
+
name: str(values, "name"),
|
|
32686
|
+
prefix: str(values, "prefix"),
|
|
32687
|
+
importPath: str(values, "importPath"),
|
|
32688
|
+
features: {
|
|
32689
|
+
command: bool(values, "command"),
|
|
32690
|
+
shortcut: str(values, "shortcut"),
|
|
32691
|
+
menu: str(values, "menu"),
|
|
32692
|
+
barItem: bool(values, "barItem"),
|
|
32693
|
+
settings: bool(values, "settings"),
|
|
32694
|
+
about: bool(values, "about"),
|
|
32695
|
+
instanceable: bool(values, "instanceable"),
|
|
32696
|
+
container: bool(values, "container"),
|
|
32697
|
+
access: str(values, "access"),
|
|
32698
|
+
spec: bool(values, "spec")
|
|
32699
|
+
}
|
|
32700
|
+
};
|
|
32701
|
+
}
|
|
32702
|
+
function distributionInput(values) {
|
|
32703
|
+
return {
|
|
32704
|
+
name: str(values, "name") ?? "",
|
|
32705
|
+
title: str(values, "title"),
|
|
32706
|
+
directory: str(values, "directory"),
|
|
32707
|
+
styles: str(values, "styles") ?? "tailwind"
|
|
32708
|
+
};
|
|
32709
|
+
}
|
|
32710
|
+
|
|
32549
32711
|
// ../devkit/src/lib/scaffolds/scaffolds.ts
|
|
32550
32712
|
function str(values, name) {
|
|
32551
32713
|
const value = values[name];
|
|
@@ -32681,24 +32843,8 @@ var SCAFFOLDS = [
|
|
|
32681
32843
|
APP_OPTION,
|
|
32682
32844
|
...PLACEMENT_OPTIONS
|
|
32683
32845
|
],
|
|
32684
|
-
build: (values) => generate(angularWeaver,
|
|
32685
|
-
|
|
32686
|
-
name: str(values, "name"),
|
|
32687
|
-
prefix: str(values, "prefix"),
|
|
32688
|
-
importPath: str(values, "importPath"),
|
|
32689
|
-
features: {
|
|
32690
|
-
command: bool(values, "command"),
|
|
32691
|
-
shortcut: str(values, "shortcut"),
|
|
32692
|
-
menu: str(values, "menu"),
|
|
32693
|
-
barItem: bool(values, "barItem"),
|
|
32694
|
-
settings: bool(values, "settings"),
|
|
32695
|
-
about: bool(values, "about"),
|
|
32696
|
-
instanceable: bool(values, "instanceable"),
|
|
32697
|
-
container: bool(values, "container"),
|
|
32698
|
-
access: str(values, "access"),
|
|
32699
|
-
spec: bool(values, "spec")
|
|
32700
|
-
}
|
|
32701
|
-
})
|
|
32846
|
+
build: (values) => generate(angularWeaver, weaverInput(values)),
|
|
32847
|
+
amend: (values) => weaverAmendments(weaverInput(values), str(values, "directory"))
|
|
32702
32848
|
},
|
|
32703
32849
|
{
|
|
32704
32850
|
name: "frame-plugin",
|
|
@@ -32754,12 +32900,8 @@ var SCAFFOLDS = [
|
|
|
32754
32900
|
},
|
|
32755
32901
|
...PLACEMENT_OPTIONS
|
|
32756
32902
|
],
|
|
32757
|
-
build: (values) => generate(angularDistribution,
|
|
32758
|
-
|
|
32759
|
-
title: str(values, "title"),
|
|
32760
|
-
directory: str(values, "directory"),
|
|
32761
|
-
styles: str(values, "styles") ?? "tailwind"
|
|
32762
|
-
})
|
|
32903
|
+
build: (values) => generate(angularDistribution, distributionInput(values)),
|
|
32904
|
+
amend: (values) => amendments(angularDistribution, distributionInput(values))
|
|
32763
32905
|
},
|
|
32764
32906
|
{
|
|
32765
32907
|
name: "auth-source",
|
|
@@ -33130,7 +33272,12 @@ function valuesFor(scaffold2, args) {
|
|
|
33130
33272
|
return values;
|
|
33131
33273
|
}
|
|
33132
33274
|
function scaffold(scaffold2, args) {
|
|
33133
|
-
|
|
33275
|
+
const values = valuesFor(scaffold2, args);
|
|
33276
|
+
const remaining = (scaffold2.amend?.(values) ?? []).map(describeAmendment);
|
|
33277
|
+
return ok({
|
|
33278
|
+
files: scaffold2.build(values),
|
|
33279
|
+
...remaining.length > 0 ? { remaining } : {}
|
|
33280
|
+
});
|
|
33134
33281
|
}
|
|
33135
33282
|
function validateManifestTool(a) {
|
|
33136
33283
|
return ok({
|
|
@@ -33150,7 +33297,7 @@ function validateI18nTool(a) {
|
|
|
33150
33297
|
}
|
|
33151
33298
|
|
|
33152
33299
|
// src/lib/server.ts
|
|
33153
|
-
var FILE_MAP_NOTE =
|
|
33300
|
+
var FILE_MAP_NOTE = 'Returns a file map (relative path -> content); write the files into your project. May also return "remaining": steps the workspace needs that this route cannot perform, each saying what it costs to skip. Carry them out, or the generated output builds and does not work.';
|
|
33154
33301
|
function inputSchema(descriptor) {
|
|
33155
33302
|
const shape = {};
|
|
33156
33303
|
for (const option of portableOptions(descriptor)) {
|
|
@@ -33163,7 +33310,7 @@ function inputSchema(descriptor) {
|
|
|
33163
33310
|
function createMcpServer() {
|
|
33164
33311
|
const server = new McpServer({
|
|
33165
33312
|
name: "loomweaver-devkit",
|
|
33166
|
-
version: "0.7.
|
|
33313
|
+
version: "0.7.4"
|
|
33167
33314
|
});
|
|
33168
33315
|
server.registerTool(
|
|
33169
33316
|
"list_generators",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loomweaver/mcp",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.4",
|
|
4
4
|
"description": "LoomWeaver MCP server: exposes LoomWeaver's scaffolding and validation as MCP tools, so an AI assistant in any product repo can scaffold and validate weavers, distributions and integrations without a LoomWeaver checkout.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"loomweaver",
|