@tonycodes-ui/mortar 0.0.0-stage → 0.11.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/AGENTS.md +10 -0
- package/CHANGELOG.md +276 -0
- package/CONTRIBUTING.md +48 -0
- package/DESIGN.md +51 -0
- package/LICENSE +21 -0
- package/README.md +155 -2
- package/TESTING.md +83 -0
- package/baseline-policy.json +16 -0
- package/bin/mortar.mjs +258 -0
- package/catalog.json +9703 -0
- package/cli/audit.mjs +943 -0
- package/cli/data.mjs +176 -0
- package/cli/mcp.mjs +216 -0
- package/cli/migrations.mjs +128 -0
- package/cli/packet.mjs +267 -0
- package/cli/search.mjs +246 -0
- package/cli/tools.mjs +229 -0
- package/design-principles.json +30 -0
- package/dist/agent-data.json +1 -0
- package/dist/application.d.ts +340 -0
- package/dist/application.js +240 -0
- package/dist/auth.d.ts +121 -0
- package/dist/auth.js +97 -0
- package/dist/brand.d.ts +69 -0
- package/dist/brand.js +266 -0
- package/dist/calendar.d.ts +75 -0
- package/dist/calendar.js +310 -0
- package/dist/choice.d.ts +36 -0
- package/dist/choice.js +36 -0
- package/dist/composer.d.ts +28 -0
- package/dist/composer.js +47 -0
- package/dist/display.d.ts +136 -0
- package/dist/display.js +75 -0
- package/dist/docs.d.ts +145 -0
- package/dist/docs.js +141 -0
- package/dist/ecommerce.d.ts +261 -0
- package/dist/ecommerce.js +177 -0
- package/dist/feedback.d.ts +80 -0
- package/dist/feedback.js +98 -0
- package/dist/foundation.d.ts +42 -0
- package/dist/foundation.js +121 -0
- package/dist/heading.d.ts +5 -0
- package/dist/heading.js +9 -0
- package/dist/icons.d.ts +50 -0
- package/dist/icons.js +70 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.js +17 -0
- package/dist/inspection.d.ts +24 -0
- package/dist/inspection.js +14 -0
- package/dist/internal.d.ts +492 -0
- package/dist/internal.js +273 -0
- package/dist/layout.d.ts +107 -0
- package/dist/layout.js +66 -0
- package/dist/marketing-sections.d.ts +161 -0
- package/dist/marketing-sections.js +58 -0
- package/dist/marketing.d.ts +254 -0
- package/dist/marketing.js +150 -0
- package/dist/navigation.d.ts +35 -0
- package/dist/navigation.js +44 -0
- package/dist/primitives.d.ts +258 -0
- package/dist/primitives.js +244 -0
- package/dist/showcase.d.ts +29 -0
- package/dist/showcase.js +10 -0
- package/dist/workspace.d.ts +80 -0
- package/dist/workspace.js +48 -0
- package/docs/agents.md +127 -0
- package/docs/auth-flows.md +71 -0
- package/docs/migrating-to-0.6.md +94 -0
- package/docs/theming.md +170 -0
- package/package.json +94 -4
- package/skills/mortar/SKILL.md +36 -0
- package/src/application.css +1487 -0
- package/src/application.tsx +1413 -0
- package/src/auth.tsx +452 -0
- package/src/brand.ts +335 -0
- package/src/calendar.css +468 -0
- package/src/calendar.tsx +868 -0
- package/src/choice.tsx +240 -0
- package/src/composer.tsx +158 -0
- package/src/data.css +690 -0
- package/src/display.tsx +452 -0
- package/src/docs.css +704 -0
- package/src/docs.tsx +737 -0
- package/src/ecommerce.css +810 -0
- package/src/ecommerce.tsx +1033 -0
- package/src/feedback.tsx +388 -0
- package/src/foundation.css +1867 -0
- package/src/foundation.tsx +227 -0
- package/src/heading.ts +13 -0
- package/src/icons.tsx +237 -0
- package/src/index.ts +230 -0
- package/src/inspection.tsx +91 -0
- package/src/internal.tsx +614 -0
- package/src/layout.tsx +342 -0
- package/src/marketing-sections.tsx +621 -0
- package/src/marketing.css +2400 -0
- package/src/marketing.tsx +1156 -0
- package/src/navigation.tsx +118 -0
- package/src/overlays.css +350 -0
- package/src/primitives.tsx +1135 -0
- package/src/showcase.tsx +120 -0
- package/src/tokens.css +449 -0
- package/src/workspace.tsx +333 -0
- package/styles.css +56 -0
package/cli/data.mjs
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
// Loads what the CLI and MCP server describe: the installed package's own
|
|
2
|
+
// catalog.json, docs and build-time data (dist/agent-data.json, generated by
|
|
3
|
+
// scripts/agent-data.mjs during `npm run build`). Nothing is fetched; the data
|
|
4
|
+
// always matches the installed version.
|
|
5
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
6
|
+
import { resolve, dirname, join } from "node:path";
|
|
7
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
8
|
+
|
|
9
|
+
export const PACKAGE_ROOT = resolve(
|
|
10
|
+
dirname(fileURLToPath(import.meta.url)),
|
|
11
|
+
"..",
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
const readJson = (file) => JSON.parse(readFileSync(file, "utf8"));
|
|
15
|
+
|
|
16
|
+
/** Guide topic → the shipped markdown file (and an optional section). */
|
|
17
|
+
export const GUIDES = {
|
|
18
|
+
design: {
|
|
19
|
+
file: "DESIGN.md",
|
|
20
|
+
summary: "Design principles, API conventions and composing flows.",
|
|
21
|
+
},
|
|
22
|
+
conventions: {
|
|
23
|
+
file: "DESIGN.md",
|
|
24
|
+
section: "API conventions",
|
|
25
|
+
summary:
|
|
26
|
+
"Prop naming rules every component follows: headings, layout/variant/align, tone, state, callbacks, items, className, data attributes.",
|
|
27
|
+
},
|
|
28
|
+
theming: {
|
|
29
|
+
file: "docs/theming.md",
|
|
30
|
+
summary:
|
|
31
|
+
"Brands, appearance (light/dark/system), density, runtime brandTokens and the token scales.",
|
|
32
|
+
},
|
|
33
|
+
"auth-flows": {
|
|
34
|
+
file: "docs/auth-flows.md",
|
|
35
|
+
summary:
|
|
36
|
+
"Sign-in and registration: each step mapped to components, autocomplete values, validation, security and accessibility.",
|
|
37
|
+
},
|
|
38
|
+
"migrating-0.6": {
|
|
39
|
+
file: "docs/migrating-to-0.6.md",
|
|
40
|
+
summary: "Every prop and markup change from 0.5 to 0.6.",
|
|
41
|
+
},
|
|
42
|
+
contributing: {
|
|
43
|
+
file: "CONTRIBUTING.md",
|
|
44
|
+
also: ["AGENTS.md"],
|
|
45
|
+
summary:
|
|
46
|
+
"How to contribute a component or fix through a GitHub pull request, and the rules for coding agents.",
|
|
47
|
+
},
|
|
48
|
+
testing: {
|
|
49
|
+
file: "TESTING.md",
|
|
50
|
+
summary:
|
|
51
|
+
"The component test contract: profiles, states, browser and visual checks.",
|
|
52
|
+
},
|
|
53
|
+
agents: {
|
|
54
|
+
file: "docs/agents.md",
|
|
55
|
+
summary: "How a coding agent uses Mortar with this MCP server and CLI.",
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/** One `## Heading` section of a markdown document. */
|
|
60
|
+
export function markdownSection(text, heading) {
|
|
61
|
+
const lines = text.split("\n");
|
|
62
|
+
const start = lines.findIndex((l) => l.trim() === `## ${heading}`);
|
|
63
|
+
if (start < 0) return "";
|
|
64
|
+
let end = lines.findIndex((l, i) => i > start && /^## /.test(l));
|
|
65
|
+
if (end < 0) end = lines.length;
|
|
66
|
+
return lines.slice(start, end).join("\n").trim();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
let cached;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* The data for a package root. `root` defaults to this package; the audit
|
|
73
|
+
* passes an application's installed copy when it has one.
|
|
74
|
+
*/
|
|
75
|
+
export async function loadData(root = PACKAGE_ROOT) {
|
|
76
|
+
if (root === PACKAGE_ROOT && cached) return cached;
|
|
77
|
+
const catalog = readJson(join(root, "catalog.json"));
|
|
78
|
+
let agent;
|
|
79
|
+
const built = join(root, "dist", "agent-data.json");
|
|
80
|
+
if (existsSync(built)) agent = readJson(built);
|
|
81
|
+
else if (existsSync(join(root, "scripts", "agent-data.mjs"))) {
|
|
82
|
+
// A source checkout that has not been built yet (needs devDependencies).
|
|
83
|
+
try {
|
|
84
|
+
const { agentData } = await import(
|
|
85
|
+
pathToFileURL(join(root, "scripts", "agent-data.mjs")).href
|
|
86
|
+
);
|
|
87
|
+
agent = agentData(root);
|
|
88
|
+
} catch {
|
|
89
|
+
agent = undefined;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
agent ??= {
|
|
93
|
+
taxonomy: { kits: [] },
|
|
94
|
+
templates: [],
|
|
95
|
+
exports: { values: catalog.components.map((c) => c.export), types: [] },
|
|
96
|
+
examples: {},
|
|
97
|
+
inherited: {},
|
|
98
|
+
inheritedSets: [],
|
|
99
|
+
classes: [],
|
|
100
|
+
sourceHashes: {},
|
|
101
|
+
missing: true,
|
|
102
|
+
};
|
|
103
|
+
let principles = [];
|
|
104
|
+
const principlesFile = join(root, "design-principles.json");
|
|
105
|
+
if (existsSync(principlesFile))
|
|
106
|
+
principles = readJson(principlesFile).principles;
|
|
107
|
+
const pkg = readJson(join(root, "package.json"));
|
|
108
|
+
const data = makeData({ root, catalog, agent, principles, pkg });
|
|
109
|
+
if (root === PACKAGE_ROOT) cached = data;
|
|
110
|
+
return data;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function makeData({ root, catalog, agent, principles, pkg }) {
|
|
114
|
+
const components = catalog.components;
|
|
115
|
+
const byId = new Map(components.map((c) => [c.id, c]));
|
|
116
|
+
const byName = new Map(components.map((c) => [c.export.toLowerCase(), c]));
|
|
117
|
+
// Category and kit for each component, from the playground taxonomy.
|
|
118
|
+
const placement = new Map();
|
|
119
|
+
for (const kit of agent.taxonomy.kits)
|
|
120
|
+
for (const category of kit.categories)
|
|
121
|
+
for (const name of category.components)
|
|
122
|
+
placement.set(name, { kit, category });
|
|
123
|
+
const kitTitle = (id) =>
|
|
124
|
+
agent.taxonomy.kits.find((k) => k.id === id)?.title ?? id;
|
|
125
|
+
return {
|
|
126
|
+
root,
|
|
127
|
+
packageName: catalog.package ?? pkg.name,
|
|
128
|
+
version: catalog.version ?? pkg.version,
|
|
129
|
+
catalog,
|
|
130
|
+
components,
|
|
131
|
+
agent,
|
|
132
|
+
principles,
|
|
133
|
+
/** A component by export name (any case) or catalogue id. */
|
|
134
|
+
find(name) {
|
|
135
|
+
if (typeof name !== "string") return undefined;
|
|
136
|
+
const key = name.trim().replace(/^<|\/?>$/g, "");
|
|
137
|
+
return (
|
|
138
|
+
byName.get(key.toLowerCase()) ??
|
|
139
|
+
byId.get(key) ??
|
|
140
|
+
byId.get(`mortar-${key}`)
|
|
141
|
+
);
|
|
142
|
+
},
|
|
143
|
+
byId: (id) => byId.get(id),
|
|
144
|
+
placement(c) {
|
|
145
|
+
const p = placement.get(c.export);
|
|
146
|
+
return {
|
|
147
|
+
kit: p?.kit.id ?? c.kitId,
|
|
148
|
+
kitTitle: p?.kit.title ?? kitTitle(c.kitId),
|
|
149
|
+
category: p?.category.id,
|
|
150
|
+
categoryTitle: p?.category.title,
|
|
151
|
+
};
|
|
152
|
+
},
|
|
153
|
+
/** Every prop name the component accepts, including inherited DOM attributes. */
|
|
154
|
+
accepts(c) {
|
|
155
|
+
const names = new Set(Object.keys(c.contract.propTypes ?? {}));
|
|
156
|
+
const set = agent.inherited[c.export];
|
|
157
|
+
if (set !== undefined)
|
|
158
|
+
for (const n of agent.inheritedSets[set]) names.add(n);
|
|
159
|
+
return names;
|
|
160
|
+
},
|
|
161
|
+
guide(topic) {
|
|
162
|
+
const g = GUIDES[topic];
|
|
163
|
+
if (!g) return undefined;
|
|
164
|
+
const parts = [];
|
|
165
|
+
for (const file of [g.file, ...(g.also ?? [])]) {
|
|
166
|
+
const path = join(root, file);
|
|
167
|
+
if (!existsSync(path)) continue;
|
|
168
|
+
let text = readFileSync(path, "utf8");
|
|
169
|
+
if (g.section && file === g.file)
|
|
170
|
+
text = markdownSection(text, g.section);
|
|
171
|
+
parts.push(text.trim());
|
|
172
|
+
}
|
|
173
|
+
return parts.length ? parts.join("\n\n---\n\n") : undefined;
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
}
|
package/cli/mcp.mjs
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
// A Model Context Protocol server over stdio: newline-delimited JSON-RPC 2.0 on
|
|
2
|
+
// stdin/stdout, implemented without dependencies. Only JSON-RPC messages are
|
|
3
|
+
// written to stdout; diagnostics go to stderr.
|
|
4
|
+
import { createInterface } from "node:readline";
|
|
5
|
+
import { loadData } from "./data.mjs";
|
|
6
|
+
import { TOOLS, ToolError, validateArguments } from "./tools.mjs";
|
|
7
|
+
|
|
8
|
+
/** Protocol revisions this server speaks, newest first. */
|
|
9
|
+
export const PROTOCOL_VERSIONS = [
|
|
10
|
+
"2025-11-25",
|
|
11
|
+
"2025-06-18",
|
|
12
|
+
"2025-03-26",
|
|
13
|
+
"2024-11-05",
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
export const ERRORS = {
|
|
17
|
+
PARSE: -32700,
|
|
18
|
+
INVALID_REQUEST: -32600,
|
|
19
|
+
METHOD_NOT_FOUND: -32601,
|
|
20
|
+
INVALID_PARAMS: -32602,
|
|
21
|
+
INTERNAL: -32603,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
class RpcError extends Error {
|
|
25
|
+
constructor(code, message, data) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.code = code;
|
|
28
|
+
this.data = data;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const INSTRUCTIONS =
|
|
33
|
+
"Mortar is an MIT React 19 + Tailwind 4 UI kit (@tonycodes-ui/mortar). Before writing UI, search_components (or list_kits) to find what to reuse, then get_build_packet for the components or the brief and compose from it: start from the purpose shell (AppShell, MarketingHeader, DocsShell, AuthLayout), use named imports and the exact props in each contract, theme through ThemeProvider and tokens, never copy components or override .m-* classes. Run audit_app on the application when done and fix its findings. Missing shared patterns are contributed to the kit by GitHub pull request (get_guide contributing).";
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Handle one parsed JSON-RPC message. Returns the response object, or
|
|
37
|
+
* undefined for notifications.
|
|
38
|
+
*/
|
|
39
|
+
export async function handleMessage(message, context) {
|
|
40
|
+
const isObject =
|
|
41
|
+
message && typeof message === "object" && !Array.isArray(message);
|
|
42
|
+
const id = isObject && "id" in message ? message.id : undefined;
|
|
43
|
+
const respond = (result) => ({ jsonrpc: "2.0", id, result });
|
|
44
|
+
const fail = (code, msg, data) => ({
|
|
45
|
+
jsonrpc: "2.0",
|
|
46
|
+
id: id === undefined ? null : id,
|
|
47
|
+
error: { code, message: msg, ...(data !== undefined ? { data } : {}) },
|
|
48
|
+
});
|
|
49
|
+
if (
|
|
50
|
+
!isObject ||
|
|
51
|
+
message.jsonrpc !== "2.0" ||
|
|
52
|
+
typeof message.method !== "string" ||
|
|
53
|
+
(id !== undefined &&
|
|
54
|
+
id !== null &&
|
|
55
|
+
typeof id !== "string" &&
|
|
56
|
+
typeof id !== "number")
|
|
57
|
+
) {
|
|
58
|
+
// A response from the client (we never send requests) needs no answer.
|
|
59
|
+
if (
|
|
60
|
+
isObject &&
|
|
61
|
+
message.jsonrpc === "2.0" &&
|
|
62
|
+
("result" in message || "error" in message)
|
|
63
|
+
)
|
|
64
|
+
return undefined;
|
|
65
|
+
return fail(ERRORS.INVALID_REQUEST, "Invalid Request");
|
|
66
|
+
}
|
|
67
|
+
const notification = id === undefined;
|
|
68
|
+
try {
|
|
69
|
+
const result = await dispatch(message.method, message.params, context);
|
|
70
|
+
return notification ? undefined : respond(result);
|
|
71
|
+
} catch (error) {
|
|
72
|
+
if (notification) return undefined;
|
|
73
|
+
if (error instanceof RpcError)
|
|
74
|
+
return fail(error.code, error.message, error.data);
|
|
75
|
+
context.log(`mortar mcp: ${error?.stack ?? error}`);
|
|
76
|
+
return fail(ERRORS.INTERNAL, "Internal error");
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async function dispatch(method, params = {}, context) {
|
|
81
|
+
if (params === null || typeof params !== "object")
|
|
82
|
+
throw new RpcError(ERRORS.INVALID_PARAMS, "params must be an object");
|
|
83
|
+
switch (method) {
|
|
84
|
+
case "initialize": {
|
|
85
|
+
const requested = params.protocolVersion;
|
|
86
|
+
if (typeof requested !== "string")
|
|
87
|
+
throw new RpcError(
|
|
88
|
+
ERRORS.INVALID_PARAMS,
|
|
89
|
+
"protocolVersion is required",
|
|
90
|
+
);
|
|
91
|
+
const data = await context.data();
|
|
92
|
+
context.initialized = true;
|
|
93
|
+
return {
|
|
94
|
+
protocolVersion: PROTOCOL_VERSIONS.includes(requested)
|
|
95
|
+
? requested
|
|
96
|
+
: PROTOCOL_VERSIONS[0],
|
|
97
|
+
capabilities: { tools: { listChanged: false } },
|
|
98
|
+
serverInfo: {
|
|
99
|
+
name: "mortar",
|
|
100
|
+
title: "Mortar UI kit",
|
|
101
|
+
version: data.version,
|
|
102
|
+
},
|
|
103
|
+
instructions: INSTRUCTIONS,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
case "notifications/initialized":
|
|
107
|
+
case "notifications/cancelled":
|
|
108
|
+
case "notifications/progress":
|
|
109
|
+
case "notifications/roots/list_changed":
|
|
110
|
+
return {};
|
|
111
|
+
case "ping":
|
|
112
|
+
return {};
|
|
113
|
+
case "tools/list":
|
|
114
|
+
return {
|
|
115
|
+
tools: TOOLS.map(({ run, ...tool }) => tool),
|
|
116
|
+
};
|
|
117
|
+
case "tools/call": {
|
|
118
|
+
const tool = TOOLS.find((t) => t.name === params.name);
|
|
119
|
+
if (!tool)
|
|
120
|
+
throw new RpcError(
|
|
121
|
+
ERRORS.INVALID_PARAMS,
|
|
122
|
+
`Unknown tool: ${params.name}`,
|
|
123
|
+
);
|
|
124
|
+
const args = params.arguments ?? {};
|
|
125
|
+
const invalid = validateArguments(tool, args);
|
|
126
|
+
if (invalid)
|
|
127
|
+
return {
|
|
128
|
+
content: [{ type: "text", text: `Invalid arguments: ${invalid}.` }],
|
|
129
|
+
isError: true,
|
|
130
|
+
};
|
|
131
|
+
try {
|
|
132
|
+
const result = await tool.run(await context.data(), args);
|
|
133
|
+
return {
|
|
134
|
+
content: [
|
|
135
|
+
{
|
|
136
|
+
type: "text",
|
|
137
|
+
text:
|
|
138
|
+
typeof result === "string"
|
|
139
|
+
? result
|
|
140
|
+
: JSON.stringify(result, null, 2),
|
|
141
|
+
},
|
|
142
|
+
],
|
|
143
|
+
};
|
|
144
|
+
} catch (error) {
|
|
145
|
+
if (!(error instanceof ToolError))
|
|
146
|
+
context.log(`mortar mcp: ${error?.stack ?? error}`);
|
|
147
|
+
return {
|
|
148
|
+
content: [{ type: "text", text: String(error?.message ?? error) }],
|
|
149
|
+
isError: true,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
default:
|
|
154
|
+
throw new RpcError(
|
|
155
|
+
ERRORS.METHOD_NOT_FOUND,
|
|
156
|
+
`Method not found: ${method}`,
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** Run the server on stdin/stdout until stdin closes. */
|
|
162
|
+
export function serve({
|
|
163
|
+
input = process.stdin,
|
|
164
|
+
output = process.stdout,
|
|
165
|
+
log = (line) => process.stderr.write(line + "\n"),
|
|
166
|
+
} = {}) {
|
|
167
|
+
// Nothing but protocol messages may reach stdout.
|
|
168
|
+
console.log = console.info = console.debug = (...args) => log(args.join(" "));
|
|
169
|
+
let dataPromise;
|
|
170
|
+
const context = {
|
|
171
|
+
data: () => (dataPromise ??= loadData()),
|
|
172
|
+
log,
|
|
173
|
+
initialized: false,
|
|
174
|
+
};
|
|
175
|
+
const write = (message) => output.write(JSON.stringify(message) + "\n");
|
|
176
|
+
// Messages are handled one at a time, in order, so responses keep the
|
|
177
|
+
// order of their requests.
|
|
178
|
+
let queue = Promise.resolve();
|
|
179
|
+
const lines = createInterface({ input, crlfDelay: Infinity });
|
|
180
|
+
lines.on("line", (line) => {
|
|
181
|
+
if (!line.trim()) return;
|
|
182
|
+
queue = queue.then(async () => {
|
|
183
|
+
let message;
|
|
184
|
+
try {
|
|
185
|
+
message = JSON.parse(line);
|
|
186
|
+
} catch {
|
|
187
|
+
write({
|
|
188
|
+
jsonrpc: "2.0",
|
|
189
|
+
id: null,
|
|
190
|
+
error: { code: ERRORS.PARSE, message: "Parse error" },
|
|
191
|
+
});
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
if (Array.isArray(message)) {
|
|
195
|
+
if (!message.length) {
|
|
196
|
+
write({
|
|
197
|
+
jsonrpc: "2.0",
|
|
198
|
+
id: null,
|
|
199
|
+
error: { code: ERRORS.INVALID_REQUEST, message: "Invalid Request" },
|
|
200
|
+
});
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const responses = (
|
|
204
|
+
await Promise.all(message.map((m) => handleMessage(m, context)))
|
|
205
|
+
).filter(Boolean);
|
|
206
|
+
if (responses.length) write(responses);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const response = await handleMessage(message, context);
|
|
210
|
+
if (response) write(response);
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
return new Promise((resolveDone) => {
|
|
214
|
+
lines.on("close", () => queue.then(resolveDone));
|
|
215
|
+
});
|
|
216
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// Removed names and their replacements, from docs/migrating-to-0.6.md and the
|
|
2
|
+
// CHANGELOG. The audit uses them to suggest the current name for an import, a
|
|
3
|
+
// prop or a value. tests/cli.test.mjs checks every replacement exists in the
|
|
4
|
+
// catalogue and every removed prop is gone.
|
|
5
|
+
|
|
6
|
+
export const REMOVED_EXPORTS = {
|
|
7
|
+
MarketingTone: {
|
|
8
|
+
replacement: "SectionTone",
|
|
9
|
+
note: "MarketingTone (surface | inverse) was merged into SectionTone (default | muted | inverse) in 0.6.",
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/** Component → removed prop → { to, note }. */
|
|
14
|
+
export const RENAMED_PROPS = {
|
|
15
|
+
AppShell: {
|
|
16
|
+
user: { to: "footer", note: "AppShell `user` became `footer` in 0.6." },
|
|
17
|
+
secondaryNavigation: {
|
|
18
|
+
to: "sections",
|
|
19
|
+
note: "AppShell `secondaryNavigation` became `sections` in 0.6.",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
Hero: {
|
|
23
|
+
align: {
|
|
24
|
+
to: "layout",
|
|
25
|
+
note: 'Hero `align="center" | "split"` became `layout` in 0.6.',
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
StackedList: {
|
|
29
|
+
heading: { to: "title", note: "StackedList `heading` became `title`." },
|
|
30
|
+
},
|
|
31
|
+
DataTable: {
|
|
32
|
+
emptyTitle: { to: "empty", note: "Use `empty={{ title, description? }}`." },
|
|
33
|
+
emptyDescription: {
|
|
34
|
+
to: "empty",
|
|
35
|
+
note: "Use `empty={{ title, description? }}`.",
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
Text: { tone: { to: "color", note: "Text `tone` became `color` in 0.6." } },
|
|
39
|
+
CommandPalette: {
|
|
40
|
+
emptyMessage: {
|
|
41
|
+
to: "empty",
|
|
42
|
+
note: "Use `empty={{ title, description? }}`.",
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
Callout: {
|
|
46
|
+
type: {
|
|
47
|
+
to: "tone",
|
|
48
|
+
note: 'Callout `type` became `tone: Tone`: `tip` → `success`, `breaking` → `tone="danger" title="Breaking"`.',
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
SaveBar: { saving: { to: "loading", note: "Busy props are `loading`." } },
|
|
52
|
+
CommentComposer: {
|
|
53
|
+
submitting: { to: "loading", note: "Busy props are `loading`." },
|
|
54
|
+
onValueChange: { to: "onChange", note: "Value changes use `onChange`." },
|
|
55
|
+
},
|
|
56
|
+
ConfirmDialog: {
|
|
57
|
+
destructive: {
|
|
58
|
+
to: "tone",
|
|
59
|
+
note: 'ConfirmDialog `destructive` became `tone: "default" | "danger"` (default "danger").',
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
Combobox: {
|
|
63
|
+
emptyLabel: { to: "empty", note: "Use `empty={{ title }}`." },
|
|
64
|
+
},
|
|
65
|
+
PreviewFrame: {
|
|
66
|
+
title: {
|
|
67
|
+
to: "label",
|
|
68
|
+
note: "PreviewFrame `title` became `label` (an accessible name).",
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
ProductOverview: {
|
|
72
|
+
adding: { to: "loading", note: "Busy props are `loading`." },
|
|
73
|
+
},
|
|
74
|
+
ProductQuickView: {
|
|
75
|
+
adding: { to: "loading", note: "Busy props are `loading`." },
|
|
76
|
+
},
|
|
77
|
+
ShoppingCart: {
|
|
78
|
+
emptyTitle: {
|
|
79
|
+
to: "empty",
|
|
80
|
+
note: "Use `empty={{ title, description?, action? }}`.",
|
|
81
|
+
},
|
|
82
|
+
emptyDescription: {
|
|
83
|
+
to: "empty",
|
|
84
|
+
note: "Use `empty={{ title, description?, action? }}`.",
|
|
85
|
+
},
|
|
86
|
+
emptyAction: {
|
|
87
|
+
to: "empty",
|
|
88
|
+
note: "Use `empty={{ title, description?, action? }}`.",
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
OrderHistory: {
|
|
92
|
+
emptyTitle: { to: "empty", note: "Use `empty={{ title, description? }}`." },
|
|
93
|
+
emptyDescription: {
|
|
94
|
+
to: "empty",
|
|
95
|
+
note: "Use `empty={{ title, description? }}`.",
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/** Renames that apply to any component (DESIGN.md API conventions). */
|
|
101
|
+
export const GENERAL_PROPS = {
|
|
102
|
+
saving: "loading",
|
|
103
|
+
submitting: "loading",
|
|
104
|
+
adding: "loading",
|
|
105
|
+
busy: "loading",
|
|
106
|
+
isLoading: "loading",
|
|
107
|
+
emptyTitle: "empty",
|
|
108
|
+
emptyDescription: "empty",
|
|
109
|
+
emptyAction: "empty",
|
|
110
|
+
emptyMessage: "empty",
|
|
111
|
+
emptyLabel: "empty",
|
|
112
|
+
heading: "title",
|
|
113
|
+
onValueChange: "onChange",
|
|
114
|
+
onClick: "onSelect",
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/** Values renamed by the 0.6 conventions. */
|
|
118
|
+
export const RENAMED_VALUES = {
|
|
119
|
+
centered: "center",
|
|
120
|
+
card: "cards",
|
|
121
|
+
surface: "default",
|
|
122
|
+
sunken: "muted",
|
|
123
|
+
left: "start",
|
|
124
|
+
right: "end",
|
|
125
|
+
tip: "success",
|
|
126
|
+
note: "info",
|
|
127
|
+
breaking: "danger",
|
|
128
|
+
};
|