@mpis/client 0.0.1

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.
Files changed (53) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +51 -0
  3. package/config/rig.json +5 -0
  4. package/lib/api.d.ts +4 -0
  5. package/lib/api.d.ts.map +1 -0
  6. package/lib/api.js +4 -0
  7. package/lib/api.js.map +1 -0
  8. package/lib/bin.d.ts +2 -0
  9. package/lib/bin.d.ts.map +1 -0
  10. package/lib/bin.js +80 -0
  11. package/lib/bin.js.map +1 -0
  12. package/lib/bins/execute-stdout.d.ts +2 -0
  13. package/lib/bins/execute-stdout.d.ts.map +1 -0
  14. package/lib/bins/execute-stdout.js +2 -0
  15. package/lib/bins/execute-stdout.js.map +1 -0
  16. package/lib/channel-client/abs.d.ts +35 -0
  17. package/lib/channel-client/abs.d.ts.map +1 -0
  18. package/lib/channel-client/abs.js +145 -0
  19. package/lib/channel-client/abs.js.map +1 -0
  20. package/lib/channel-client/http.d.ts +13 -0
  21. package/lib/channel-client/http.d.ts.map +1 -0
  22. package/lib/channel-client/http.js +30 -0
  23. package/lib/channel-client/http.js.map +1 -0
  24. package/lib/channel-client/nodejs.d.ts +9 -0
  25. package/lib/channel-client/nodejs.d.ts.map +1 -0
  26. package/lib/channel-client/nodejs.js +16 -0
  27. package/lib/channel-client/nodejs.js.map +1 -0
  28. package/lib/channel-client/tcp.d.ts +15 -0
  29. package/lib/channel-client/tcp.d.ts.map +1 -0
  30. package/lib/channel-client/tcp.js +41 -0
  31. package/lib/channel-client/tcp.js.map +1 -0
  32. package/lib/common/message-channel.d.ts +3 -0
  33. package/lib/common/message-channel.d.ts.map +1 -0
  34. package/lib/common/message-channel.js +21 -0
  35. package/lib/common/message-channel.js.map +1 -0
  36. package/lib/handlers/stdout.d.ts +10 -0
  37. package/lib/handlers/stdout.d.ts.map +1 -0
  38. package/lib/handlers/stdout.js +73 -0
  39. package/lib/handlers/stdout.js.map +1 -0
  40. package/lib/tsconfig.tsbuildinfo +1 -0
  41. package/loader/bin.devel.js +4 -0
  42. package/loader/bin.js +8 -0
  43. package/package.json +39 -0
  44. package/src/api.ts +3 -0
  45. package/src/bin.ts +88 -0
  46. package/src/bins/execute-stdout.ts +0 -0
  47. package/src/channel-client/abs.ts +161 -0
  48. package/src/channel-client/http.ts +33 -0
  49. package/src/channel-client/nodejs.ts +20 -0
  50. package/src/channel-client/tcp.ts +47 -0
  51. package/src/common/message-channel.ts +19 -0
  52. package/src/handlers/stdout.ts +85 -0
  53. package/src/tsconfig.json +9 -0
@@ -0,0 +1,33 @@
1
+ import type { IMessageObject } from '@mpis/shared';
2
+ import { AbstractChannelClient } from './abs.js';
3
+
4
+ /**
5
+ * HTTP连接的客户端实现
6
+ */
7
+ export class HttpClient extends AbstractChannelClient {
8
+ constructor(private readonly remote: string) {
9
+ super();
10
+ }
11
+
12
+ protected override async _disconnect() {}
13
+ protected override async _connect() {}
14
+
15
+ protected override async _send(message: IMessageObject): Promise<void> {
16
+ const response = await fetch(this.remote, {
17
+ method: 'POST',
18
+ headers: {
19
+ 'Content-Type': 'application/json',
20
+ },
21
+ body: JSON.stringify(message),
22
+ });
23
+
24
+ if (!response.ok) {
25
+ throw new Error(`HTTP request failed with status ${response.status}: ${response.statusText}`);
26
+ }
27
+
28
+ const body: any = await response.json();
29
+ if (!body.success) {
30
+ throw new Error(body.message);
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,20 @@
1
+ import type { IMessageObject } from '@mpis/shared';
2
+ import { AbstractChannelClient } from './abs.js';
3
+
4
+ export class NodejsIpcClient extends AbstractChannelClient {
5
+ constructor() {
6
+ super();
7
+
8
+ if (typeof process.send !== 'function') {
9
+ throw new Error('process.send is not a function, this is not a valid child process');
10
+ }
11
+ }
12
+
13
+ protected override async _disconnect(): Promise<void> {}
14
+ protected override async _connect(): Promise<void> {}
15
+
16
+ protected override _send(message: IMessageObject): void {
17
+ // biome-ignore lint/style/noNonNullAssertion: checked in constructor
18
+ process.send!(message);
19
+ }
20
+ }
@@ -0,0 +1,47 @@
1
+ import { createConnection, type Socket } from 'node:net';
2
+ import { AbstractChannelClient } from './abs.js';
3
+ import type { IMessageObject } from '@mpis/shared';
4
+ export { make_message, type IMessageObject } from '@mpis/shared';
5
+
6
+ /**
7
+ * TCP连接的客户端实现
8
+ */
9
+ export class TcpClient extends AbstractChannelClient {
10
+ private declare socket: Socket;
11
+
12
+ constructor(private readonly remote: string) {
13
+ super();
14
+ }
15
+
16
+ protected override async _disconnect() {
17
+ return new Promise<void>((resolve) => {
18
+ this.socket.end(resolve);
19
+ });
20
+ }
21
+ protected override async _connect() {
22
+ let socket: Socket;
23
+
24
+ const remote = this.remote.trim();
25
+ if (remote.includes(':')) {
26
+ const [host, port] = remote.split(':');
27
+ socket = createConnection({ port: Number.parseInt(port), host });
28
+ } else {
29
+ socket = createConnection({ path: remote });
30
+ }
31
+
32
+ await new Promise<void>((resolve, reject) => {
33
+ socket.once('connect', () => resolve());
34
+ socket.once('error', (err) => reject(err));
35
+ });
36
+
37
+ socket.on('error', (err) => {
38
+ this._onFailure.fireNoError(err);
39
+ });
40
+
41
+ this.socket = socket;
42
+ }
43
+
44
+ protected override _send(message: IMessageObject): void {
45
+ this.socket.write(`${JSON.stringify(message)}\n`);
46
+ }
47
+ }
@@ -0,0 +1,19 @@
1
+ import { VoidClient, type AbstractChannelClient } from '../channel-client/abs.js';
2
+ import { HttpClient } from '../channel-client/http.js';
3
+ import { NodejsIpcClient } from '../channel-client/nodejs.js';
4
+
5
+ const server = process.env.BUILD_PROTOCOL_SERVER;
6
+
7
+ export let channelClient: AbstractChannelClient;
8
+ if (!server) {
9
+ channelClient = new VoidClient();
10
+ if (!process.stderr.isTTY) {
11
+ channelClient.logger.error('BUILD_PROTOCOL_SERVER environment variable is not set, sending messages to void.');
12
+ }
13
+ } else if (server === 'ipc:nodejs') {
14
+ channelClient = new NodejsIpcClient();
15
+ } else if (server.startsWith('http://')) {
16
+ channelClient = new HttpClient(server);
17
+ } else {
18
+ throw new TypeError(`Unknown BUILD_PROTOCOL_SERVER: ${server}`);
19
+ }
@@ -0,0 +1,85 @@
1
+ import { PassThrough } from 'node:stream';
2
+ import split2 from 'split2';
3
+ import { channelClient } from '../common/message-channel.js';
4
+
5
+ interface IOptions {
6
+ title?: string;
7
+ start?: RegExp;
8
+ stop: RegExp;
9
+ isFailed(stop_line: string, full_output: string): boolean;
10
+ }
11
+
12
+ export function listenOutputStream(stream: NodeJS.ReadableStream, options: IOptions) {
13
+ if (options.title) channelClient.friendlyTitle = options.title;
14
+
15
+ function emit_failed() {
16
+ channelClient.failed('matching failed output', memory);
17
+ memory = '';
18
+ }
19
+ function emit_success() {
20
+ channelClient.success('matching success output', memory);
21
+ memory = '';
22
+ }
23
+
24
+ function emit_start() {
25
+ channelClient.start();
26
+ memory = '';
27
+ }
28
+
29
+ const reading_stream = split2();
30
+
31
+ let memory = '';
32
+ let started = false;
33
+ let lastFailed = false;
34
+
35
+ reading_stream.on('end', () => {
36
+ if (started || lastFailed) {
37
+ emit_failed();
38
+ process.exitCode = 1;
39
+ }
40
+ });
41
+
42
+ reading_stream.on('data', (line: string) => {
43
+ if (started) {
44
+ memory += line;
45
+ memory += '\n';
46
+ if (!options.stop.test(line)) return;
47
+
48
+ lastFailed = options.isFailed(line, memory);
49
+ if (lastFailed) {
50
+ emit_failed();
51
+ } else {
52
+ emit_success();
53
+ }
54
+ return;
55
+ } else if (options.start) {
56
+ // 如果有开始signal,尝试匹配,失败继续等
57
+ // 成功的话设置started,然后返回以确保丢弃当前行
58
+ started = options.start.test(line);
59
+ if (!started) return;
60
+ emit_start();
61
+ } else {
62
+ started = true;
63
+ emit_start();
64
+ }
65
+
66
+ memory += line;
67
+ memory += '\n';
68
+ });
69
+
70
+ stream.pipe(reading_stream, { end: true });
71
+ }
72
+ export function hookCurrentProcessOutput(options: IOptions) {
73
+ const pipe = new PassThrough({});
74
+ listenOutputStream(pipe, options);
75
+
76
+ function makePipeFunction(originalWrite: (...args: any[]) => boolean) {
77
+ return function (this: NodeJS.WriteStream, ...args: any[]) {
78
+ pipe.write.apply(pipe, args as any);
79
+ return originalWrite.apply(this, args);
80
+ };
81
+ }
82
+
83
+ process.stdout.write = makePipeFunction(process.stdout.write);
84
+ process.stderr.write = makePipeFunction(process.stderr.write);
85
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "@internal/local-rig/profiles/default/tsconfig.json",
3
+ "compilerOptions": {
4
+ "typeRoots": ["../node_modules/@types", "../node_modules"],
5
+ "outDir": "../lib",
6
+ "rootDir": "./",
7
+ "types": ["node"]
8
+ }
9
+ }