@sit-onyx/modelcontextprotocol 0.0.0 → 0.1.0-dev-20260409084453
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +20 -4
- package/dist/index.js +7095 -47
- package/package.json +12 -8
- package/dist/config.d.ts +0 -4
- package/dist/config.js +0 -6
- package/dist/resources/get-component-api.d.ts +0 -2
- package/dist/resources/get-component-api.js +0 -92
- package/dist/resources/list-components.d.ts +0 -2
- package/dist/resources/list-components.js +0 -41
- package/dist/resources/list-icons.d.ts +0 -1
- package/dist/resources/list-icons.js +0 -118
- package/dist/server/http.d.ts +0 -5
- package/dist/server/http.js +0 -20
- package/dist/server/server.d.ts +0 -6
- package/dist/server/server.js +0 -17
- package/dist/server/stdio.d.ts +0 -5
- package/dist/server/stdio.js +0 -12
- package/dist/server/web.js +0 -10
- package/dist/types.d.ts +0 -7
- package/dist/types.js +0 -1
- package/dist/util/component-meta-json.d.ts +0 -2
- package/dist/util/component-meta-json.js +0 -64
- package/dist/util/icons-meta-json.d.ts +0 -2
- package/dist/util/icons-meta-json.js +0 -63
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sit-onyx/modelcontextprotocol",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.0-dev-20260409084453",
|
|
4
4
|
"description": "MCP (Model Context Protocol) Server that provide onyx specific tools and resources.",
|
|
5
5
|
"homepage": "https://onyx.schwarz",
|
|
6
6
|
"bugs": {
|
|
@@ -9,12 +9,13 @@
|
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
11
11
|
"url": "https://github.com/SchwarzIT/onyx",
|
|
12
|
-
"directory": "
|
|
12
|
+
"directory": "packages/modelcontextprotocol"
|
|
13
13
|
},
|
|
14
14
|
"license": "Apache-2.0",
|
|
15
15
|
"author": "Schwarz IT KG",
|
|
16
16
|
"type": "module",
|
|
17
|
-
"main": "index.js",
|
|
17
|
+
"main": "./dist/index.js",
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
18
19
|
"bin": {
|
|
19
20
|
"onyx-mcp": "./dist/index.js"
|
|
20
21
|
},
|
|
@@ -27,18 +28,21 @@
|
|
|
27
28
|
"devDependencies": {
|
|
28
29
|
"@types/node": "24.12.0",
|
|
29
30
|
"@types/tar-stream": "^3.1.4",
|
|
30
|
-
"pacote": "^21.5.0",
|
|
31
31
|
"query-registry": "^4.3.0",
|
|
32
32
|
"tar-stream": "^3.1.8",
|
|
33
33
|
"typescript": "5.9.3",
|
|
34
|
-
"
|
|
35
|
-
"
|
|
34
|
+
"vite": "8.0.3",
|
|
35
|
+
"vite-plugin-dts": "^4.5.4",
|
|
36
|
+
"vue-component-meta": "^3.2.6",
|
|
37
|
+
"@sit-onyx/shared": "^0.1.0"
|
|
36
38
|
},
|
|
37
39
|
"engines": {
|
|
38
40
|
"node": ">=20"
|
|
39
41
|
},
|
|
40
42
|
"scripts": {
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
+
"dev": "pnpm run \"/build-dev|inspect-mcp/\"",
|
|
44
|
+
"build-dev": "vite build --ssr -w",
|
|
45
|
+
"inspect-mcp": "pnpm dlx @modelcontextprotocol/inspector node ./dist/index.js",
|
|
46
|
+
"build": "vite build --ssr"
|
|
43
47
|
}
|
|
44
48
|
}
|
package/dist/config.d.ts
DELETED
package/dist/config.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import packageJson from "../package.json" with { type: "json" };
|
|
2
|
-
const { version } = packageJson;
|
|
3
|
-
export const USER_AGENT = `onyx-mcp/${version}`;
|
|
4
|
-
export const REGISTRY_URL = process.env.REGISTRY_URL ?? "https://registry.npmjs.org";
|
|
5
|
-
export const SIT_ONYX_MIN_VERSION = "1.0.0";
|
|
6
|
-
export const SIT_ONYX_COMPONENT_META_FILE = "package/dist/component-meta.json";
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
import { retrieveComponentMetaJsonFile } from "../util/component-meta-json.js";
|
|
3
|
-
/**
|
|
4
|
-
* Returns true if both parameters are defined and equal (ignoring surrounding whitespaces and case)
|
|
5
|
-
*/
|
|
6
|
-
const compareDefined = (a, b) => a && b && a.trim().toLowerCase() === b.trim().toLowerCase();
|
|
7
|
-
const tagsToList = (tags) => tags
|
|
8
|
-
.filter(({ name }) => !!name)
|
|
9
|
-
.map(({ text, name }) => `- ${name}: ${text}`)
|
|
10
|
-
.join("\n");
|
|
11
|
-
export const getComponentApi = [
|
|
12
|
-
"get-component-api",
|
|
13
|
-
new ResourceTemplate("components://sit-onyx/{version}/{component}", {
|
|
14
|
-
list: undefined,
|
|
15
|
-
}),
|
|
16
|
-
{
|
|
17
|
-
title: "Get Component API",
|
|
18
|
-
description: "Get the component api for a specific component and version of onyx",
|
|
19
|
-
mimeType: "text/markdown",
|
|
20
|
-
},
|
|
21
|
-
async (uri, { version: _version, component: _component }) => {
|
|
22
|
-
const version = Array.isArray(_version) ? _version[0] : _version;
|
|
23
|
-
const component = Array.isArray(_component) ? _component[0] : _component;
|
|
24
|
-
const componentMetaJson = await retrieveComponentMetaJsonFile(version);
|
|
25
|
-
const componentMeta = componentMetaJson.find(({ displayName, name }) => compareDefined(displayName, name) || compareDefined(name, component));
|
|
26
|
-
if (!componentMeta) {
|
|
27
|
-
throw new Error(`Component ${component} not found for version ${version}`);
|
|
28
|
-
}
|
|
29
|
-
// TODO: improve code readability through use of better templating
|
|
30
|
-
const propsText = componentMeta.props
|
|
31
|
-
.map((prop) => `### ${prop.name}
|
|
32
|
-
|
|
33
|
-
- required: ${prop.required}
|
|
34
|
-
- type: ${prop.type}
|
|
35
|
-
${tagsToList(prop.tags)}
|
|
36
|
-
|
|
37
|
-
${prop.description}`)
|
|
38
|
-
.join("\n\n");
|
|
39
|
-
const slotsText = componentMeta.slots
|
|
40
|
-
.map((slot) => `### ${slot.name}
|
|
41
|
-
|
|
42
|
-
${tagsToList(slot.tags)}
|
|
43
|
-
|
|
44
|
-
${slot.description}`)
|
|
45
|
-
.join("\n\n");
|
|
46
|
-
const eventsText = componentMeta.events
|
|
47
|
-
.map((event) => `### ${event.name}
|
|
48
|
-
|
|
49
|
-
- type: ${event.type}
|
|
50
|
-
${tagsToList(event.tags)}
|
|
51
|
-
|
|
52
|
-
${event.description}`)
|
|
53
|
-
.join("\n\n");
|
|
54
|
-
const exposedText = componentMeta.exposed
|
|
55
|
-
.map((exposed) => `### ${exposed.name}
|
|
56
|
-
|
|
57
|
-
- type: ${exposed.type}
|
|
58
|
-
${tagsToList(exposed.tags)}
|
|
59
|
-
|
|
60
|
-
${exposed.description}`)
|
|
61
|
-
.join("\n\n");
|
|
62
|
-
const text = `# Component API of \`${componentMeta.displayName}\`
|
|
63
|
-
|
|
64
|
-
*Version: \`sit-onyx@${version}\`*
|
|
65
|
-
|
|
66
|
-
## Props
|
|
67
|
-
|
|
68
|
-
${propsText}
|
|
69
|
-
|
|
70
|
-
## Slots
|
|
71
|
-
|
|
72
|
-
${slotsText}
|
|
73
|
-
|
|
74
|
-
## Events
|
|
75
|
-
|
|
76
|
-
${eventsText}
|
|
77
|
-
|
|
78
|
-
## Exposed
|
|
79
|
-
|
|
80
|
-
${exposedText}
|
|
81
|
-
`;
|
|
82
|
-
return {
|
|
83
|
-
contents: [
|
|
84
|
-
{
|
|
85
|
-
uri: uri.href,
|
|
86
|
-
text,
|
|
87
|
-
mimeType: "text/markdown",
|
|
88
|
-
},
|
|
89
|
-
],
|
|
90
|
-
};
|
|
91
|
-
},
|
|
92
|
-
];
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
import { getAbbreviatedPackument } from "query-registry";
|
|
3
|
-
import { REGISTRY_URL, SIT_ONYX_MIN_VERSION } from "../config.js";
|
|
4
|
-
import { retrieveComponentMetaJsonFile } from "../util/component-meta-json.js";
|
|
5
|
-
export const listComponents = [
|
|
6
|
-
"list-components",
|
|
7
|
-
new ResourceTemplate("components://sit-onyx/{version}", {
|
|
8
|
-
list: async () => {
|
|
9
|
-
const { versions } = await getAbbreviatedPackument("sit-onyx", REGISTRY_URL);
|
|
10
|
-
const relevantVersions = Object.keys(versions).filter((version) => version.split("-").at(0) ?? "" >= SIT_ONYX_MIN_VERSION);
|
|
11
|
-
const resources = relevantVersions.map((version) => ({
|
|
12
|
-
uri: `components://sit-onyx/${version}`,
|
|
13
|
-
name: version,
|
|
14
|
-
}));
|
|
15
|
-
return { resources };
|
|
16
|
-
},
|
|
17
|
-
}),
|
|
18
|
-
{
|
|
19
|
-
title: "Component Overview",
|
|
20
|
-
description: "Lists all components for a specific version of onyx",
|
|
21
|
-
mimeType: "text/markdown",
|
|
22
|
-
},
|
|
23
|
-
async (uri, { version: _version }) => {
|
|
24
|
-
const version = Array.isArray(_version) ? _version[0] : _version;
|
|
25
|
-
const componentMetaJson = await retrieveComponentMetaJsonFile(version);
|
|
26
|
-
const componentsText = componentMetaJson
|
|
27
|
-
.toSorted((a, b) => a.displayName.localeCompare(b.displayName))
|
|
28
|
-
.map(({ displayName, description }) => `## ${displayName}\n\n${description ?? ""}\n`)
|
|
29
|
-
.join("\n");
|
|
30
|
-
const text = `# Components for \`sit-onyx@${version}\`\n\n${componentsText}`;
|
|
31
|
-
return {
|
|
32
|
-
contents: [
|
|
33
|
-
{
|
|
34
|
-
uri: uri.href,
|
|
35
|
-
text,
|
|
36
|
-
mimeType: "text/markdown",
|
|
37
|
-
},
|
|
38
|
-
],
|
|
39
|
-
};
|
|
40
|
-
},
|
|
41
|
-
];
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
export {};
|
|
2
|
-
/* import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
-
import type { RegisterableResource } from "../types.js";
|
|
4
|
-
import { retrieveComponentMetaJsonFile } from "../util/component-meta-json.js";
|
|
5
|
-
|
|
6
|
-
const compareDefined = (a: string | undefined | null, b: string | undefined | null) =>
|
|
7
|
-
a && b && a.trim().toLowerCase() === b.trim().toLowerCase();
|
|
8
|
-
|
|
9
|
-
type Tag = {
|
|
10
|
-
name?: string;
|
|
11
|
-
text?: string;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
const tagsToList = (tags: Tag[]) =>
|
|
15
|
-
tags
|
|
16
|
-
.filter(({ name }) => !!name)
|
|
17
|
-
.map(({ text, name }) => `- ${name}: ${text}`)
|
|
18
|
-
.join("\n");
|
|
19
|
-
|
|
20
|
-
export const listIcons: RegisterableResource = [
|
|
21
|
-
"list-icons",
|
|
22
|
-
new ResourceTemplate("icons://sit-onyx/{version}", {
|
|
23
|
-
list: undefined,
|
|
24
|
-
}),
|
|
25
|
-
{
|
|
26
|
-
title: "List @sit-onyx/icons icons",
|
|
27
|
-
description: "List all icons available in a specific version of @sit-onyx/icons",
|
|
28
|
-
mimeType: "text/markdown",
|
|
29
|
-
},
|
|
30
|
-
async (uri, { version: _version }) => {
|
|
31
|
-
const version = Array.isArray(_version) ? _version[0] : _version;
|
|
32
|
-
const componentMetaJson = await retrieveComponentMetaJsonFile(version);
|
|
33
|
-
const componentMeta = componentMetaJson.find(
|
|
34
|
-
({ displayName, name }) =>
|
|
35
|
-
compareDefined(displayName, name) || compareDefined(name, component),
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
if (!componentMeta) {
|
|
39
|
-
throw new Error(`Component ${component} not found for version ${version}`);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const propsText = componentMeta.props
|
|
43
|
-
.map(
|
|
44
|
-
(prop) => `### ${prop.name}
|
|
45
|
-
|
|
46
|
-
- required: ${prop.required}
|
|
47
|
-
- type: ${prop.type}
|
|
48
|
-
${tagsToList(prop.tags)}
|
|
49
|
-
|
|
50
|
-
${prop.description}`,
|
|
51
|
-
)
|
|
52
|
-
.join("\n\n");
|
|
53
|
-
|
|
54
|
-
const slotsText = componentMeta.slots
|
|
55
|
-
.map(
|
|
56
|
-
(slot) => `### ${slot.name}
|
|
57
|
-
|
|
58
|
-
${tagsToList(slot.tags)}
|
|
59
|
-
|
|
60
|
-
${slot.description}`,
|
|
61
|
-
)
|
|
62
|
-
.join("\n\n");
|
|
63
|
-
|
|
64
|
-
const eventsText = componentMeta.events
|
|
65
|
-
.map(
|
|
66
|
-
(event) => `### ${event.name}
|
|
67
|
-
|
|
68
|
-
- type: ${event.type}
|
|
69
|
-
${tagsToList(event.tags)}
|
|
70
|
-
|
|
71
|
-
${event.description}`,
|
|
72
|
-
)
|
|
73
|
-
.join("\n\n");
|
|
74
|
-
|
|
75
|
-
const exposedText = componentMeta.exposed
|
|
76
|
-
.map(
|
|
77
|
-
(exposed) => `### ${exposed.name}
|
|
78
|
-
|
|
79
|
-
- type: ${exposed.type}
|
|
80
|
-
${tagsToList(exposed.tags)}
|
|
81
|
-
|
|
82
|
-
${exposed.description}`,
|
|
83
|
-
)
|
|
84
|
-
.join("\n\n");
|
|
85
|
-
|
|
86
|
-
const text = `# Component API of \`${componentMeta.displayName}\`
|
|
87
|
-
|
|
88
|
-
*Version: \`sit-onyx@${version}\`*
|
|
89
|
-
|
|
90
|
-
## Props
|
|
91
|
-
|
|
92
|
-
${propsText}
|
|
93
|
-
|
|
94
|
-
## Slots
|
|
95
|
-
|
|
96
|
-
${slotsText}
|
|
97
|
-
|
|
98
|
-
## Events
|
|
99
|
-
|
|
100
|
-
${eventsText}
|
|
101
|
-
|
|
102
|
-
## Exposed
|
|
103
|
-
|
|
104
|
-
${exposedText}
|
|
105
|
-
`;
|
|
106
|
-
|
|
107
|
-
return {
|
|
108
|
-
contents: [
|
|
109
|
-
{
|
|
110
|
-
uri: uri.href,
|
|
111
|
-
text,
|
|
112
|
-
mimeType: "text/markdown",
|
|
113
|
-
},
|
|
114
|
-
],
|
|
115
|
-
};
|
|
116
|
-
},
|
|
117
|
-
];
|
|
118
|
-
*/
|
package/dist/server/http.d.ts
DELETED
package/dist/server/http.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
2
|
-
import { randomUUID } from "node:crypto";
|
|
3
|
-
import { createServer } from "node:http";
|
|
4
|
-
import { server } from "./server.js";
|
|
5
|
-
import { error } from "node:console";
|
|
6
|
-
/**
|
|
7
|
-
* MCP server running as a http server.
|
|
8
|
-
* `HOST` and `PORT` environment variable can be used to change the server settings.
|
|
9
|
-
*/
|
|
10
|
-
export const run = async () => {
|
|
11
|
-
const transport = new StreamableHTTPServerTransport({
|
|
12
|
-
sessionIdGenerator: () => randomUUID(),
|
|
13
|
-
});
|
|
14
|
-
await server.connect(transport);
|
|
15
|
-
const httpServer = createServer(transport.handleRequest);
|
|
16
|
-
const PORT = Number.parseInt(process.env["PORT"] ?? "3000");
|
|
17
|
-
const HOST = process.env["HOST"] ?? "0.0.0.0";
|
|
18
|
-
httpServer.listen(PORT, HOST);
|
|
19
|
-
error(`MCP http server listening on ${HOST}:${PORT}.`);
|
|
20
|
-
};
|
package/dist/server/server.d.ts
DELETED
package/dist/server/server.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
import packageJson from "../../package.json" with { type: "json" };
|
|
3
|
-
import { getComponentApi } from "../resources/get-component-api.js";
|
|
4
|
-
import { listComponents } from "../resources/list-components.js";
|
|
5
|
-
const { name, version, description } = packageJson;
|
|
6
|
-
/**
|
|
7
|
-
* Internal McpServer, which provides the MCP resources.
|
|
8
|
-
*/
|
|
9
|
-
const server = new McpServer({
|
|
10
|
-
name,
|
|
11
|
-
version,
|
|
12
|
-
description,
|
|
13
|
-
websiteUrl: "https://onyx.schwarz",
|
|
14
|
-
});
|
|
15
|
-
server.registerResource(...listComponents);
|
|
16
|
-
server.registerResource(...getComponentApi);
|
|
17
|
-
export { server };
|
package/dist/server/stdio.d.ts
DELETED
package/dist/server/stdio.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
2
|
-
import { error } from "node:console";
|
|
3
|
-
import { server } from "./server.js";
|
|
4
|
-
/**
|
|
5
|
-
* MCP server running via stdio.
|
|
6
|
-
* All logging has to use stderr, otherwise the logging to stdio will break the transport.
|
|
7
|
-
*/
|
|
8
|
-
export const run = async () => {
|
|
9
|
-
const transport = new StdioServerTransport();
|
|
10
|
-
await server.connect(transport);
|
|
11
|
-
error("MCP Server running on stdio.");
|
|
12
|
-
};
|
package/dist/server/web.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
2
|
-
import { randomUUID } from "node:crypto";
|
|
3
|
-
import { server } from "./server.js";
|
|
4
|
-
export const run = async () => {
|
|
5
|
-
const transport = new StreamableHTTPServerTransport({
|
|
6
|
-
sessionIdGenerator: () => randomUUID(),
|
|
7
|
-
});
|
|
8
|
-
await server.connect(transport);
|
|
9
|
-
console.error("Weather MCP Server running on stdio");
|
|
10
|
-
};
|
package/dist/types.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
import { type ComponentMeta, type MetaCheckerOptions } from "vue-component-meta";
|
|
3
|
-
export type RegisterableResource = Parameters<InstanceType<typeof McpServer>["registerResource"]>;
|
|
4
|
-
export type MetaSource = {
|
|
5
|
-
exportName: string;
|
|
6
|
-
displayName: string;
|
|
7
|
-
} & ComponentMeta & Exclude<MetaCheckerOptions["schema"], boolean>;
|
package/dist/types.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { Readable } from "node:stream";
|
|
2
|
-
import { buffer } from "node:stream/consumers";
|
|
3
|
-
import { pipeline } from "node:stream/promises";
|
|
4
|
-
import { createGunzip } from "node:zlib";
|
|
5
|
-
import { getPackageManifest } from "query-registry";
|
|
6
|
-
import tarStream from "tar-stream";
|
|
7
|
-
import { REGISTRY_URL, SIT_ONYX_COMPONENT_META_FILE } from "../config.js";
|
|
8
|
-
class SuccessfulAbort {
|
|
9
|
-
data;
|
|
10
|
-
constructor(data) {
|
|
11
|
-
this.data = data;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
// TODO: It's quite fast, but we should add caching nevertheless.
|
|
15
|
-
export async function retrieveComponentMetaJsonFile(version) {
|
|
16
|
-
const { dist } = await getPackageManifest("sit-onyx", version, REGISTRY_URL);
|
|
17
|
-
const { body } = await fetch(dist.tarball);
|
|
18
|
-
if (!body) {
|
|
19
|
-
throw new Error(`No body in response for tarball request to "${dist.tarball}"!`);
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Allows us to stop the stream pipeline at any time.
|
|
23
|
-
* We also use the abort reason to emit the result.
|
|
24
|
-
*/
|
|
25
|
-
const abortController = new AbortController();
|
|
26
|
-
const archiveDownload = Readable.fromWeb(body); // Incorrect typing, see: https://github.com/DefinitelyTyped/DefinitelyTyped/discussions/65542#discussioncomment-6071004
|
|
27
|
-
const decompress = createGunzip();
|
|
28
|
-
const fileSearcher = createTarFileSearcher(abortController);
|
|
29
|
-
try {
|
|
30
|
-
await pipeline(archiveDownload, decompress, fileSearcher, { signal: abortController.signal });
|
|
31
|
-
throw new Error("No 'component-meta.json' found!");
|
|
32
|
-
}
|
|
33
|
-
catch (error) {
|
|
34
|
-
if (error instanceof Error &&
|
|
35
|
-
error.name === "AbortError" &&
|
|
36
|
-
error.cause instanceof SuccessfulAbort) {
|
|
37
|
-
// Return the found data as parsed JSON
|
|
38
|
-
const { data } = error.cause;
|
|
39
|
-
return JSON.parse(data.toString("utf-8"));
|
|
40
|
-
}
|
|
41
|
-
// Re-throw any other error
|
|
42
|
-
throw error;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Returns a writable stream, which searches a file in a tar archive by filename/filepath.
|
|
47
|
-
* If found, will call the AbortController with the file content as reason.
|
|
48
|
-
*/
|
|
49
|
-
function createTarFileSearcher(abortController) {
|
|
50
|
-
const searchFile = tarStream.extract();
|
|
51
|
-
searchFile.on("entry", async (headers, stream, next) => {
|
|
52
|
-
if (headers.name === SIT_ONYX_COMPONENT_META_FILE) {
|
|
53
|
-
const data = await buffer(stream);
|
|
54
|
-
// found the relevant file, stop further processing
|
|
55
|
-
abortController.abort(new SuccessfulAbort(data));
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
// continue searching
|
|
59
|
-
stream.resume();
|
|
60
|
-
next();
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
return searchFile;
|
|
64
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { Readable } from "node:stream";
|
|
2
|
-
import { buffer } from "node:stream/consumers";
|
|
3
|
-
import { pipeline } from "node:stream/promises";
|
|
4
|
-
import { createGunzip } from "node:zlib";
|
|
5
|
-
import { getPackageManifest } from "query-registry";
|
|
6
|
-
import tarStream from "tar-stream";
|
|
7
|
-
import { REGISTRY_URL, SIT_ONYX_COMPONENT_META_FILE } from "../config.js";
|
|
8
|
-
class SuccessfulAbort {
|
|
9
|
-
data;
|
|
10
|
-
constructor(data) {
|
|
11
|
-
this.data = data;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
export async function retrieveComponentMetaJsonFile(version) {
|
|
15
|
-
const { dist } = await getPackageManifest("@sit-onyx/icons", version, REGISTRY_URL);
|
|
16
|
-
const { body } = await fetch(dist.tarball);
|
|
17
|
-
if (!body) {
|
|
18
|
-
throw new Error(`No body in response for tarball request to "${dist.tarball}"!`);
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Allows us to stop the stream pipeline at any time.
|
|
22
|
-
* We also use the abort reason to emit the result.
|
|
23
|
-
*/
|
|
24
|
-
const abortController = new AbortController();
|
|
25
|
-
const archiveDownload = Readable.fromWeb(body); // Incorrect typing, see: https://github.com/DefinitelyTyped/DefinitelyTyped/discussions/65542#discussioncomment-6071004
|
|
26
|
-
const decompress = createGunzip();
|
|
27
|
-
const fileSearcher = createTarFileSearcher(abortController);
|
|
28
|
-
try {
|
|
29
|
-
await pipeline(archiveDownload, decompress, fileSearcher, { signal: abortController.signal });
|
|
30
|
-
throw new Error("No 'component-meta.json' found!");
|
|
31
|
-
}
|
|
32
|
-
catch (error) {
|
|
33
|
-
if (error instanceof Error &&
|
|
34
|
-
error.name === "AbortError" &&
|
|
35
|
-
error.cause instanceof SuccessfulAbort) {
|
|
36
|
-
// Return the found data as parsed JSON
|
|
37
|
-
const { data } = error.cause;
|
|
38
|
-
return JSON.parse(data.toString("utf-8"));
|
|
39
|
-
}
|
|
40
|
-
// Re-throw any other error
|
|
41
|
-
throw error;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Returns a writable stream, which searches a file in a tar archive by filename/filepath.
|
|
46
|
-
* If found, will call the AbortController with the file content as reason.
|
|
47
|
-
*/
|
|
48
|
-
function createTarFileSearcher(abortController) {
|
|
49
|
-
const searchFile = tarStream.extract();
|
|
50
|
-
searchFile.on("entry", async (headers, stream, next) => {
|
|
51
|
-
if (headers.name === SIT_ONYX_COMPONENT_META_FILE) {
|
|
52
|
-
const data = await buffer(stream);
|
|
53
|
-
// found the relevant file, stop further processing
|
|
54
|
-
abortController.abort(new SuccessfulAbort(data));
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
// continue searching
|
|
58
|
-
stream.resume();
|
|
59
|
-
next();
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
return searchFile;
|
|
63
|
-
}
|