every-plugin 3.0.0-rc.3 → 3.0.0-rc.4
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/client.cjs +69 -0
- package/dist/client.cjs.map +1 -0
- package/dist/client.d.cts +15 -0
- package/dist/client.d.cts.map +1 -0
- package/dist/client.d.mts +15 -0
- package/dist/client.d.mts.map +1 -0
- package/dist/client.mjs +68 -0
- package/dist/client.mjs.map +1 -0
- package/dist/dev/host.cjs +149 -0
- package/dist/dev/host.cjs.map +1 -0
- package/dist/dev/host.d.cts +32 -0
- package/dist/dev/host.d.cts.map +1 -0
- package/dist/dev/host.d.mts +32 -0
- package/dist/dev/host.d.mts.map +1 -0
- package/dist/dev/host.mjs +148 -0
- package/dist/dev/host.mjs.map +1 -0
- package/dist/dev/serve.cjs +14 -109
- package/dist/dev/serve.cjs.map +1 -1
- package/dist/dev/serve.d.cts.map +1 -1
- package/dist/dev/serve.d.mts.map +1 -1
- package/dist/dev/serve.mjs +14 -109
- package/dist/dev/serve.mjs.map +1 -1
- package/dist/index.cjs +2 -0
- package/dist/index.d.cts +3 -2
- package/dist/index.d.mts +3 -2
- package/dist/index.mjs +2 -1
- package/dist/plugin.d.cts +1 -1
- package/dist/runtime/mf-config.cjs +1 -1
- package/dist/runtime/mf-config.mjs +1 -1
- package/dist/runtime/services/plugin-loader.service.d.cts +2 -2
- package/dist/types.d.cts +23 -2
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +22 -1
- package/dist/types.d.mts.map +1 -1
- package/package.json +19 -2
- package/src/client.ts +111 -0
- package/src/dev/host.ts +235 -0
- package/src/dev/serve.ts +14 -135
- package/src/index.ts +9 -0
- package/src/types.ts +36 -2
package/src/dev/serve.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { getPluginInfo, loadDevConfig } from "../build/rspack/utils";
|
|
|
10
10
|
import { ensureGeneratedUiRsbuildConfig, pluginLayoutKey } from "../build/ui/generated-config";
|
|
11
11
|
import { PLUGIN_ERROR_STATUS_MAP } from "../errors";
|
|
12
12
|
import { loadRemoteWithRetry } from "../remote-entry";
|
|
13
|
+
import { startDirectModuleHost } from "./host";
|
|
13
14
|
import { killChildEscalating, watchParentDeath } from "./watch-kill";
|
|
14
15
|
|
|
15
16
|
const corsHeaders = {
|
|
@@ -81,12 +82,6 @@ const loadPluginWithRetry = (
|
|
|
81
82
|
}),
|
|
82
83
|
);
|
|
83
84
|
|
|
84
|
-
const sendJson = (res: http.ServerResponse, status: number, body: unknown) => {
|
|
85
|
-
res.statusCode = status;
|
|
86
|
-
res.setHeader("content-type", "application/json; charset=utf-8");
|
|
87
|
-
res.end(JSON.stringify(body));
|
|
88
|
-
};
|
|
89
|
-
|
|
90
85
|
const sendText = (res: http.ServerResponse, status: number, text: string) => {
|
|
91
86
|
res.statusCode = status;
|
|
92
87
|
res.setHeader("content-type", "text/plain; charset=utf-8");
|
|
@@ -125,7 +120,6 @@ export async function startPluginDevServer(
|
|
|
125
120
|
const compositionKey = pluginLayoutKey(cwd) ?? pluginId;
|
|
126
121
|
const port = options.port ?? (Number(process.env.PORT) || devConfig?.port || 3999);
|
|
127
122
|
const rpcPrefix = normalizePrefix(devConfig?.prefix);
|
|
128
|
-
const rpcBase = `/api/rpc${rpcPrefix}`;
|
|
129
123
|
|
|
130
124
|
const distDir = path.join(cwd, "dist");
|
|
131
125
|
const serveStatic = sirv(distDir, { dev: true });
|
|
@@ -208,134 +202,19 @@ export async function startPluginDevServer(
|
|
|
208
202
|
const handlers: { rpc: any; api: any } = { rpc: null, api: null };
|
|
209
203
|
const effectContextHolder: { context: unknown } = { context: null };
|
|
210
204
|
let runtime: { shutdown: () => Promise<void> } | null = null;
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
let cachedRawBody: string | null = null;
|
|
219
|
-
return {
|
|
220
|
-
reqHeaders: webRequest.headers,
|
|
221
|
-
"effect/context": effectContextHolder.context,
|
|
222
|
-
getRawBody: async (): Promise<string> => {
|
|
223
|
-
if (cachedRawBody !== null) return cachedRawBody;
|
|
224
|
-
if (!rawClone) {
|
|
225
|
-
cachedRawBody = "";
|
|
226
|
-
return cachedRawBody;
|
|
227
|
-
}
|
|
228
|
-
cachedRawBody = await rawClone.text();
|
|
229
|
-
return cachedRawBody;
|
|
230
|
-
},
|
|
231
|
-
};
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
const toWebRequest = (req: http.IncomingMessage): Request => {
|
|
235
|
-
const url = `http://localhost:${port}${req.url}`;
|
|
236
|
-
return new Request(url, {
|
|
237
|
-
method: req.method,
|
|
238
|
-
headers: req.headers,
|
|
239
|
-
body: req.method !== "GET" && req.method !== "HEAD" ? req : undefined,
|
|
240
|
-
duplex: req.method !== "GET" && req.method !== "HEAD" ? "half" : undefined,
|
|
241
|
-
} as RequestInit);
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
const handleOrpc = async (
|
|
245
|
-
req: http.IncomingMessage,
|
|
246
|
-
res: http.ServerResponse,
|
|
247
|
-
handler: any,
|
|
248
|
-
prefix: string,
|
|
249
|
-
errorLabel: string,
|
|
250
|
-
) => {
|
|
251
|
-
try {
|
|
252
|
-
const webRequest = toWebRequest(req);
|
|
253
|
-
const result = await handler.handle(webRequest, {
|
|
254
|
-
prefix,
|
|
255
|
-
context: buildDevContext(req, webRequest),
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
if (result.response) {
|
|
259
|
-
res.statusCode = result.response.status;
|
|
260
|
-
result.response.headers.forEach((value: string, key: string) => {
|
|
261
|
-
res.setHeader(key, value);
|
|
262
|
-
});
|
|
263
|
-
const text = await result.response.text();
|
|
264
|
-
if (!res.getHeader("content-length")) {
|
|
265
|
-
res.setHeader("content-length", Buffer.byteLength(text).toString());
|
|
266
|
-
}
|
|
267
|
-
res.end(text);
|
|
268
|
-
} else {
|
|
269
|
-
sendText(res, 404, "Not Found");
|
|
270
|
-
}
|
|
271
|
-
} catch (error) {
|
|
272
|
-
console.error(`${errorLabel} error:`, error);
|
|
273
|
-
sendJson(res, 500, { error: (error as Error).message });
|
|
274
|
-
}
|
|
275
|
-
};
|
|
276
|
-
|
|
277
|
-
const server = http.createServer((req, res) => {
|
|
278
|
-
applyCorsHeaders(res);
|
|
279
|
-
const pathname = pathnameOf(req);
|
|
280
|
-
|
|
281
|
-
if (req.method === "OPTIONS") {
|
|
282
|
-
res.statusCode = 200;
|
|
283
|
-
res.end();
|
|
284
|
-
return;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
if (pathname === "/" && (req.method === "GET" || req.method === "HEAD")) {
|
|
288
|
-
sendJson(res, 200, {
|
|
289
|
-
ok: true,
|
|
290
|
-
plugin: pluginInfo.normalizedName,
|
|
291
|
-
version: pluginInfo.version,
|
|
292
|
-
status: handlers.rpc ? "ready" : "loading",
|
|
293
|
-
endpoints: {
|
|
294
|
-
health: "/",
|
|
295
|
-
docs: "/api",
|
|
296
|
-
rpc: rpcBase,
|
|
297
|
-
},
|
|
298
|
-
});
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
if (pathname === "/health" && (req.method === "GET" || req.method === "HEAD")) {
|
|
303
|
-
sendText(res, 200, "OK");
|
|
304
|
-
return;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
if (pathname.startsWith(`${rpcBase}/`)) {
|
|
308
|
-
if (!handlers.rpc) {
|
|
309
|
-
sendJson(res, 503, { error: "Plugin still loading..." });
|
|
310
|
-
return;
|
|
311
|
-
}
|
|
312
|
-
handleOrpc(req, res, handlers.rpc, rpcBase, "RPC").catch(() => {});
|
|
313
|
-
return;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
if (pathname === "/api" || pathname.startsWith("/api/")) {
|
|
317
|
-
if (!handlers.api) {
|
|
318
|
-
sendJson(res, 503, { error: "Plugin still loading..." });
|
|
319
|
-
return;
|
|
320
|
-
}
|
|
321
|
-
handleOrpc(req, res, handlers.api, "/api", "OpenAPI").catch(() => {});
|
|
322
|
-
return;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
serveStatic(req, res, () => {
|
|
326
|
-
sendText(res, 404, "Not Found");
|
|
327
|
-
});
|
|
328
|
-
});
|
|
329
|
-
|
|
330
|
-
await new Promise<void>((resolve, reject) => {
|
|
331
|
-
server.once("error", reject);
|
|
332
|
-
server.listen(port, () => resolve());
|
|
205
|
+
const host = await startDirectModuleHost({
|
|
206
|
+
name: pluginInfo.normalizedName,
|
|
207
|
+
version: pluginInfo.version,
|
|
208
|
+
handlers,
|
|
209
|
+
effectContext: () => effectContextHolder.context,
|
|
210
|
+
port,
|
|
211
|
+
staticHandler: serveStatic,
|
|
333
212
|
});
|
|
334
213
|
|
|
335
|
-
console.log(`🚀 ${pluginInfo.name} dev server listening on port ${port}`);
|
|
336
|
-
console.log(`├─ 📡 RPC: http://localhost:${port}/api/rpc${rpcPrefix}`);
|
|
337
|
-
console.log(`├─ 📖 Docs: http://localhost:${port}/api`);
|
|
338
|
-
console.log(`└─ 💚 Health: http://localhost:${port}/`);
|
|
214
|
+
console.log(`🚀 ${pluginInfo.name} dev server listening on port ${host.port}`);
|
|
215
|
+
console.log(`├─ 📡 RPC: http://localhost:${host.port}/api/rpc${rpcPrefix}`);
|
|
216
|
+
console.log(`├─ 📖 Docs: http://localhost:${host.port}/api`);
|
|
217
|
+
console.log(`└─ 💚 Health: http://localhost:${host.port}/`);
|
|
339
218
|
|
|
340
219
|
const load = async () => {
|
|
341
220
|
try {
|
|
@@ -360,7 +239,7 @@ export async function startPluginDevServer(
|
|
|
360
239
|
|
|
361
240
|
const registry: Record<string, { remote: string }> = {
|
|
362
241
|
[pluginId]: {
|
|
363
|
-
remote: `http://localhost:${port}/${DEV_ENTRY_FILENAME}`,
|
|
242
|
+
remote: `http://localhost:${host.port}/${DEV_ENTRY_FILENAME}`,
|
|
364
243
|
},
|
|
365
244
|
...siblings,
|
|
366
245
|
};
|
|
@@ -440,8 +319,8 @@ export async function startPluginDevServer(
|
|
|
440
319
|
if (uiStaticServer) {
|
|
441
320
|
await new Promise<void>((resolve) => uiStaticServer.close(() => resolve()));
|
|
442
321
|
}
|
|
322
|
+
await host.close();
|
|
443
323
|
if (runtime) await runtime.shutdown().catch(() => {});
|
|
444
|
-
await new Promise<void>((resolve) => server.close(() => resolve()));
|
|
445
324
|
};
|
|
446
325
|
|
|
447
326
|
process.once("SIGINT", async () => {
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import "@orpc/openapi/extensions/route";
|
|
2
2
|
|
|
3
|
+
export * from "./client";
|
|
3
4
|
export * from "./effect-helpers";
|
|
4
5
|
export * from "./errors";
|
|
5
6
|
export * from "./plugin";
|
|
@@ -13,10 +14,16 @@ export type {
|
|
|
13
14
|
EveryPlugin,
|
|
14
15
|
InitializedPlugin,
|
|
15
16
|
LoadedPlugin,
|
|
17
|
+
ModuleClientEntry,
|
|
18
|
+
ModuleEndpoint,
|
|
19
|
+
ModuleSurface,
|
|
20
|
+
ModuleTransport,
|
|
21
|
+
PluginClientEntry,
|
|
16
22
|
PluginClientType,
|
|
17
23
|
PluginConfigInput,
|
|
18
24
|
PluginContext,
|
|
19
25
|
PluginContract,
|
|
26
|
+
PluginEndpoint,
|
|
20
27
|
PluginInstance,
|
|
21
28
|
PluginMetadata,
|
|
22
29
|
PluginRegistry,
|
|
@@ -24,6 +31,8 @@ export type {
|
|
|
24
31
|
PluginRuntimeConfig,
|
|
25
32
|
PluginSecrets,
|
|
26
33
|
PluginServicesEntry,
|
|
34
|
+
PluginSurface,
|
|
35
|
+
PluginTransport,
|
|
27
36
|
PluginVariables,
|
|
28
37
|
RegisteredPlugins,
|
|
29
38
|
SecretsConfig,
|
package/src/types.ts
CHANGED
|
@@ -24,6 +24,24 @@ import type { PluginWarningInfo } from "./runtime/errors";
|
|
|
24
24
|
// biome-ignore lint/suspicious/noEmptyInterface: required for module augmentation pattern
|
|
25
25
|
export interface RegisteredPlugins {}
|
|
26
26
|
|
|
27
|
+
export type ModuleTransport = "inproc" | "rpc" | "mf";
|
|
28
|
+
|
|
29
|
+
export type ModuleSurface = "api" | "ui" | "jobs";
|
|
30
|
+
|
|
31
|
+
export interface ModuleEndpoint {
|
|
32
|
+
readonly transport: ModuleTransport;
|
|
33
|
+
readonly surface?: ModuleSurface;
|
|
34
|
+
readonly url: string;
|
|
35
|
+
readonly path?: `/${string}`;
|
|
36
|
+
readonly manifest?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type PluginTransport = ModuleTransport;
|
|
40
|
+
|
|
41
|
+
export type PluginSurface = ModuleSurface;
|
|
42
|
+
|
|
43
|
+
export type PluginEndpoint = ModuleEndpoint;
|
|
44
|
+
|
|
27
45
|
/**
|
|
28
46
|
* Base type for any plugin instance.
|
|
29
47
|
*/
|
|
@@ -46,8 +64,14 @@ export type AnyPluginConstructor = {
|
|
|
46
64
|
* Registry entry that supports both direct module imports and remote URLs
|
|
47
65
|
*/
|
|
48
66
|
export type PluginRegistryEntry =
|
|
49
|
-
| {
|
|
50
|
-
|
|
67
|
+
| {
|
|
68
|
+
module: AnyPluginConstructor;
|
|
69
|
+
remote?: string;
|
|
70
|
+
endpoint?: PluginEndpoint;
|
|
71
|
+
version?: string;
|
|
72
|
+
description?: string;
|
|
73
|
+
}
|
|
74
|
+
| { remote: string; endpoint?: PluginEndpoint; version?: string; description?: string };
|
|
51
75
|
|
|
52
76
|
/**
|
|
53
77
|
* Extract plugin constructor type from registry entry
|
|
@@ -116,8 +140,18 @@ export type PluginClientType<T> = RouterClient<PluginRouterType<T>>;
|
|
|
116
140
|
export type PluginServicesEntry<T = any> = {
|
|
117
141
|
client: (context?: PluginContextInput<T>) => PluginClientType<T>;
|
|
118
142
|
router: PluginRouterType<T>;
|
|
143
|
+
endpoint?: PluginEndpoint;
|
|
119
144
|
};
|
|
120
145
|
|
|
146
|
+
export type ModuleClientEntry<C extends AnyContractRouter = AnyContractRouter> = {
|
|
147
|
+
client: (context?: Record<string, unknown>) => RouterClient<ContractedRouter<C, any>>;
|
|
148
|
+
router?: ContractedRouter<C, any>;
|
|
149
|
+
endpoint?: PluginEndpoint;
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
export type PluginClientEntry<C extends AnyContractRouter = AnyContractRouter> =
|
|
153
|
+
ModuleClientEntry<C>;
|
|
154
|
+
|
|
121
155
|
/**
|
|
122
156
|
* Extract plugin type from registered plugins by key
|
|
123
157
|
* @param K - The plugin key
|