@jmfederico/pi-web 1.202608.0 → 1.202608.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.
- package/README.md +4 -4
- package/dist/cli.js +69 -7
- package/dist/cli.js.map +1 -1
- package/dist/client/assets/{CodeViewer-D91Sp61M.js → CodeViewer-mEiBZFA5.js} +2 -2
- package/dist/client/assets/{TerminalPanel-fYrKc3jh.js → TerminalPanel-O9381Eme.js} +6 -6
- package/dist/client/assets/index-uI2AGFUy.js +4091 -0
- package/dist/client/index.html +1 -1
- package/dist/config.js +109 -73
- package/dist/config.js.map +1 -1
- package/dist/docker/piWebDockerCommandPlan.js +4 -3
- package/dist/docker/piWebDockerCommandPlan.js.map +1 -1
- package/dist/nativeServices/servicePlan.js +1 -1
- package/dist/nativeServices/servicePlan.js.map +1 -1
- package/dist/pi-web-plugins/git/browser/git-contract.js +108 -0
- package/dist/pi-web-plugins/git/browser/git-panel.js +609 -0
- package/dist/pi-web-plugins/git/browser/gitFileList.js +43 -0
- package/dist/pi-web-plugins/git/browser/gitFileShared.js +16 -0
- package/dist/pi-web-plugins/git/browser/gitFileTree.js +81 -0
- package/dist/pi-web-plugins/git/browser/gitFileViewPreference.js +35 -0
- package/dist/pi-web-plugins/git/browser/gitRoute.js +42 -0
- package/dist/pi-web-plugins/git/browser/pi-web-plugin.js +10 -0
- package/dist/pi-web-plugins/git/browser/unifiedDiff.js +301 -0
- package/dist/{server/git/gitService.js → pi-web-plugins/git/git-backend.js} +209 -60
- package/dist/pi-web-plugins/git/package.json +16 -0
- package/dist/pi-web-plugins/git/server-plugin.js +176 -0
- package/dist/pi-web-plugins/info/infoInternals.js +1 -2
- package/dist/pi-web-plugins/info/package.json +1 -1
- package/dist/pi-web-plugins/info/pi-web-plugin.js +2 -2
- package/dist/pi-web-plugins/relays/package.json +1 -1
- package/dist/pi-web-plugins/relays/pi-web-plugin.js +3 -3
- package/dist/pi-web-plugins/updates/package.json +1 -1
- package/dist/pi-web-plugins/updates/pi-web-plugin.js +1 -1
- package/dist/pi-web-plugins/workspace-tasks/package.json +1 -1
- package/dist/pi-web-plugins/workspace-tasks/pi-web-plugin.js +3 -3
- package/dist/plugin-api.d.ts +33 -16
- package/dist/pluginRecoveryCli.js +172 -0
- package/dist/pluginRecoveryCli.js.map +1 -0
- package/dist/server/activity/workspaceActivityService.js +27 -19
- package/dist/server/activity/workspaceActivityService.js.map +1 -1
- package/dist/server/app.js +35 -15
- package/dist/server/app.js.map +1 -1
- package/dist/server/configRoutes.js +3 -21
- package/dist/server/configRoutes.js.map +1 -1
- package/dist/server/machines/machineClient.js +23 -4
- package/dist/server/machines/machineClient.js.map +1 -1
- package/dist/server/machines/machinePluginProxyRoutes.js +74 -17
- package/dist/server/machines/machinePluginProxyRoutes.js.map +1 -1
- package/dist/server/machines/machineProxyRoutes.js +165 -8
- package/dist/server/machines/machineProxyRoutes.js.map +1 -1
- package/dist/server/machines/machineService.js +22 -0
- package/dist/server/machines/machineService.js.map +1 -1
- package/dist/server/piWebPluginCatalog.js +584 -0
- package/dist/server/piWebPluginCatalog.js.map +1 -0
- package/dist/server/piWebPluginLifecycle.js +162 -0
- package/dist/server/piWebPluginLifecycle.js.map +1 -0
- package/dist/server/piWebPluginService.js +159 -261
- package/dist/server/piWebPluginService.js.map +1 -1
- package/dist/server/piWebStatus.js +28 -7
- package/dist/server/piWebStatus.js.map +1 -1
- package/dist/server/plugins/pluginBackendProxyRoutes.js +69 -0
- package/dist/server/plugins/pluginBackendProxyRoutes.js.map +1 -0
- package/dist/server/plugins/serverPluginExec.js +184 -0
- package/dist/server/plugins/serverPluginExec.js.map +1 -0
- package/dist/server/plugins/serverPluginRuntime.js +480 -0
- package/dist/server/plugins/serverPluginRuntime.js.map +1 -0
- package/dist/server/realtime/sessionEventHub.js +26 -11
- package/dist/server/realtime/sessionEventHub.js.map +1 -1
- package/dist/server/requestCancellation.js +32 -0
- package/dist/server/requestCancellation.js.map +1 -0
- package/dist/server/sessiond/agentProcessEnvironment.js +29 -30
- package/dist/server/sessiond/agentProcessEnvironment.js.map +1 -1
- package/dist/server/sessiond/pluginBackendRoutes.js +64 -0
- package/dist/server/sessiond/pluginBackendRoutes.js.map +1 -0
- package/dist/server/sessiond/sessionDaemonShutdown.js +24 -0
- package/dist/server/sessiond/sessionDaemonShutdown.js.map +1 -0
- package/dist/server/sessiond/sessionProxyRoutes.js +2 -2
- package/dist/server/sessiond/sessionProxyRoutes.js.map +1 -1
- package/dist/server/sessiond/sessionServiceDependencies.js +2 -1
- package/dist/server/sessiond/sessionServiceDependencies.js.map +1 -1
- package/dist/server/sessiond/sessiondStateOwnership.js +235 -0
- package/dist/server/sessiond/sessiondStateOwnership.js.map +1 -0
- package/dist/server/sessiond/workspaceCatalogRoutes.js +31 -0
- package/dist/server/sessiond/workspaceCatalogRoutes.js.map +1 -0
- package/dist/server/sessiond/workspaceRemovalRoutes.js +41 -0
- package/dist/server/sessiond/workspaceRemovalRoutes.js.map +1 -0
- package/dist/server/sessiond.js +265 -99
- package/dist/server/sessiond.js.map +1 -1
- package/dist/server/sessions/authService.js +15 -54
- package/dist/server/sessions/authService.js.map +1 -1
- package/dist/server/sessions/dockerEnvironmentFacts.js +254 -0
- package/dist/server/sessions/dockerEnvironmentFacts.js.map +1 -0
- package/dist/server/sessions/modelCatalogRefresher.js +4 -3
- package/dist/server/sessions/modelCatalogRefresher.js.map +1 -1
- package/dist/server/sessions/piSessionManagerGateway.js +18 -67
- package/dist/server/sessions/piSessionManagerGateway.js.map +1 -1
- package/dist/server/sessions/piSessionService.js +141 -134
- package/dist/server/sessions/piSessionService.js.map +1 -1
- package/dist/server/sessions/sessionCommandService.js +24 -1
- package/dist/server/sessions/sessionCommandService.js.map +1 -1
- package/dist/server/sessions/sessionEnvironmentFacts.js +48 -0
- package/dist/server/sessions/sessionEnvironmentFacts.js.map +1 -0
- package/dist/server/sessions/sessionFileFormat.js +27 -0
- package/dist/server/sessions/sessionFileFormat.js.map +1 -0
- package/dist/server/sessions/sessionFileHeader.js +1 -14
- package/dist/server/sessions/sessionFileHeader.js.map +1 -1
- package/dist/server/sessions/sessionRoutes.js +14 -0
- package/dist/server/sessions/sessionRoutes.js.map +1 -1
- package/dist/server/sessions/sessionSummaryScanner.js +96 -224
- package/dist/server/sessions/sessionSummaryScanner.js.map +1 -1
- package/dist/server/sessions/spawnSubsessionTool.js +5 -9
- package/dist/server/sessions/spawnSubsessionTool.js.map +1 -1
- package/dist/server/sessions/spawnTargetResolver.js +1 -1
- package/dist/server/status/machineStatusRoutes.js +8 -0
- package/dist/server/status/machineStatusRoutes.js.map +1 -0
- package/dist/server/status/machineStatusService.js +181 -0
- package/dist/server/status/machineStatusService.js.map +1 -0
- package/dist/server/status/workspaceAttribution.js +87 -0
- package/dist/server/status/workspaceAttribution.js.map +1 -0
- package/dist/server/terminalProxyRoutes.js +2 -1
- package/dist/server/terminalProxyRoutes.js.map +1 -1
- package/dist/server/workspaceExplorerRoutes.js +20 -13
- package/dist/server/workspaceExplorerRoutes.js.map +1 -1
- package/dist/server/workspaces/fileContentService.js +18 -9
- package/dist/server/workspaces/fileContentService.js.map +1 -1
- package/dist/server/workspaces/filePreviewResponseHeaders.js +18 -0
- package/dist/server/workspaces/filePreviewResponseHeaders.js.map +1 -0
- package/dist/server/workspaces/filePreviewResponsePolicy.js +55 -0
- package/dist/server/workspaces/filePreviewResponsePolicy.js.map +1 -0
- package/dist/server/workspaces/filePreviewService.js +81 -0
- package/dist/server/workspaces/filePreviewService.js.map +1 -0
- package/dist/server/workspaces/projectWorkspaceCwds.js +0 -5
- package/dist/server/workspaces/projectWorkspaceCwds.js.map +1 -1
- package/dist/server/workspaces/sessionDaemonWorkspaceCatalog.js +402 -0
- package/dist/server/workspaces/sessionDaemonWorkspaceCatalog.js.map +1 -0
- package/dist/server/workspaces/workspaceCatalog.js +47 -0
- package/dist/server/workspaces/workspaceCatalog.js.map +1 -0
- package/dist/server/workspaces/workspaceContext.js +1 -3
- package/dist/server/workspaces/workspaceContext.js.map +1 -1
- package/dist/server/workspaces/workspaceDeletionRoutes.js +35 -125
- package/dist/server/workspaces/workspaceDeletionRoutes.js.map +1 -1
- package/dist/server/workspaces/workspaceProviderRegistry.js +651 -0
- package/dist/server/workspaces/workspaceProviderRegistry.js.map +1 -0
- package/dist/server/workspaces/workspaceRemovalService.js +256 -0
- package/dist/server/workspaces/workspaceRemovalService.js.map +1 -0
- package/dist/server/workspaces/workspaceRouteErrors.js +7 -0
- package/dist/server/workspaces/workspaceRouteErrors.js.map +1 -0
- package/dist/server/workspaces/worktreePreRemoveHook.js +39 -0
- package/dist/server/workspaces/worktreePreRemoveHook.js.map +1 -0
- package/dist/server-plugin-api.d.ts +140 -0
- package/dist/server-plugin-api.js +2 -0
- package/dist/server-plugin-api.js.map +1 -0
- package/dist/serverPluginRecovery.js +138 -0
- package/dist/serverPluginRecovery.js.map +1 -0
- package/dist/sessiond/activeAgentProfile.js +3 -22
- package/dist/sessiond/activeAgentProfile.js.map +1 -1
- package/dist/sessiond/config.js +11 -0
- package/dist/sessiond/config.js.map +1 -1
- package/dist/sessiond/sessionDaemonClient.js +11 -9
- package/dist/sessiond/sessionDaemonClient.js.map +1 -1
- package/dist/shared/activeAgentProfile.js +2 -41
- package/dist/shared/activeAgentProfile.js.map +1 -1
- package/dist/shared/activity.js +0 -3
- package/dist/shared/activity.js.map +1 -1
- package/dist/shared/apiTypes.js +7 -5
- package/dist/shared/apiTypes.js.map +1 -1
- package/dist/shared/capabilities.js +8 -6
- package/dist/shared/capabilities.js.map +1 -1
- package/dist/shared/federatedRoutes.js +28 -5
- package/dist/shared/federatedRoutes.js.map +1 -1
- package/dist/shared/machinePluginIds.js +4 -2
- package/dist/shared/machinePluginIds.js.map +1 -1
- package/dist/shared/machineStatus.js +94 -0
- package/dist/shared/machineStatus.js.map +1 -0
- package/dist/shared/piWebStatusParsing.js +29 -0
- package/dist/shared/piWebStatusParsing.js.map +1 -1
- package/dist/shared/pluginApiTypes.d.ts +148 -0
- package/dist/shared/pluginApiTypes.js +3 -0
- package/dist/shared/pluginApiTypes.js.map +1 -0
- package/dist/shared/pluginBackendProtocol.js +110 -0
- package/dist/shared/pluginBackendProtocol.js.map +1 -0
- package/dist/shared/pluginIds.js +5 -0
- package/dist/shared/pluginIds.js.map +1 -1
- package/dist/shared/pluginRecoveryCommands.js +14 -0
- package/dist/shared/pluginRecoveryCommands.js.map +1 -0
- package/dist/shared/workspaceFiles.js +41 -2
- package/dist/shared/workspaceFiles.js.map +1 -1
- package/dist/shared/workspaceRemovalProtocol.js +24 -0
- package/dist/shared/workspaceRemovalProtocol.js.map +1 -0
- package/docs/config.md +89 -51
- package/docs/plugins.md +383 -136
- package/examples/workspace-provider-plugin/README.md +52 -0
- package/examples/workspace-provider-plugin/package.json +25 -0
- package/examples/workspace-provider-plugin/src/browser/index.ts +69 -0
- package/examples/workspace-provider-plugin/src/server.ts +64 -0
- package/examples/workspace-provider-plugin/tsconfig.json +21 -0
- package/package.json +29 -10
- package/server-plugin-api.d.ts +1 -0
- package/dist/client/assets/UnifiedDiffViewer-BafLWGtF.js +0 -39
- package/dist/client/assets/index-CA8q9_o7.js +0 -4025
- package/dist/plugin-api/unstable.d.ts +0 -22
- package/dist/server/activity/workspaceActivityRoutes.js +0 -4
- package/dist/server/activity/workspaceActivityRoutes.js.map +0 -1
- package/dist/server/git/gitService.js.map +0 -1
- package/dist/server/gitRoutes.js +0 -23
- package/dist/server/gitRoutes.js.map +0 -1
- package/dist/server/sessions/parentSessionLocator.js +0 -75
- package/dist/server/sessions/parentSessionLocator.js.map +0 -1
- package/dist/server/workspaces/gitWorktreeDiscovery.js +0 -43
- package/dist/server/workspaces/gitWorktreeDiscovery.js.map +0 -1
- package/dist/server/workspaces/imagePreviewService.js +0 -40
- package/dist/server/workspaces/imagePreviewService.js.map +0 -1
- package/dist/server/workspaces/workspaceService.js +0 -52
- package/dist/server/workspaces/workspaceService.js.map +0 -1
- package/dist/shared/apiTypes.d.ts +0 -1217
- package/dist/shared/thinkingLevels.d.ts +0 -27
- package/plugin-api/unstable.d.ts +0 -1
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
import { pathToFileURL } from "node:url";
|
|
2
|
+
import { createServerPluginExecFile } from "./serverPluginExec.js";
|
|
3
|
+
const DEFAULT_LIFECYCLE_TIMEOUT_MS = 10_000;
|
|
4
|
+
/**
|
|
5
|
+
* Resolves exactly one desired catalog snapshot and activates its server
|
|
6
|
+
* entries. The resulting runtime is immutable except for explicit shutdown;
|
|
7
|
+
* v1 intentionally has no hot reload or unload path.
|
|
8
|
+
*/
|
|
9
|
+
export async function createServerPluginRuntime(options) {
|
|
10
|
+
if (options.safeStart === "none") {
|
|
11
|
+
return await ServerPluginRuntime.activate({ plugins: [], diagnostics: [] }, options);
|
|
12
|
+
}
|
|
13
|
+
const snapshot = await options.catalog.snapshot(options.safeStart === "bundled-only" ? { scope: "bundled" } : undefined);
|
|
14
|
+
return await ServerPluginRuntime.activate(snapshot, options);
|
|
15
|
+
}
|
|
16
|
+
export class ServerPluginRuntime {
|
|
17
|
+
constructor(safeStart, diagnostics, logger, importer, execFile, lifecycleTimeoutMs) {
|
|
18
|
+
this.safeStart = safeStart;
|
|
19
|
+
this.diagnostics = diagnostics;
|
|
20
|
+
this.logger = logger;
|
|
21
|
+
this.importer = importer;
|
|
22
|
+
this.execFile = execFile;
|
|
23
|
+
this.lifecycleTimeoutMs = lifecycleTimeoutMs;
|
|
24
|
+
this.recordsById = new Map();
|
|
25
|
+
this.activePlugins = [];
|
|
26
|
+
this.stopped = false;
|
|
27
|
+
}
|
|
28
|
+
static async activate(snapshot, options) {
|
|
29
|
+
const runtime = new ServerPluginRuntime(options.safeStart, Object.freeze(snapshot.diagnostics.map((diagnostic) => Object.freeze({ ...diagnostic }))), options.logger, options.importer ?? importServerPluginModule, options.execFile ?? createServerPluginExecFile(), positiveInteger(options.lifecycleTimeoutMs, DEFAULT_LIFECYCLE_TIMEOUT_MS, "lifecycleTimeoutMs"));
|
|
30
|
+
try {
|
|
31
|
+
await runtime.start(snapshot.plugins);
|
|
32
|
+
return runtime;
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
await runtime.stop();
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
safeStartLevel() {
|
|
40
|
+
return this.safeStart;
|
|
41
|
+
}
|
|
42
|
+
catalogDiagnostics() {
|
|
43
|
+
return this.diagnostics;
|
|
44
|
+
}
|
|
45
|
+
healthRecords() {
|
|
46
|
+
return Object.freeze([...this.recordsById.values()]
|
|
47
|
+
.sort((left, right) => left.pluginId.localeCompare(right.pluginId))
|
|
48
|
+
.map((record) => Object.freeze({ ...record })));
|
|
49
|
+
}
|
|
50
|
+
providerContributions() {
|
|
51
|
+
return Object.freeze(this.activePlugins.flatMap((active) => active.contribution === undefined ? [] : [active.contribution]));
|
|
52
|
+
}
|
|
53
|
+
async inspectHealth() {
|
|
54
|
+
const inspections = [];
|
|
55
|
+
for (const active of this.activePlugins) {
|
|
56
|
+
const callback = active.activation.health?.bind(active.activation);
|
|
57
|
+
if (callback === undefined) {
|
|
58
|
+
inspections.push(Object.freeze({ pluginId: active.entry.id, health: Object.freeze({ status: "healthy" }) }));
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
const result = await runBounded(active.entry.id, "health", this.lifecycleTimeoutMs, (signal) => callback(signal));
|
|
63
|
+
inspections.push(Object.freeze({ pluginId: active.entry.id, health: parseHealth(result) }));
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
const message = errorMessage(error);
|
|
67
|
+
inspections.push(Object.freeze({
|
|
68
|
+
pluginId: active.entry.id,
|
|
69
|
+
health: Object.freeze({ status: "unhealthy", message }),
|
|
70
|
+
phase: "health",
|
|
71
|
+
error: message,
|
|
72
|
+
}));
|
|
73
|
+
this.logger.warn({ err: error, pluginId: active.entry.id, phase: "health" }, "server plugin health check failed");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return Object.freeze(inspections);
|
|
77
|
+
}
|
|
78
|
+
/** Stops every successfully published plugin in reverse activation order. */
|
|
79
|
+
async stop() {
|
|
80
|
+
if (this.stopped)
|
|
81
|
+
return;
|
|
82
|
+
this.stopped = true;
|
|
83
|
+
const activePlugins = [...this.activePlugins].reverse();
|
|
84
|
+
this.activePlugins = [];
|
|
85
|
+
for (const active of activePlugins) {
|
|
86
|
+
const stop = active.activation.stop?.bind(active.activation);
|
|
87
|
+
if (stop === undefined)
|
|
88
|
+
continue;
|
|
89
|
+
try {
|
|
90
|
+
await runBounded(active.entry.id, "stop", this.lifecycleTimeoutMs, (signal) => stop(signal));
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
this.recordsById.set(active.entry.id, recordFor(active.entry, {
|
|
94
|
+
state: "failed",
|
|
95
|
+
name: active.plugin.name,
|
|
96
|
+
phase: "stop",
|
|
97
|
+
message: errorMessage(error),
|
|
98
|
+
}));
|
|
99
|
+
this.logger.error({ err: error, pluginId: active.entry.id, phase: "stop" }, "server plugin stop failed");
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
async start(entries) {
|
|
104
|
+
const serverEntries = entries
|
|
105
|
+
.filter((entry) => entry.serverModule !== undefined)
|
|
106
|
+
.sort((left, right) => left.id.localeCompare(right.id));
|
|
107
|
+
for (const entry of serverEntries)
|
|
108
|
+
await this.activateEntry(entry);
|
|
109
|
+
}
|
|
110
|
+
async activateEntry(entry) {
|
|
111
|
+
const disabledMessage = disabledReason(entry, this.safeStart);
|
|
112
|
+
if (disabledMessage !== undefined) {
|
|
113
|
+
this.recordsById.set(entry.id, recordFor(entry, { state: "disabled", message: disabledMessage }));
|
|
114
|
+
this.logger.info({ pluginId: entry.id, reason: disabledMessage }, "server plugin skipped");
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
let phase = "validate";
|
|
118
|
+
let plugin;
|
|
119
|
+
let activation;
|
|
120
|
+
try {
|
|
121
|
+
const settings = cloneJsonObject(entry.settings, `settings for server plugin ${entry.id}`);
|
|
122
|
+
phase = "import";
|
|
123
|
+
const moduleUrl = serverModuleUrl(entry);
|
|
124
|
+
const imported = await runBounded(entry.id, phase, this.lifecycleTimeoutMs, (signal) => this.importer(moduleUrl, signal));
|
|
125
|
+
phase = "validate";
|
|
126
|
+
const loadedPlugin = parsePluginExport(imported);
|
|
127
|
+
plugin = loadedPlugin;
|
|
128
|
+
phase = "activate";
|
|
129
|
+
const scopedLogger = createScopedLogger(entry.id, this.logger);
|
|
130
|
+
const activationValue = await runBounded(entry.id, phase, this.lifecycleTimeoutMs, (signal) => loadedPlugin.activate(Object.freeze({
|
|
131
|
+
apiVersion: 1,
|
|
132
|
+
pluginId: entry.id,
|
|
133
|
+
packageRoot: entry.packageRoot,
|
|
134
|
+
logger: scopedLogger,
|
|
135
|
+
settings,
|
|
136
|
+
execFile: this.execFile,
|
|
137
|
+
signal,
|
|
138
|
+
})));
|
|
139
|
+
phase = "validate";
|
|
140
|
+
const loadedActivation = parseActivation(activationValue);
|
|
141
|
+
activation = loadedActivation;
|
|
142
|
+
phase = "start";
|
|
143
|
+
const start = loadedActivation.start?.bind(loadedActivation);
|
|
144
|
+
if (start !== undefined) {
|
|
145
|
+
await runBounded(entry.id, phase, this.lifecycleTimeoutMs, (signal) => start(signal));
|
|
146
|
+
}
|
|
147
|
+
const contribution = loadedActivation.workspaceProvider === undefined
|
|
148
|
+
? undefined
|
|
149
|
+
: Object.freeze({
|
|
150
|
+
pluginId: entry.id,
|
|
151
|
+
pluginName: loadedPlugin.name,
|
|
152
|
+
packageRoot: entry.packageRoot,
|
|
153
|
+
source: entry.source,
|
|
154
|
+
scope: entry.scope,
|
|
155
|
+
moduleRevision: requireServerModule(entry).revision,
|
|
156
|
+
provider: loadedActivation.workspaceProvider,
|
|
157
|
+
});
|
|
158
|
+
this.activePlugins.push(Object.freeze({
|
|
159
|
+
entry,
|
|
160
|
+
plugin: loadedPlugin,
|
|
161
|
+
activation: loadedActivation,
|
|
162
|
+
...(contribution === undefined ? {} : { contribution }),
|
|
163
|
+
}));
|
|
164
|
+
this.recordsById.set(entry.id, recordFor(entry, { state: "active", name: loadedPlugin.name }));
|
|
165
|
+
this.logger.info({ pluginId: entry.id, pluginName: loadedPlugin.name }, "server plugin activated");
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
const rollbackError = phase === "start" && activation?.stop !== undefined
|
|
169
|
+
? await this.rollbackStart(entry.id, activation)
|
|
170
|
+
: undefined;
|
|
171
|
+
const message = rollbackError === undefined
|
|
172
|
+
? errorMessage(error)
|
|
173
|
+
: `${errorMessage(error)}; startup rollback failed: ${errorMessage(rollbackError)}`;
|
|
174
|
+
const state = error instanceof IncompatibleServerPluginError ? "incompatible" : "failed";
|
|
175
|
+
this.recordsById.set(entry.id, recordFor(entry, {
|
|
176
|
+
state,
|
|
177
|
+
...(plugin === undefined ? {} : { name: plugin.name }),
|
|
178
|
+
phase,
|
|
179
|
+
message,
|
|
180
|
+
}));
|
|
181
|
+
const details = { err: error, pluginId: entry.id, phase, ...(rollbackError === undefined ? {} : { rollbackError }) };
|
|
182
|
+
if (state === "incompatible") {
|
|
183
|
+
this.logger.warn(details, "server plugin is incompatible");
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
this.logger.error(details, "server plugin activation failed");
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
async rollbackStart(pluginId, activation) {
|
|
191
|
+
const stop = activation.stop?.bind(activation);
|
|
192
|
+
if (stop === undefined)
|
|
193
|
+
return undefined;
|
|
194
|
+
try {
|
|
195
|
+
await runBounded(pluginId, "stop", this.lifecycleTimeoutMs, (signal) => stop(signal));
|
|
196
|
+
return undefined;
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
return error;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
function disabledReason(entry, safeStart) {
|
|
204
|
+
if (!entry.enabled)
|
|
205
|
+
return "disabled in PI WEB config";
|
|
206
|
+
if (safeStart === "none")
|
|
207
|
+
return "disabled by no-server-plugin safe start";
|
|
208
|
+
if (safeStart === "bundled-only" && entry.scope !== "bundled")
|
|
209
|
+
return "disabled by bundled-only safe start";
|
|
210
|
+
return undefined;
|
|
211
|
+
}
|
|
212
|
+
function recordFor(entry, status) {
|
|
213
|
+
return Object.freeze({
|
|
214
|
+
pluginId: entry.id,
|
|
215
|
+
source: entry.source,
|
|
216
|
+
scope: entry.scope,
|
|
217
|
+
moduleRevision: requireServerModule(entry).revision,
|
|
218
|
+
...(entry.browserModule === undefined ? {} : { browserRevision: entry.browserModule.revision }),
|
|
219
|
+
settingsRevision: entry.settingsRevision,
|
|
220
|
+
machineSpecific: entry.machineSpecific,
|
|
221
|
+
state: status.state,
|
|
222
|
+
...(status.name === undefined ? {} : { name: status.name }),
|
|
223
|
+
...(status.phase === undefined ? {} : { phase: status.phase }),
|
|
224
|
+
...(status.message === undefined ? {} : { message: status.message }),
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
function requireServerModule(entry) {
|
|
228
|
+
const serverModule = entry.serverModule;
|
|
229
|
+
if (serverModule === undefined)
|
|
230
|
+
throw new Error(`PI WEB plugin has no server module: ${entry.id}`);
|
|
231
|
+
return serverModule;
|
|
232
|
+
}
|
|
233
|
+
function serverModuleUrl(entry) {
|
|
234
|
+
const serverModule = requireServerModule(entry);
|
|
235
|
+
const url = pathToFileURL(serverModule.filePath);
|
|
236
|
+
url.searchParams.set("piWebRevision", serverModule.revision);
|
|
237
|
+
return url.href;
|
|
238
|
+
}
|
|
239
|
+
async function importServerPluginModule(moduleUrl) {
|
|
240
|
+
const imported = await import(moduleUrl);
|
|
241
|
+
return imported;
|
|
242
|
+
}
|
|
243
|
+
function parsePluginExport(imported) {
|
|
244
|
+
if (!isRecord(imported))
|
|
245
|
+
throw new IncompatibleServerPluginError("Server plugin module must export a default plugin object");
|
|
246
|
+
const plugin = imported["default"];
|
|
247
|
+
if (!isRecord(plugin))
|
|
248
|
+
throw new IncompatibleServerPluginError("Server plugin module must export a default plugin object");
|
|
249
|
+
const candidate = {
|
|
250
|
+
apiVersion: plugin["apiVersion"],
|
|
251
|
+
name: plugin["name"],
|
|
252
|
+
activate: plugin["activate"],
|
|
253
|
+
};
|
|
254
|
+
if (candidate.apiVersion !== 1) {
|
|
255
|
+
throw new IncompatibleServerPluginError(`Unsupported server plugin API version: ${formatUnknown(candidate.apiVersion)}`);
|
|
256
|
+
}
|
|
257
|
+
if (typeof candidate.name !== "string" || candidate.name === "") {
|
|
258
|
+
throw new IncompatibleServerPluginError("Server plugin name must be a non-empty string");
|
|
259
|
+
}
|
|
260
|
+
if (typeof candidate.activate !== "function" || !isPiWebServerPlugin(candidate)) {
|
|
261
|
+
throw new IncompatibleServerPluginError("Server plugin activate must be a function");
|
|
262
|
+
}
|
|
263
|
+
const activate = candidate.activate.bind(plugin);
|
|
264
|
+
return Object.freeze({ apiVersion: 1, name: candidate.name, activate: (context) => activate(context) });
|
|
265
|
+
}
|
|
266
|
+
function isPiWebServerPlugin(value) {
|
|
267
|
+
return isRecord(value)
|
|
268
|
+
&& value["apiVersion"] === 1
|
|
269
|
+
&& typeof value["name"] === "string"
|
|
270
|
+
&& value["name"] !== ""
|
|
271
|
+
&& typeof value["activate"] === "function";
|
|
272
|
+
}
|
|
273
|
+
function parseActivation(value) {
|
|
274
|
+
if (!isRecord(value))
|
|
275
|
+
throw new IncompatibleServerPluginError("Server plugin activation must be an object");
|
|
276
|
+
if (value["workspaceProviders"] !== undefined) {
|
|
277
|
+
throw new IncompatibleServerPluginError("Server plugins may contribute only one workspaceProvider");
|
|
278
|
+
}
|
|
279
|
+
const workspaceProviderValue = value["workspaceProvider"];
|
|
280
|
+
const candidate = {
|
|
281
|
+
workspaceProvider: workspaceProviderValue === undefined ? undefined : snapshotWorkspaceProvider(workspaceProviderValue),
|
|
282
|
+
start: value["start"],
|
|
283
|
+
stop: value["stop"],
|
|
284
|
+
health: value["health"],
|
|
285
|
+
};
|
|
286
|
+
for (const callback of ["start", "stop", "health"]) {
|
|
287
|
+
const callbackValue = candidate[callback];
|
|
288
|
+
if (callbackValue !== undefined && typeof callbackValue !== "function") {
|
|
289
|
+
throw new IncompatibleServerPluginError(`Server plugin ${callback} must be a function`);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
if (!isServerPluginActivation(candidate))
|
|
293
|
+
throw new IncompatibleServerPluginError("Server plugin activation is invalid");
|
|
294
|
+
const start = candidate.start?.bind(value);
|
|
295
|
+
const stop = candidate.stop?.bind(value);
|
|
296
|
+
const health = candidate.health?.bind(value);
|
|
297
|
+
return Object.freeze({
|
|
298
|
+
...(candidate.workspaceProvider === undefined ? {} : { workspaceProvider: candidate.workspaceProvider }),
|
|
299
|
+
...(start === undefined ? {} : { start: (signal) => start(signal) }),
|
|
300
|
+
...(stop === undefined ? {} : { stop: (signal) => stop(signal) }),
|
|
301
|
+
...(health === undefined ? {} : { health: (signal) => health(signal) }),
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
function isServerPluginActivation(value) {
|
|
305
|
+
if (!isRecord(value))
|
|
306
|
+
return false;
|
|
307
|
+
const workspaceProvider = value["workspaceProvider"];
|
|
308
|
+
const start = value["start"];
|
|
309
|
+
const stop = value["stop"];
|
|
310
|
+
const health = value["health"];
|
|
311
|
+
return (workspaceProvider === undefined || isWorkspaceProvider(workspaceProvider))
|
|
312
|
+
&& (start === undefined || typeof start === "function")
|
|
313
|
+
&& (stop === undefined || typeof stop === "function")
|
|
314
|
+
&& (health === undefined || typeof health === "function");
|
|
315
|
+
}
|
|
316
|
+
function snapshotWorkspaceProvider(value) {
|
|
317
|
+
if (!isRecord(value))
|
|
318
|
+
throw new IncompatibleServerPluginError("Server plugin workspaceProvider is invalid");
|
|
319
|
+
const candidate = {
|
|
320
|
+
fallback: value["fallback"],
|
|
321
|
+
probe: value["probe"],
|
|
322
|
+
list: value["list"],
|
|
323
|
+
request: value["request"],
|
|
324
|
+
prepareRemove: value["prepareRemove"],
|
|
325
|
+
};
|
|
326
|
+
if (!isWorkspaceProvider(candidate))
|
|
327
|
+
throw new IncompatibleServerPluginError("Server plugin workspaceProvider is invalid");
|
|
328
|
+
const probe = candidate.probe.bind(value);
|
|
329
|
+
const list = candidate.list.bind(value);
|
|
330
|
+
const request = candidate.request?.bind(value);
|
|
331
|
+
const prepareRemove = candidate.prepareRemove?.bind(value);
|
|
332
|
+
return Object.freeze({
|
|
333
|
+
...(candidate.fallback === undefined ? {} : { fallback: candidate.fallback }),
|
|
334
|
+
probe: (project, signal) => probe(project, signal),
|
|
335
|
+
list: (project, signal) => list(project, signal),
|
|
336
|
+
...(request === undefined ? {} : { request: (context) => request(context) }),
|
|
337
|
+
...(prepareRemove === undefined ? {} : { prepareRemove: (context) => prepareRemove(context) }),
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
function isWorkspaceProvider(value) {
|
|
341
|
+
if (!isRecord(value))
|
|
342
|
+
return false;
|
|
343
|
+
const fallback = value["fallback"];
|
|
344
|
+
const probe = value["probe"];
|
|
345
|
+
const list = value["list"];
|
|
346
|
+
const request = value["request"];
|
|
347
|
+
const prepareRemove = value["prepareRemove"];
|
|
348
|
+
return (fallback === undefined || typeof fallback === "boolean")
|
|
349
|
+
&& typeof probe === "function"
|
|
350
|
+
&& typeof list === "function"
|
|
351
|
+
&& (request === undefined || typeof request === "function")
|
|
352
|
+
&& (prepareRemove === undefined || typeof prepareRemove === "function");
|
|
353
|
+
}
|
|
354
|
+
function parseHealth(value) {
|
|
355
|
+
if (!isRecord(value))
|
|
356
|
+
throw new IncompatibleServerPluginError("Server plugin health must be an object");
|
|
357
|
+
const status = value["status"];
|
|
358
|
+
const message = value["message"];
|
|
359
|
+
const details = value["details"];
|
|
360
|
+
if (status !== "healthy" && status !== "degraded" && status !== "unhealthy") {
|
|
361
|
+
throw new IncompatibleServerPluginError("Server plugin health status is invalid");
|
|
362
|
+
}
|
|
363
|
+
if (message !== undefined && typeof message !== "string") {
|
|
364
|
+
throw new IncompatibleServerPluginError("Server plugin health message must be a string");
|
|
365
|
+
}
|
|
366
|
+
const clonedDetails = details === undefined ? undefined : cloneJsonObject(details, "server plugin health details");
|
|
367
|
+
return Object.freeze({
|
|
368
|
+
status,
|
|
369
|
+
...(message === undefined ? {} : { message }),
|
|
370
|
+
...(clonedDetails === undefined ? {} : { details: clonedDetails }),
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
function createScopedLogger(pluginId, logger) {
|
|
374
|
+
return Object.freeze({
|
|
375
|
+
debug(message, details) {
|
|
376
|
+
logger.debug({ pluginId, ...(details ?? {}) }, message);
|
|
377
|
+
},
|
|
378
|
+
info(message, details) {
|
|
379
|
+
logger.info({ pluginId, ...(details ?? {}) }, message);
|
|
380
|
+
},
|
|
381
|
+
warn(message, details) {
|
|
382
|
+
logger.warn({ pluginId, ...(details ?? {}) }, message);
|
|
383
|
+
},
|
|
384
|
+
error(message, details) {
|
|
385
|
+
logger.error({ pluginId, ...(details ?? {}) }, message);
|
|
386
|
+
},
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
async function runBounded(pluginId, phase, timeoutMs, operation) {
|
|
390
|
+
const controller = new AbortController();
|
|
391
|
+
const timeoutError = new ServerPluginTimeoutError(`Server plugin ${pluginId} ${phase} timed out after ${String(timeoutMs)}ms`);
|
|
392
|
+
const timeout = setTimeout(() => { controller.abort(timeoutError); }, timeoutMs);
|
|
393
|
+
timeout.unref();
|
|
394
|
+
const deadline = new Promise((_resolve, reject) => {
|
|
395
|
+
controller.signal.addEventListener("abort", () => { reject(abortError(controller.signal)); }, { once: true });
|
|
396
|
+
});
|
|
397
|
+
const result = Promise.resolve().then(() => operation(controller.signal));
|
|
398
|
+
try {
|
|
399
|
+
return await Promise.race([result, deadline]);
|
|
400
|
+
}
|
|
401
|
+
finally {
|
|
402
|
+
clearTimeout(timeout);
|
|
403
|
+
if (!controller.signal.aborted)
|
|
404
|
+
controller.abort(new DOMException("Server plugin operation completed", "AbortError"));
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
function cloneJsonObject(value, label) {
|
|
408
|
+
if (!isRecord(value))
|
|
409
|
+
throw new IncompatibleServerPluginError(`${label} must be a JSON object`);
|
|
410
|
+
return cloneJsonRecord(value, new Set(), label);
|
|
411
|
+
}
|
|
412
|
+
function cloneJsonRecord(value, ancestors, label) {
|
|
413
|
+
if (ancestors.has(value))
|
|
414
|
+
throw new IncompatibleServerPluginError(`${label} must not contain cycles`);
|
|
415
|
+
ancestors.add(value);
|
|
416
|
+
const output = {};
|
|
417
|
+
for (const [key, child] of Object.entries(value))
|
|
418
|
+
output[key] = cloneJsonValue(child, ancestors, label);
|
|
419
|
+
ancestors.delete(value);
|
|
420
|
+
return Object.freeze(output);
|
|
421
|
+
}
|
|
422
|
+
function cloneJsonValue(value, ancestors, label) {
|
|
423
|
+
if (value === null || typeof value === "string" || typeof value === "boolean")
|
|
424
|
+
return value;
|
|
425
|
+
if (typeof value === "number") {
|
|
426
|
+
if (!Number.isFinite(value))
|
|
427
|
+
throw new IncompatibleServerPluginError(`${label} must contain only finite JSON numbers`);
|
|
428
|
+
return value;
|
|
429
|
+
}
|
|
430
|
+
if (Array.isArray(value)) {
|
|
431
|
+
if (ancestors.has(value))
|
|
432
|
+
throw new IncompatibleServerPluginError(`${label} must not contain cycles`);
|
|
433
|
+
ancestors.add(value);
|
|
434
|
+
const output = value.map((child) => cloneJsonValue(child, ancestors, label));
|
|
435
|
+
ancestors.delete(value);
|
|
436
|
+
return Object.freeze(output);
|
|
437
|
+
}
|
|
438
|
+
if (isRecord(value))
|
|
439
|
+
return cloneJsonRecord(value, ancestors, label);
|
|
440
|
+
throw new IncompatibleServerPluginError(`${label} must contain only JSON values`);
|
|
441
|
+
}
|
|
442
|
+
function abortError(signal) {
|
|
443
|
+
const reason = signal.reason;
|
|
444
|
+
return reason instanceof Error ? reason : new Error("Server plugin operation aborted", { cause: reason });
|
|
445
|
+
}
|
|
446
|
+
class IncompatibleServerPluginError extends Error {
|
|
447
|
+
constructor() {
|
|
448
|
+
super(...arguments);
|
|
449
|
+
this.name = "IncompatibleServerPluginError";
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
class ServerPluginTimeoutError extends Error {
|
|
453
|
+
constructor() {
|
|
454
|
+
super(...arguments);
|
|
455
|
+
this.name = "TimeoutError";
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
function positiveInteger(value, fallback, key) {
|
|
459
|
+
const resolved = value ?? fallback;
|
|
460
|
+
if (!Number.isInteger(resolved) || resolved <= 0)
|
|
461
|
+
throw new Error(`${key} must be a positive integer`);
|
|
462
|
+
return resolved;
|
|
463
|
+
}
|
|
464
|
+
function errorMessage(error) {
|
|
465
|
+
return error instanceof Error ? error.message : String(error);
|
|
466
|
+
}
|
|
467
|
+
function formatUnknown(value) {
|
|
468
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null || value === undefined)
|
|
469
|
+
return String(value);
|
|
470
|
+
try {
|
|
471
|
+
return JSON.stringify(value);
|
|
472
|
+
}
|
|
473
|
+
catch {
|
|
474
|
+
return Object.prototype.toString.call(value);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
function isRecord(value) {
|
|
478
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
479
|
+
}
|
|
480
|
+
//# sourceMappingURL=serverPluginRuntime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serverPluginRuntime.js","sourceRoot":"","sources":["../../../src/server/plugins/serverPluginRuntime.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,9 +16,22 @@ export class SessionEventHub {
|
|
|
16
16
|
sockets.delete(socket);
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Frame sent to each global subscriber the moment it joins, before any live
|
|
21
|
+
* event. It closes the join race for state the browser would otherwise only
|
|
22
|
+
* fetch over HTTP: with two proxy hops in federation, that fetch can resolve
|
|
23
|
+
* before the upstream subscription exists and then be clobbered by a stale
|
|
24
|
+
* value.
|
|
25
|
+
*/
|
|
26
|
+
setGlobalJoinFrame(frame) {
|
|
27
|
+
this.globalJoinFrame = frame;
|
|
28
|
+
}
|
|
19
29
|
addGlobal(socket) {
|
|
20
30
|
this.globalSockets.add(socket);
|
|
21
31
|
socket.on("close", () => this.globalSockets.delete(socket));
|
|
32
|
+
const joinFrame = this.globalJoinFrame?.();
|
|
33
|
+
if (joinFrame !== undefined)
|
|
34
|
+
this.sendToSocket(this.globalSockets, socket, JSON.stringify(joinFrame));
|
|
22
35
|
}
|
|
23
36
|
publish(sessionId, event) {
|
|
24
37
|
const seq = (this.seqBySession.get(sessionId) ?? 0) + 1;
|
|
@@ -49,20 +62,22 @@ export class SessionEventHub {
|
|
|
49
62
|
sendToSockets(sockets, payload) {
|
|
50
63
|
if (sockets === undefined)
|
|
51
64
|
return;
|
|
52
|
-
for (const socket of sockets)
|
|
53
|
-
|
|
54
|
-
|
|
65
|
+
for (const socket of sockets)
|
|
66
|
+
this.sendToSocket(sockets, socket, payload);
|
|
67
|
+
}
|
|
68
|
+
sendToSocket(sockets, socket, payload) {
|
|
69
|
+
if (socket.readyState !== socket.OPEN)
|
|
70
|
+
return;
|
|
71
|
+
try {
|
|
72
|
+
socket.send(payload);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
sockets.delete(socket);
|
|
55
76
|
try {
|
|
56
|
-
socket.
|
|
77
|
+
socket.terminate();
|
|
57
78
|
}
|
|
58
79
|
catch {
|
|
59
|
-
sockets.
|
|
60
|
-
try {
|
|
61
|
-
socket.terminate();
|
|
62
|
-
}
|
|
63
|
-
catch {
|
|
64
|
-
// Removal is authoritative; cleanup failure must not block healthy sockets.
|
|
65
|
-
}
|
|
80
|
+
// Removal is authoritative; cleanup failure must not block healthy sockets.
|
|
66
81
|
}
|
|
67
82
|
}
|
|
68
83
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionEventHub.js","sourceRoot":"","sources":["../../../src/server/realtime/sessionEventHub.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAC;AAU5E,MAAM,OAAO,eAAe;IAA5B;QACmB,qBAAgB,GAAG,IAAI,GAAG,EAA+B,CAAC;QAC1D,kBAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;QAC1C,iBAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"sessionEventHub.js","sourceRoot":"","sources":["../../../src/server/realtime/sessionEventHub.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turns an inbound HTTP disconnect into cooperative cancellation for a bounded
|
|
3
|
+
* downstream operation. A normal completed response never aborts the signal.
|
|
4
|
+
*/
|
|
5
|
+
export function requestCancellation(request, reply) {
|
|
6
|
+
const controller = new AbortController();
|
|
7
|
+
const abort = () => {
|
|
8
|
+
if (!controller.signal.aborted) {
|
|
9
|
+
controller.abort(new DOMException("HTTP request cancelled", "AbortError"));
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
const abortOnPrematureResponseClose = () => {
|
|
13
|
+
if (!reply.raw.writableEnded)
|
|
14
|
+
abort();
|
|
15
|
+
};
|
|
16
|
+
request.raw.once("aborted", abort);
|
|
17
|
+
reply.raw.once("close", abortOnPrematureResponseClose);
|
|
18
|
+
// Node auto-destroys the request stream once its body has been fully read, so
|
|
19
|
+
// `request.raw.destroyed` alone does not mean the client went away. Only an
|
|
20
|
+
// incomplete request stream, or a response closed before it was written, is a
|
|
21
|
+
// real disconnect that happened before this cancellation was installed.
|
|
22
|
+
if ((request.raw.destroyed && !request.raw.complete) || (reply.raw.destroyed && !reply.raw.writableEnded))
|
|
23
|
+
abort();
|
|
24
|
+
return {
|
|
25
|
+
signal: controller.signal,
|
|
26
|
+
dispose() {
|
|
27
|
+
request.raw.removeListener("aborted", abort);
|
|
28
|
+
reply.raw.removeListener("close", abortOnPrematureResponseClose);
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=requestCancellation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requestCancellation.js","sourceRoot":"","sources":["../../src/server/requestCancellation.ts"],"names":[],"mappings":"AAOA;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAuB,EAAE,KAAmB;IAC9E,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,GAAS,EAAE;QACvB,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YAC/B,UAAU,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,wBAAwB,EAAE,YAAY,CAAC,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC,CAAC;IACF,MAAM,6BAA6B,GAAG,GAAS,EAAE;QAC/C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,aAAa;YAAE,KAAK,EAAE,CAAC;IACxC,CAAC,CAAC;IAEF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACnC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,6BAA6B,CAAC,CAAC;IACvD,8EAA8E;IAC9E,4EAA4E;IAC5E,8EAA8E;IAC9E,wEAAwE;IACxE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC;QAAE,KAAK,EAAE,CAAC;IAEnH,OAAO;QACL,MAAM,EAAE,UAAU,CAAC,MAAM;QACzB,OAAO;YACL,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YAC7C,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,OAAO,EAAE,6BAA6B,CAAC,CAAC;QACnE,CAAC;KACF,CAAC;AACJ,CAAC"}
|