feat(planning): grille hebdomadaire complète avec API et filtres
- Connexion API via proxy Angular (résolution CORS, base path /api) - Import CSS ng-zorro global pour les modales et composants - Filtres Camion/Show câblés sur l'affichage de la grille - Camions affichés via TrucksService (linkés au show du même créneau) - Panneau de détails : spectacles + camions du jour sélectionné - Modale de création de spectacle stylisée avec fond et centrage - Positionnement précis des events à la minute dans leur créneau - Auto-scroll vers l'heure courante au chargement - Ligne "maintenant" sur la colonne du jour actuel - Régénération des services OpenAPI (nouveaux noms de types) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+63
-78
@@ -1,27 +1,27 @@
|
||||
import spawn from 'cross-spawn';
|
||||
import process from 'node:process';
|
||||
import { PassThrough } from 'node:stream';
|
||||
import { ReadBuffer, serializeMessage } from '../shared/stdio.js';
|
||||
import spawn from "cross-spawn";
|
||||
import process from "node:process";
|
||||
import { PassThrough } from "node:stream";
|
||||
import { ReadBuffer, serializeMessage } from "../shared/stdio.js";
|
||||
/**
|
||||
* Environment variables to inherit by default, if an environment is not explicitly given.
|
||||
*/
|
||||
export const DEFAULT_INHERITED_ENV_VARS = process.platform === 'win32'
|
||||
export const DEFAULT_INHERITED_ENV_VARS = process.platform === "win32"
|
||||
? [
|
||||
'APPDATA',
|
||||
'HOMEDRIVE',
|
||||
'HOMEPATH',
|
||||
'LOCALAPPDATA',
|
||||
'PATH',
|
||||
'PROCESSOR_ARCHITECTURE',
|
||||
'SYSTEMDRIVE',
|
||||
'SYSTEMROOT',
|
||||
'TEMP',
|
||||
'USERNAME',
|
||||
'USERPROFILE',
|
||||
'PROGRAMFILES'
|
||||
"APPDATA",
|
||||
"HOMEDRIVE",
|
||||
"HOMEPATH",
|
||||
"LOCALAPPDATA",
|
||||
"PATH",
|
||||
"PROCESSOR_ARCHITECTURE",
|
||||
"SYSTEMDRIVE",
|
||||
"SYSTEMROOT",
|
||||
"TEMP",
|
||||
"USERNAME",
|
||||
"USERPROFILE",
|
||||
"PROGRAMFILES",
|
||||
]
|
||||
: /* list inspired by the default env inheritance of sudo */
|
||||
['HOME', 'LOGNAME', 'PATH', 'SHELL', 'TERM', 'USER'];
|
||||
["HOME", "LOGNAME", "PATH", "SHELL", "TERM", "USER"];
|
||||
/**
|
||||
* Returns a default environment object including only environment variables deemed safe to inherit.
|
||||
*/
|
||||
@@ -32,7 +32,7 @@ export function getDefaultEnvironment() {
|
||||
if (value === undefined) {
|
||||
continue;
|
||||
}
|
||||
if (value.startsWith('()')) {
|
||||
if (value.startsWith("()")) {
|
||||
// Skip functions, which are a security risk.
|
||||
continue;
|
||||
}
|
||||
@@ -47,10 +47,11 @@ export function getDefaultEnvironment() {
|
||||
*/
|
||||
export class StdioClientTransport {
|
||||
constructor(server) {
|
||||
this._abortController = new AbortController();
|
||||
this._readBuffer = new ReadBuffer();
|
||||
this._stderrStream = null;
|
||||
this._serverParams = server;
|
||||
if (server.stderr === 'pipe' || server.stderr === 'overlapped') {
|
||||
if (server.stderr === "pipe" || server.stderr === "overlapped") {
|
||||
this._stderrStream = new PassThrough();
|
||||
}
|
||||
}
|
||||
@@ -59,40 +60,51 @@ export class StdioClientTransport {
|
||||
*/
|
||||
async start() {
|
||||
if (this._process) {
|
||||
throw new Error('StdioClientTransport already started! If using Client class, note that connect() calls start() automatically.');
|
||||
throw new Error("StdioClientTransport already started! If using Client class, note that connect() calls start() automatically.");
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
this._process = spawn(this._serverParams.command, this._serverParams.args ?? [], {
|
||||
var _a, _b, _c, _d, _e;
|
||||
this._process = spawn(this._serverParams.command, (_a = this._serverParams.args) !== null && _a !== void 0 ? _a : [], {
|
||||
// merge default env with server env because mcp server needs some env vars
|
||||
env: {
|
||||
...getDefaultEnvironment(),
|
||||
...this._serverParams.env
|
||||
...this._serverParams.env,
|
||||
},
|
||||
stdio: ['pipe', 'pipe', this._serverParams.stderr ?? 'inherit'],
|
||||
stdio: ["pipe", "pipe", (_b = this._serverParams.stderr) !== null && _b !== void 0 ? _b : "inherit"],
|
||||
shell: false,
|
||||
windowsHide: process.platform === 'win32' && isElectron(),
|
||||
cwd: this._serverParams.cwd
|
||||
signal: this._abortController.signal,
|
||||
windowsHide: process.platform === "win32" && isElectron(),
|
||||
cwd: this._serverParams.cwd,
|
||||
});
|
||||
this._process.on('error', error => {
|
||||
this._process.on("error", (error) => {
|
||||
var _a, _b;
|
||||
if (error.name === "AbortError") {
|
||||
// Expected when close() is called.
|
||||
(_a = this.onclose) === null || _a === void 0 ? void 0 : _a.call(this);
|
||||
return;
|
||||
}
|
||||
reject(error);
|
||||
this.onerror?.(error);
|
||||
(_b = this.onerror) === null || _b === void 0 ? void 0 : _b.call(this, error);
|
||||
});
|
||||
this._process.on('spawn', () => {
|
||||
this._process.on("spawn", () => {
|
||||
resolve();
|
||||
});
|
||||
this._process.on('close', _code => {
|
||||
this._process.on("close", (_code) => {
|
||||
var _a;
|
||||
this._process = undefined;
|
||||
this.onclose?.();
|
||||
(_a = this.onclose) === null || _a === void 0 ? void 0 : _a.call(this);
|
||||
});
|
||||
this._process.stdin?.on('error', error => {
|
||||
this.onerror?.(error);
|
||||
(_c = this._process.stdin) === null || _c === void 0 ? void 0 : _c.on("error", (error) => {
|
||||
var _a;
|
||||
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
|
||||
});
|
||||
this._process.stdout?.on('data', chunk => {
|
||||
(_d = this._process.stdout) === null || _d === void 0 ? void 0 : _d.on("data", (chunk) => {
|
||||
this._readBuffer.append(chunk);
|
||||
this.processReadBuffer();
|
||||
});
|
||||
this._process.stdout?.on('error', error => {
|
||||
this.onerror?.(error);
|
||||
(_e = this._process.stdout) === null || _e === void 0 ? void 0 : _e.on("error", (error) => {
|
||||
var _a;
|
||||
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
|
||||
});
|
||||
if (this._stderrStream && this._process.stderr) {
|
||||
this._process.stderr.pipe(this._stderrStream);
|
||||
@@ -107,10 +119,11 @@ export class StdioClientTransport {
|
||||
* error output emitted by the child process.
|
||||
*/
|
||||
get stderr() {
|
||||
var _a, _b;
|
||||
if (this._stderrStream) {
|
||||
return this._stderrStream;
|
||||
}
|
||||
return this._process?.stderr ?? null;
|
||||
return (_b = (_a = this._process) === null || _a === void 0 ? void 0 : _a.stderr) !== null && _b !== void 0 ? _b : null;
|
||||
}
|
||||
/**
|
||||
* The child process pid spawned by this transport.
|
||||
@@ -118,74 +131,46 @@ export class StdioClientTransport {
|
||||
* This is only available after the transport has been started.
|
||||
*/
|
||||
get pid() {
|
||||
return this._process?.pid ?? null;
|
||||
var _a, _b;
|
||||
return (_b = (_a = this._process) === null || _a === void 0 ? void 0 : _a.pid) !== null && _b !== void 0 ? _b : null;
|
||||
}
|
||||
processReadBuffer() {
|
||||
var _a, _b;
|
||||
while (true) {
|
||||
try {
|
||||
const message = this._readBuffer.readMessage();
|
||||
if (message === null) {
|
||||
break;
|
||||
}
|
||||
this.onmessage?.(message);
|
||||
(_a = this.onmessage) === null || _a === void 0 ? void 0 : _a.call(this, message);
|
||||
}
|
||||
catch (error) {
|
||||
this.onerror?.(error);
|
||||
(_b = this.onerror) === null || _b === void 0 ? void 0 : _b.call(this, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
async close() {
|
||||
if (this._process) {
|
||||
const processToClose = this._process;
|
||||
this._process = undefined;
|
||||
const closePromise = new Promise(resolve => {
|
||||
processToClose.once('close', () => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
try {
|
||||
processToClose.stdin?.end();
|
||||
}
|
||||
catch {
|
||||
// ignore
|
||||
}
|
||||
await Promise.race([closePromise, new Promise(resolve => setTimeout(resolve, 2000).unref())]);
|
||||
if (processToClose.exitCode === null) {
|
||||
try {
|
||||
processToClose.kill('SIGTERM');
|
||||
}
|
||||
catch {
|
||||
// ignore
|
||||
}
|
||||
await Promise.race([closePromise, new Promise(resolve => setTimeout(resolve, 2000).unref())]);
|
||||
}
|
||||
if (processToClose.exitCode === null) {
|
||||
try {
|
||||
processToClose.kill('SIGKILL');
|
||||
}
|
||||
catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
this._abortController.abort();
|
||||
this._process = undefined;
|
||||
this._readBuffer.clear();
|
||||
}
|
||||
send(message) {
|
||||
return new Promise(resolve => {
|
||||
if (!this._process?.stdin) {
|
||||
throw new Error('Not connected');
|
||||
return new Promise((resolve) => {
|
||||
var _a;
|
||||
if (!((_a = this._process) === null || _a === void 0 ? void 0 : _a.stdin)) {
|
||||
throw new Error("Not connected");
|
||||
}
|
||||
const json = serializeMessage(message);
|
||||
if (this._process.stdin.write(json)) {
|
||||
resolve();
|
||||
}
|
||||
else {
|
||||
this._process.stdin.once('drain', resolve);
|
||||
this._process.stdin.once("drain", resolve);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
function isElectron() {
|
||||
return 'type' in process;
|
||||
return "type" in process;
|
||||
}
|
||||
//# sourceMappingURL=stdio.js.map
|
||||
Reference in New Issue
Block a user