@powerlines/engine 0.9.1 → 0.9.2
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/api/build.d.cts +1 -1
- package/dist/api/build.d.mts +1 -1
- package/dist/api/clean.d.cts +1 -1
- package/dist/api/clean.d.mts +1 -1
- package/dist/api/create.d.cts +1 -1
- package/dist/api/create.d.mts +1 -1
- package/dist/api/deploy.d.cts +1 -1
- package/dist/api/deploy.d.mts +1 -1
- package/dist/api/docs.d.cts +1 -1
- package/dist/api/docs.d.mts +1 -1
- package/dist/api/lint.d.cts +1 -1
- package/dist/api/lint.d.mts +1 -1
- package/dist/api/prepare.d.cts +1 -1
- package/dist/api/prepare.d.mts +1 -1
- package/dist/api/test.d.cts +1 -1
- package/dist/api/test.d.mts +1 -1
- package/dist/api/types.d.cts +1 -1
- package/dist/api/types.d.mts +1 -1
- package/dist/{api-Bw-RpQgX.d.cts → api-Bi_h4LMX.d.cts} +5 -4
- package/dist/api-Bi_h4LMX.d.cts.map +1 -0
- package/dist/{api-D9bpSxPB.d.mts → api-oIs2Wp3t.d.mts} +5 -4
- package/dist/api-oIs2Wp3t.d.mts.map +1 -0
- package/dist/context/index.d.cts +1 -1
- package/dist/context/index.d.mts +1 -1
- package/dist/{context-DrNGEC0b.d.mts → context-DrNQXXRC.d.mts} +2 -2
- package/dist/{context-C_P-KYJX.d.cts.map → context-DrNQXXRC.d.mts.map} +1 -1
- package/dist/{context-C_P-KYJX.d.cts → context-LQBeYY23.d.cts} +2 -2
- package/dist/{context-DrNGEC0b.d.mts.map → context-LQBeYY23.d.cts.map} +1 -1
- package/dist/{engine-context-BXjBJuHe.d.mts → engine-context-BBSMtv0b.d.mts} +2 -2
- package/dist/{engine-context-BXjBJuHe.d.mts.map → engine-context-BBSMtv0b.d.mts.map} +1 -1
- package/dist/{engine-context-CPYw-aGB.d.cts → engine-context-C6bNxumd.d.cts} +2 -2
- package/dist/{engine-context-CPYw-aGB.d.cts.map → engine-context-C6bNxumd.d.cts.map} +1 -1
- package/dist/engine.d.cts +3 -3
- package/dist/engine.d.mts +3 -3
- package/dist/helpers/create-execution-host.cjs +27 -2
- package/dist/helpers/create-execution-host.d.cts +2 -2
- package/dist/helpers/create-execution-host.d.cts.map +1 -1
- package/dist/helpers/create-execution-host.d.mts +2 -2
- package/dist/helpers/create-execution-host.d.mts.map +1 -1
- package/dist/helpers/create-execution-host.mjs +27 -2
- package/dist/helpers/create-execution-host.mjs.map +1 -1
- package/dist/helpers/execution-host-worker.d.cts +2 -2
- package/dist/helpers/execution-host-worker.d.mts +2 -2
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/worker/execution-host.cjs +160 -2
- package/dist/worker/execution-host.d.cts +52 -2
- package/dist/worker/execution-host.d.cts.map +1 -1
- package/dist/worker/execution-host.d.mts +52 -2
- package/dist/worker/execution-host.d.mts.map +1 -1
- package/dist/worker/execution-host.mjs +161 -3
- package/dist/worker/execution-host.mjs.map +1 -1
- package/package.json +6 -6
- package/dist/api-Bw-RpQgX.d.cts.map +0 -1
- package/dist/api-D9bpSxPB.d.mts.map +0 -1
|
@@ -55,6 +55,19 @@ let _stryke_helpers_omit = require("@stryke/helpers/omit");
|
|
|
55
55
|
let _stryke_type_checks_is_set_object = require("@stryke/type-checks/is-set-object");
|
|
56
56
|
let _powerlines_core_context_execution_context = require("@powerlines/core/context/execution-context");
|
|
57
57
|
let _powerlines_core_lib_context_helpers = require("@powerlines/core/lib/context-helpers");
|
|
58
|
+
let _stryke_string_format_title_case = require("@stryke/string-format/title-case");
|
|
59
|
+
let _stryke_unique_id_uuid = require("@stryke/unique-id/uuid");
|
|
60
|
+
let _powerlines_core_lib_events = require("@powerlines/core/lib/events");
|
|
61
|
+
let _stryke_type_checks_is_number = require("@stryke/type-checks/is-number");
|
|
62
|
+
let _stryke_type_checks_is_set = require("@stryke/type-checks/is-set");
|
|
63
|
+
let _stryke_url = require("@stryke/url");
|
|
64
|
+
let devframe_client = require("devframe/client");
|
|
65
|
+
let devframe_rpc = require("devframe/rpc");
|
|
66
|
+
let devframe_rpc_client = require("devframe/rpc/client");
|
|
67
|
+
let devframe_rpc_transports_ws_client = require("devframe/rpc/transports/ws-client");
|
|
68
|
+
let devframe_utils_promise = require("devframe/utils/promise");
|
|
69
|
+
let human_id = require("human-id");
|
|
70
|
+
let node_events = require("node:events");
|
|
58
71
|
|
|
59
72
|
//#region src/api/prepare.ts
|
|
60
73
|
/**
|
|
@@ -367,6 +380,131 @@ async function types$1(context) {
|
|
|
367
380
|
timer();
|
|
368
381
|
}
|
|
369
382
|
|
|
383
|
+
//#endregion
|
|
384
|
+
//#region src/helpers/rpc.ts
|
|
385
|
+
function createWsRpcClientMode(baseURL, connectionMeta, events, clientRpc, authToken = (0, human_id.humanId)({
|
|
386
|
+
separator: "-",
|
|
387
|
+
capitalize: false
|
|
388
|
+
}), rpcOptions = {}, wsOptions = {}) {
|
|
389
|
+
let isTrusted = false;
|
|
390
|
+
const trustedPromise = (0, devframe_utils_promise.promiseWithResolver)();
|
|
391
|
+
const url = (0, _stryke_type_checks_is_number.isNumber)(connectionMeta.websocket) || (0, _stryke_type_checks_is_set.isSet)(connectionMeta.websocket) && `${+connectionMeta.websocket}` === `${connectionMeta.websocket}` ? `${baseURL.protocol.replace("http", "ws")}//${baseURL.hostname}:${connectionMeta.websocket}` : connectionMeta.websocket;
|
|
392
|
+
const definitions = /* @__PURE__ */ new Map();
|
|
393
|
+
for (const name of connectionMeta.jsonSerializableMethods ?? []) definitions.set(name, { jsonSerializable: true });
|
|
394
|
+
const serverRpc = (0, devframe_rpc_client.createRpcClient)(clientRpc.functions, {
|
|
395
|
+
channel: (0, devframe_rpc_transports_ws_client.createWsRpcChannel)({
|
|
396
|
+
url,
|
|
397
|
+
authToken,
|
|
398
|
+
definitions,
|
|
399
|
+
...wsOptions
|
|
400
|
+
}),
|
|
401
|
+
rpcOptions
|
|
402
|
+
});
|
|
403
|
+
clientRpc.register({
|
|
404
|
+
name: "devframe:auth:revoked",
|
|
405
|
+
type: "event",
|
|
406
|
+
handler: () => {
|
|
407
|
+
isTrusted = false;
|
|
408
|
+
events.emit("rpc:is-trusted:updated", false);
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
let currentAuthToken = authToken;
|
|
412
|
+
async function requestTrustWithToken(token) {
|
|
413
|
+
currentAuthToken = token;
|
|
414
|
+
return true;
|
|
415
|
+
}
|
|
416
|
+
async function requestTrust() {
|
|
417
|
+
if (isTrusted) return true;
|
|
418
|
+
return requestTrustWithToken(currentAuthToken);
|
|
419
|
+
}
|
|
420
|
+
async function ensureTrusted(timeout = 6e4) {
|
|
421
|
+
if (isTrusted) trustedPromise.resolve(true);
|
|
422
|
+
if (timeout <= 0) return trustedPromise.promise;
|
|
423
|
+
let clear = () => {};
|
|
424
|
+
await Promise.race([trustedPromise.promise.then(clear), new Promise((resolve, reject) => {
|
|
425
|
+
const id = setTimeout(() => {
|
|
426
|
+
reject(/* @__PURE__ */ new Error("Timeout waiting for rpc to be trusted"));
|
|
427
|
+
}, timeout);
|
|
428
|
+
clear = () => clearTimeout(id);
|
|
429
|
+
})]);
|
|
430
|
+
return isTrusted;
|
|
431
|
+
}
|
|
432
|
+
return {
|
|
433
|
+
get isTrusted() {
|
|
434
|
+
return isTrusted;
|
|
435
|
+
},
|
|
436
|
+
requestTrust,
|
|
437
|
+
requestTrustWithToken,
|
|
438
|
+
ensureTrusted,
|
|
439
|
+
call: (...args) => {
|
|
440
|
+
return serverRpc.$call(...args);
|
|
441
|
+
},
|
|
442
|
+
callEvent: (...args) => {
|
|
443
|
+
return serverRpc.$callEvent(...args);
|
|
444
|
+
},
|
|
445
|
+
callOptional: (...args) => {
|
|
446
|
+
return serverRpc.$callOptional(...args);
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
const CONNECTION_AUTH_TOKEN_KEY = "__DEVTOOLS_CONNECTION_AUTH_TOKEN__";
|
|
451
|
+
function createRpcClient(options) {
|
|
452
|
+
const baseURL = new _stryke_url.StormURL(options.baseURL);
|
|
453
|
+
const cacheManager = new devframe_rpc.RpcCacheManager({
|
|
454
|
+
functions: [],
|
|
455
|
+
...typeof options.cacheOptions === "object" ? options.cacheOptions : {}
|
|
456
|
+
});
|
|
457
|
+
const context = { rpc: void 0 };
|
|
458
|
+
const clientRpc = new devframe_rpc.RpcFunctionsCollectorBase(context);
|
|
459
|
+
node_events.EventEmitter.setMaxListeners(100);
|
|
460
|
+
const events = (0, _powerlines_core_lib_events.createEventEmitter)();
|
|
461
|
+
const mode = createWsRpcClientMode(baseURL, options.connection, events, clientRpc, void 0, {
|
|
462
|
+
...options.rpcOptions,
|
|
463
|
+
async onRequest(req, next, resolve) {
|
|
464
|
+
await options.rpcOptions?.onRequest?.call(this, req, next, resolve);
|
|
465
|
+
if (options.cacheOptions && cacheManager?.validate(req.m)) {
|
|
466
|
+
const cached = cacheManager.cached(req.m, req.a);
|
|
467
|
+
if (cached) return resolve(cached);
|
|
468
|
+
else {
|
|
469
|
+
const res = await next(req);
|
|
470
|
+
cacheManager?.apply(req, res);
|
|
471
|
+
}
|
|
472
|
+
} else await next(req);
|
|
473
|
+
}
|
|
474
|
+
}, options.wsOptions);
|
|
475
|
+
const rpc = {
|
|
476
|
+
events,
|
|
477
|
+
get isTrusted() {
|
|
478
|
+
return mode.isTrusted;
|
|
479
|
+
},
|
|
480
|
+
connectionMeta: options.connection,
|
|
481
|
+
ensureTrusted: mode.ensureTrusted,
|
|
482
|
+
requestTrust: mode.requestTrust,
|
|
483
|
+
requestTrustWithToken: async (token) => {
|
|
484
|
+
localStorage.setItem(CONNECTION_AUTH_TOKEN_KEY, token);
|
|
485
|
+
globalThis[CONNECTION_AUTH_TOKEN_KEY] = token;
|
|
486
|
+
return mode.requestTrustWithToken(token);
|
|
487
|
+
},
|
|
488
|
+
call: mode.call,
|
|
489
|
+
callEvent: mode.callEvent,
|
|
490
|
+
callOptional: mode.callOptional,
|
|
491
|
+
client: clientRpc,
|
|
492
|
+
sharedState: void 0,
|
|
493
|
+
streaming: void 0,
|
|
494
|
+
cacheManager
|
|
495
|
+
};
|
|
496
|
+
rpc.streaming = (0, devframe_client.createRpcStreamingClientHost)(rpc);
|
|
497
|
+
context.rpc = rpc;
|
|
498
|
+
mode.requestTrust();
|
|
499
|
+
try {
|
|
500
|
+
const bc = new BroadcastChannel("vite-devtools-auth");
|
|
501
|
+
bc.onmessage = (event) => {
|
|
502
|
+
if (event.data?.type === "auth-update" && event.data.authToken) rpc.requestTrustWithToken(event.data.authToken);
|
|
503
|
+
};
|
|
504
|
+
} catch {}
|
|
505
|
+
return rpc;
|
|
506
|
+
}
|
|
507
|
+
|
|
370
508
|
//#endregion
|
|
371
509
|
//#region src/helpers/create-execution-host.ts
|
|
372
510
|
/**
|
|
@@ -377,8 +515,28 @@ async function types$1(context) {
|
|
|
377
515
|
*/
|
|
378
516
|
function createExecutionHost(methods) {
|
|
379
517
|
return Object.fromEntries(Object.entries(methods).map(([method, fn]) => [method, async (params) => {
|
|
380
|
-
const
|
|
381
|
-
|
|
518
|
+
const { options, inlineConfig } = params;
|
|
519
|
+
let rpc;
|
|
520
|
+
if (options.baseURL && options.connection) rpc = createRpcClient(options);
|
|
521
|
+
else throw new Error(`Execution RPC client could not be created - Missing ${!options.baseURL ? `baseURL${options.connection ? ` and connection information` : ""}` : "connection"} or connection information.`);
|
|
522
|
+
const logFn = (meta, message) => {
|
|
523
|
+
(0, _powerlines_core_plugin_utils.consoleLogger)(meta, message);
|
|
524
|
+
if (rpc) rpc.callEvent("powerlines:log", {
|
|
525
|
+
meta: {
|
|
526
|
+
category: "general",
|
|
527
|
+
...options,
|
|
528
|
+
...(0, _stryke_type_checks_is_set_object.isSetObject)(meta) ? meta : { type: meta },
|
|
529
|
+
logId: (0, _stryke_unique_id_uuid.uuid)(),
|
|
530
|
+
timestamp: Date.now()
|
|
531
|
+
},
|
|
532
|
+
message
|
|
533
|
+
});
|
|
534
|
+
};
|
|
535
|
+
const context = await _powerlines_core_context_execution_context.PowerlinesExecutionContext.from({
|
|
536
|
+
...options,
|
|
537
|
+
logFn
|
|
538
|
+
}, inlineConfig ?? {}, { rpc });
|
|
539
|
+
context.logger.info(`Starting ${(0, _stryke_string_format_title_case.titleCase)(options.framework?.name) || "Powerlines"} - ${(0, _stryke_string_format_title_case.titleCase)(method)} execution (${options.executionId})`);
|
|
382
540
|
await (0, _powerlines_core_lib_context_helpers.resolvePluginConfig)(context);
|
|
383
541
|
await fn(context);
|
|
384
542
|
}]));
|
|
@@ -1,10 +1,60 @@
|
|
|
1
|
-
import { ExecutionOptions, InlineConfig } from "@powerlines/core";
|
|
1
|
+
import { ExecutionOptions, InlineConfig, LogMeta } from "@powerlines/core";
|
|
2
|
+
import { BirpcOptions } from "birpc";
|
|
3
|
+
import { RpcCacheOptions } from "devframe/rpc";
|
|
4
|
+
import { WsRpcChannelOptions } from "devframe/rpc/transports/ws-client";
|
|
5
|
+
import { ConnectionMeta, DevToolsRpcClientFunctions, DevToolsRpcServerFunctions } from "devframe/types";
|
|
6
|
+
//#region src/types/rpc.d.ts
|
|
7
|
+
/**
|
|
8
|
+
* Payload for write log Rpc messages.
|
|
9
|
+
*/
|
|
10
|
+
interface LogPayload {
|
|
11
|
+
/**
|
|
12
|
+
* Metadata associated with the log message, excluding fields that are automatically added by the engine such as executionId, configIndex, environment, and timestamp. This can include custom fields relevant to the log entry, such as category, name, command, hook, plugin, and source.
|
|
13
|
+
*/
|
|
14
|
+
meta: LogMeta;
|
|
15
|
+
/**
|
|
16
|
+
* The log message content, which can be a string or an array of strings representing the log entry. This field is required and should contain the actual message to be logged.
|
|
17
|
+
*/
|
|
18
|
+
message: string;
|
|
19
|
+
}
|
|
20
|
+
interface RpcServerFunctions extends DevToolsRpcServerFunctions {
|
|
21
|
+
"powerlines:log": (payload: LogPayload) => void;
|
|
22
|
+
}
|
|
23
|
+
interface RpcClientFunctions extends DevToolsRpcClientFunctions {}
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/types/config.d.ts
|
|
26
|
+
interface EngineExecutionOptions extends ExecutionOptions {
|
|
27
|
+
/**
|
|
28
|
+
* The base URL for the dev server, which can be used by plugins to construct URLs for assets or API endpoints during development. This value is only relevant in "dev" mode and will be `undefined` in "build" mode.
|
|
29
|
+
*/
|
|
30
|
+
baseURL: string;
|
|
31
|
+
/**
|
|
32
|
+
* Metadata for the connection used by the dev server, including the backend type and websocket configuration.
|
|
33
|
+
*/
|
|
34
|
+
connection: ConnectionMeta;
|
|
35
|
+
/**
|
|
36
|
+
* Options for configuring the WebSocket RPC channel used for communication between the dev server and the client, which can be used by plugins to customize the behavior of the WebSocket connection, such as setting custom timeouts, retry strategies, or other options.
|
|
37
|
+
*/
|
|
38
|
+
wsOptions?: Partial<WsRpcChannelOptions>;
|
|
39
|
+
/**
|
|
40
|
+
* Options for configuring the RPC client used for communication between the dev server and the client, which can be used by plugins to customize the behavior of the RPC client, such as setting custom timeouts, retry strategies, or other options.
|
|
41
|
+
*/
|
|
42
|
+
rpcOptions?: Partial<BirpcOptions<RpcServerFunctions, RpcClientFunctions, boolean>>;
|
|
43
|
+
/**
|
|
44
|
+
* Options for configuring the RPC cache used for caching RPC responses between the dev server and the client, which can be used by plugins to customize the behavior of the RPC cache, such as setting custom cache keys, expiration times, or other options.
|
|
45
|
+
*
|
|
46
|
+
* @remarks
|
|
47
|
+
* This option can be set to `true` to enable caching with default options, or it can be set to a configuration object that allows for fine-grained control over the caching behavior.
|
|
48
|
+
*/
|
|
49
|
+
cacheOptions?: boolean | Partial<RpcCacheOptions>;
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
2
52
|
//#region src/types/api.d.ts
|
|
3
53
|
interface ExecutionHostParams {
|
|
4
54
|
/**
|
|
5
55
|
* The execution options for the current execution instance
|
|
6
56
|
*/
|
|
7
|
-
options:
|
|
57
|
+
options: EngineExecutionOptions;
|
|
8
58
|
/**
|
|
9
59
|
* The inline configuration for the current execution instance, which is the result of merging the user configuration with any configuration provided by plugins during the "config" hook.
|
|
10
60
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execution-host.d.cts","names":[],"sources":["../../src/types/api.ts","../../src/execution-host.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"execution-host.d.cts","names":[],"sources":["../../src/types/rpc.ts","../../src/types/config.ts","../../src/types/api.ts","../../src/execution-host.ts"],"mappings":";;;;;;;;;UAqGiB,UAAA;ECtBK;;;ED0BpB,IAAA,EAAM,OAAA;ECpBS;;;EDyBf,OAAA;AAAA;AAAA,UAGe,kBAAA,SAA2B,0BAAA;EAE1C,gBAAA,GAAmB,OAAA,EAAS,UAAA;AAAA;AAAA,UAGb,kBAAA,SAA2B,0BAAA;;;UCrD3B,sBAAA,SAA+B,gBAAA;;;;EAI9C,OAAA;;;AAJF;EASE,UAAA,EAAY,cAAA;;;;EAKZ,SAAA,GAAY,OAAA,CAAQ,mBAAA;EAML;;;EADf,UAAA,GAAa,OAAA,CACX,YAAA,CAAa,kBAAA,EAAoB,kBAAA;EASF;;;;;;EAAjC,YAAA,aAAyB,OAAA,CAAQ,eAAA;AAAA;;;UC8ClB,mBAAA;EClGG;;;EDsGlB,OAAA,EAAS,sBAAA;ECrG+B;;;ED0GxC,YAAA,EAAc,YAAA;AAAA;;;cC5GH,KAAA,IAAK,MAAA,EAAsB,mBAAA,KAAtB,OAAA;AAAA,cACL,OAAA,IAAO,MAAA,EAAwB,mBAAA,KAAxB,OAAA;AAAA,cACP,MAAA,IAAM,MAAA,EAAuB,mBAAA,KAAvB,OAAA;AAAA,cACN,KAAA,IAAK,MAAA,EAAsB,mBAAA,KAAtB,OAAA;AAAA,cACL,IAAA,IAAI,MAAA,EAAqB,mBAAA,KAArB,OAAA;AAAA,cACJ,IAAA,IAAI,MAAA,EAAqB,mBAAA,KAArB,OAAA;AAAA,cACJ,KAAA,IAAK,MAAA,EAAsB,mBAAA,KAAtB,OAAA;AAAA,cACL,IAAA,IAAI,MAAA,EAAqB,mBAAA,KAArB,OAAA;AAAA,cACJ,MAAA,IAAM,MAAA,EAAuB,mBAAA,KAAvB,OAAA"}
|
|
@@ -1,10 +1,60 @@
|
|
|
1
|
-
import { ExecutionOptions, InlineConfig } from "@powerlines/core";
|
|
1
|
+
import { ExecutionOptions, InlineConfig, LogMeta } from "@powerlines/core";
|
|
2
|
+
import { RpcCacheManager, RpcCacheOptions } from "devframe/rpc";
|
|
3
|
+
import { WsRpcChannelOptions } from "devframe/rpc/transports/ws-client";
|
|
4
|
+
import { BirpcOptions } from "birpc";
|
|
5
|
+
import { ConnectionMeta, DevToolsRpcClientFunctions, DevToolsRpcServerFunctions } from "devframe/types";
|
|
6
|
+
//#region src/types/rpc.d.ts
|
|
7
|
+
/**
|
|
8
|
+
* Payload for write log Rpc messages.
|
|
9
|
+
*/
|
|
10
|
+
interface LogPayload {
|
|
11
|
+
/**
|
|
12
|
+
* Metadata associated with the log message, excluding fields that are automatically added by the engine such as executionId, configIndex, environment, and timestamp. This can include custom fields relevant to the log entry, such as category, name, command, hook, plugin, and source.
|
|
13
|
+
*/
|
|
14
|
+
meta: LogMeta;
|
|
15
|
+
/**
|
|
16
|
+
* The log message content, which can be a string or an array of strings representing the log entry. This field is required and should contain the actual message to be logged.
|
|
17
|
+
*/
|
|
18
|
+
message: string;
|
|
19
|
+
}
|
|
20
|
+
interface RpcServerFunctions extends DevToolsRpcServerFunctions {
|
|
21
|
+
"powerlines:log": (payload: LogPayload) => void;
|
|
22
|
+
}
|
|
23
|
+
interface RpcClientFunctions extends DevToolsRpcClientFunctions {}
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/types/config.d.ts
|
|
26
|
+
interface EngineExecutionOptions extends ExecutionOptions {
|
|
27
|
+
/**
|
|
28
|
+
* The base URL for the dev server, which can be used by plugins to construct URLs for assets or API endpoints during development. This value is only relevant in "dev" mode and will be `undefined` in "build" mode.
|
|
29
|
+
*/
|
|
30
|
+
baseURL: string;
|
|
31
|
+
/**
|
|
32
|
+
* Metadata for the connection used by the dev server, including the backend type and websocket configuration.
|
|
33
|
+
*/
|
|
34
|
+
connection: ConnectionMeta;
|
|
35
|
+
/**
|
|
36
|
+
* Options for configuring the WebSocket RPC channel used for communication between the dev server and the client, which can be used by plugins to customize the behavior of the WebSocket connection, such as setting custom timeouts, retry strategies, or other options.
|
|
37
|
+
*/
|
|
38
|
+
wsOptions?: Partial<WsRpcChannelOptions>;
|
|
39
|
+
/**
|
|
40
|
+
* Options for configuring the RPC client used for communication between the dev server and the client, which can be used by plugins to customize the behavior of the RPC client, such as setting custom timeouts, retry strategies, or other options.
|
|
41
|
+
*/
|
|
42
|
+
rpcOptions?: Partial<BirpcOptions<RpcServerFunctions, RpcClientFunctions, boolean>>;
|
|
43
|
+
/**
|
|
44
|
+
* Options for configuring the RPC cache used for caching RPC responses between the dev server and the client, which can be used by plugins to customize the behavior of the RPC cache, such as setting custom cache keys, expiration times, or other options.
|
|
45
|
+
*
|
|
46
|
+
* @remarks
|
|
47
|
+
* This option can be set to `true` to enable caching with default options, or it can be set to a configuration object that allows for fine-grained control over the caching behavior.
|
|
48
|
+
*/
|
|
49
|
+
cacheOptions?: boolean | Partial<RpcCacheOptions>;
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
2
52
|
//#region src/types/api.d.ts
|
|
3
53
|
interface ExecutionHostParams {
|
|
4
54
|
/**
|
|
5
55
|
* The execution options for the current execution instance
|
|
6
56
|
*/
|
|
7
|
-
options:
|
|
57
|
+
options: EngineExecutionOptions;
|
|
8
58
|
/**
|
|
9
59
|
* The inline configuration for the current execution instance, which is the result of merging the user configuration with any configuration provided by plugins during the "config" hook.
|
|
10
60
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execution-host.d.mts","names":[],"sources":["../../src/types/api.ts","../../src/execution-host.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"execution-host.d.mts","names":[],"sources":["../../src/types/rpc.ts","../../src/types/config.ts","../../src/types/api.ts","../../src/execution-host.ts"],"mappings":";;;;;;;;;UAqGiB,UAAA;ECtBK;;;ED0BpB,IAAA,EAAM,OAAA;ECpBS;;;EDyBf,OAAA;AAAA;AAAA,UAGe,kBAAA,SAA2B,0BAAA;EAE1C,gBAAA,GAAmB,OAAA,EAAS,UAAA;AAAA;AAAA,UAGb,kBAAA,SAA2B,0BAAA;;;UCrD3B,sBAAA,SAA+B,gBAAA;;;;EAI9C,OAAA;;;AAJF;EASE,UAAA,EAAY,cAAA;;;;EAKZ,SAAA,GAAY,OAAA,CAAQ,mBAAA;EAML;;;EADf,UAAA,GAAa,OAAA,CACX,YAAA,CAAa,kBAAA,EAAoB,kBAAA;EASF;;;;;;EAAjC,YAAA,aAAyB,OAAA,CAAQ,eAAA;AAAA;;;UC8ClB,mBAAA;EClGG;;;EDsGlB,OAAA,EAAS,sBAAA;ECrG+B;;;ED0GxC,YAAA,EAAc,YAAA;AAAA;;;cC5GH,KAAA,IAAK,MAAA,EAAsB,mBAAA,KAAtB,OAAA;AAAA,cACL,OAAA,IAAO,MAAA,EAAwB,mBAAA,KAAxB,OAAA;AAAA,cACP,MAAA,IAAM,MAAA,EAAuB,mBAAA,KAAvB,OAAA;AAAA,cACN,KAAA,IAAK,MAAA,EAAsB,mBAAA,KAAtB,OAAA;AAAA,cACL,IAAA,IAAI,MAAA,EAAqB,mBAAA,KAArB,OAAA;AAAA,cACJ,IAAA,IAAI,MAAA,EAAqB,mBAAA,KAArB,OAAA;AAAA,cACJ,KAAA,IAAK,MAAA,EAAsB,mBAAA,KAAtB,OAAA;AAAA,cACL,IAAA,IAAI,MAAA,EAAqB,mBAAA,KAArB,OAAA;AAAA,cACJ,MAAA,IAAM,MAAA,EAAuB,mBAAA,KAAvB,OAAA"}
|
|
@@ -13,7 +13,7 @@ import { installDependencies } from "@powerlines/core/lib/install-dependencies";
|
|
|
13
13
|
import { writeMetaFile } from "@powerlines/core/lib/meta";
|
|
14
14
|
import { initializeTsconfig, resolveTsconfig } from "@powerlines/core/lib/typescript/tsconfig";
|
|
15
15
|
import { format, formatFolder as formatFolder$1 } from "@powerlines/core/lib/utilities/format";
|
|
16
|
-
import { formatConfig } from "@powerlines/core/plugin-utils";
|
|
16
|
+
import { consoleLogger, formatConfig } from "@powerlines/core/plugin-utils";
|
|
17
17
|
import { toArray } from "@stryke/convert/to-array";
|
|
18
18
|
import { createDirectory } from "@stryke/fs/helpers";
|
|
19
19
|
import { isObject } from "@stryke/type-checks/is-object";
|
|
@@ -25,6 +25,19 @@ import { omit } from "@stryke/helpers/omit";
|
|
|
25
25
|
import { isSetObject } from "@stryke/type-checks/is-set-object";
|
|
26
26
|
import { PowerlinesExecutionContext } from "@powerlines/core/context/execution-context";
|
|
27
27
|
import { resolvePluginConfig } from "@powerlines/core/lib/context-helpers";
|
|
28
|
+
import { titleCase } from "@stryke/string-format/title-case";
|
|
29
|
+
import { uuid } from "@stryke/unique-id/uuid";
|
|
30
|
+
import { createEventEmitter } from "@powerlines/core/lib/events";
|
|
31
|
+
import { isNumber } from "@stryke/type-checks/is-number";
|
|
32
|
+
import { isSet } from "@stryke/type-checks/is-set";
|
|
33
|
+
import { StormURL } from "@stryke/url";
|
|
34
|
+
import { createRpcStreamingClientHost } from "devframe/client";
|
|
35
|
+
import { RpcCacheManager, RpcFunctionsCollectorBase } from "devframe/rpc";
|
|
36
|
+
import { createRpcClient } from "devframe/rpc/client";
|
|
37
|
+
import { createWsRpcChannel } from "devframe/rpc/transports/ws-client";
|
|
38
|
+
import { promiseWithResolver } from "devframe/utils/promise";
|
|
39
|
+
import { humanId } from "human-id";
|
|
40
|
+
import { EventEmitter } from "node:events";
|
|
28
41
|
|
|
29
42
|
//#region src/api/prepare.ts
|
|
30
43
|
/**
|
|
@@ -337,6 +350,131 @@ async function types$1(context) {
|
|
|
337
350
|
timer();
|
|
338
351
|
}
|
|
339
352
|
|
|
353
|
+
//#endregion
|
|
354
|
+
//#region src/helpers/rpc.ts
|
|
355
|
+
function createWsRpcClientMode(baseURL, connectionMeta, events, clientRpc, authToken = humanId({
|
|
356
|
+
separator: "-",
|
|
357
|
+
capitalize: false
|
|
358
|
+
}), rpcOptions = {}, wsOptions = {}) {
|
|
359
|
+
let isTrusted = false;
|
|
360
|
+
const trustedPromise = promiseWithResolver();
|
|
361
|
+
const url = isNumber(connectionMeta.websocket) || isSet(connectionMeta.websocket) && `${+connectionMeta.websocket}` === `${connectionMeta.websocket}` ? `${baseURL.protocol.replace("http", "ws")}//${baseURL.hostname}:${connectionMeta.websocket}` : connectionMeta.websocket;
|
|
362
|
+
const definitions = /* @__PURE__ */ new Map();
|
|
363
|
+
for (const name of connectionMeta.jsonSerializableMethods ?? []) definitions.set(name, { jsonSerializable: true });
|
|
364
|
+
const serverRpc = createRpcClient(clientRpc.functions, {
|
|
365
|
+
channel: createWsRpcChannel({
|
|
366
|
+
url,
|
|
367
|
+
authToken,
|
|
368
|
+
definitions,
|
|
369
|
+
...wsOptions
|
|
370
|
+
}),
|
|
371
|
+
rpcOptions
|
|
372
|
+
});
|
|
373
|
+
clientRpc.register({
|
|
374
|
+
name: "devframe:auth:revoked",
|
|
375
|
+
type: "event",
|
|
376
|
+
handler: () => {
|
|
377
|
+
isTrusted = false;
|
|
378
|
+
events.emit("rpc:is-trusted:updated", false);
|
|
379
|
+
}
|
|
380
|
+
});
|
|
381
|
+
let currentAuthToken = authToken;
|
|
382
|
+
async function requestTrustWithToken(token) {
|
|
383
|
+
currentAuthToken = token;
|
|
384
|
+
return true;
|
|
385
|
+
}
|
|
386
|
+
async function requestTrust() {
|
|
387
|
+
if (isTrusted) return true;
|
|
388
|
+
return requestTrustWithToken(currentAuthToken);
|
|
389
|
+
}
|
|
390
|
+
async function ensureTrusted(timeout = 6e4) {
|
|
391
|
+
if (isTrusted) trustedPromise.resolve(true);
|
|
392
|
+
if (timeout <= 0) return trustedPromise.promise;
|
|
393
|
+
let clear = () => {};
|
|
394
|
+
await Promise.race([trustedPromise.promise.then(clear), new Promise((resolve, reject) => {
|
|
395
|
+
const id = setTimeout(() => {
|
|
396
|
+
reject(/* @__PURE__ */ new Error("Timeout waiting for rpc to be trusted"));
|
|
397
|
+
}, timeout);
|
|
398
|
+
clear = () => clearTimeout(id);
|
|
399
|
+
})]);
|
|
400
|
+
return isTrusted;
|
|
401
|
+
}
|
|
402
|
+
return {
|
|
403
|
+
get isTrusted() {
|
|
404
|
+
return isTrusted;
|
|
405
|
+
},
|
|
406
|
+
requestTrust,
|
|
407
|
+
requestTrustWithToken,
|
|
408
|
+
ensureTrusted,
|
|
409
|
+
call: (...args) => {
|
|
410
|
+
return serverRpc.$call(...args);
|
|
411
|
+
},
|
|
412
|
+
callEvent: (...args) => {
|
|
413
|
+
return serverRpc.$callEvent(...args);
|
|
414
|
+
},
|
|
415
|
+
callOptional: (...args) => {
|
|
416
|
+
return serverRpc.$callOptional(...args);
|
|
417
|
+
}
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
const CONNECTION_AUTH_TOKEN_KEY = "__DEVTOOLS_CONNECTION_AUTH_TOKEN__";
|
|
421
|
+
function createRpcClient$1(options) {
|
|
422
|
+
const baseURL = new StormURL(options.baseURL);
|
|
423
|
+
const cacheManager = new RpcCacheManager({
|
|
424
|
+
functions: [],
|
|
425
|
+
...typeof options.cacheOptions === "object" ? options.cacheOptions : {}
|
|
426
|
+
});
|
|
427
|
+
const context = { rpc: void 0 };
|
|
428
|
+
const clientRpc = new RpcFunctionsCollectorBase(context);
|
|
429
|
+
EventEmitter.setMaxListeners(100);
|
|
430
|
+
const events = createEventEmitter();
|
|
431
|
+
const mode = createWsRpcClientMode(baseURL, options.connection, events, clientRpc, void 0, {
|
|
432
|
+
...options.rpcOptions,
|
|
433
|
+
async onRequest(req, next, resolve) {
|
|
434
|
+
await options.rpcOptions?.onRequest?.call(this, req, next, resolve);
|
|
435
|
+
if (options.cacheOptions && cacheManager?.validate(req.m)) {
|
|
436
|
+
const cached = cacheManager.cached(req.m, req.a);
|
|
437
|
+
if (cached) return resolve(cached);
|
|
438
|
+
else {
|
|
439
|
+
const res = await next(req);
|
|
440
|
+
cacheManager?.apply(req, res);
|
|
441
|
+
}
|
|
442
|
+
} else await next(req);
|
|
443
|
+
}
|
|
444
|
+
}, options.wsOptions);
|
|
445
|
+
const rpc = {
|
|
446
|
+
events,
|
|
447
|
+
get isTrusted() {
|
|
448
|
+
return mode.isTrusted;
|
|
449
|
+
},
|
|
450
|
+
connectionMeta: options.connection,
|
|
451
|
+
ensureTrusted: mode.ensureTrusted,
|
|
452
|
+
requestTrust: mode.requestTrust,
|
|
453
|
+
requestTrustWithToken: async (token) => {
|
|
454
|
+
localStorage.setItem(CONNECTION_AUTH_TOKEN_KEY, token);
|
|
455
|
+
globalThis[CONNECTION_AUTH_TOKEN_KEY] = token;
|
|
456
|
+
return mode.requestTrustWithToken(token);
|
|
457
|
+
},
|
|
458
|
+
call: mode.call,
|
|
459
|
+
callEvent: mode.callEvent,
|
|
460
|
+
callOptional: mode.callOptional,
|
|
461
|
+
client: clientRpc,
|
|
462
|
+
sharedState: void 0,
|
|
463
|
+
streaming: void 0,
|
|
464
|
+
cacheManager
|
|
465
|
+
};
|
|
466
|
+
rpc.streaming = createRpcStreamingClientHost(rpc);
|
|
467
|
+
context.rpc = rpc;
|
|
468
|
+
mode.requestTrust();
|
|
469
|
+
try {
|
|
470
|
+
const bc = new BroadcastChannel("vite-devtools-auth");
|
|
471
|
+
bc.onmessage = (event) => {
|
|
472
|
+
if (event.data?.type === "auth-update" && event.data.authToken) rpc.requestTrustWithToken(event.data.authToken);
|
|
473
|
+
};
|
|
474
|
+
} catch {}
|
|
475
|
+
return rpc;
|
|
476
|
+
}
|
|
477
|
+
|
|
340
478
|
//#endregion
|
|
341
479
|
//#region src/helpers/create-execution-host.ts
|
|
342
480
|
/**
|
|
@@ -347,8 +485,28 @@ async function types$1(context) {
|
|
|
347
485
|
*/
|
|
348
486
|
function createExecutionHost(methods) {
|
|
349
487
|
return Object.fromEntries(Object.entries(methods).map(([method, fn]) => [method, async (params) => {
|
|
350
|
-
const
|
|
351
|
-
|
|
488
|
+
const { options, inlineConfig } = params;
|
|
489
|
+
let rpc;
|
|
490
|
+
if (options.baseURL && options.connection) rpc = createRpcClient$1(options);
|
|
491
|
+
else throw new Error(`Execution RPC client could not be created - Missing ${!options.baseURL ? `baseURL${options.connection ? ` and connection information` : ""}` : "connection"} or connection information.`);
|
|
492
|
+
const logFn = (meta, message) => {
|
|
493
|
+
consoleLogger(meta, message);
|
|
494
|
+
if (rpc) rpc.callEvent("powerlines:log", {
|
|
495
|
+
meta: {
|
|
496
|
+
category: "general",
|
|
497
|
+
...options,
|
|
498
|
+
...isSetObject(meta) ? meta : { type: meta },
|
|
499
|
+
logId: uuid(),
|
|
500
|
+
timestamp: Date.now()
|
|
501
|
+
},
|
|
502
|
+
message
|
|
503
|
+
});
|
|
504
|
+
};
|
|
505
|
+
const context = await PowerlinesExecutionContext.from({
|
|
506
|
+
...options,
|
|
507
|
+
logFn
|
|
508
|
+
}, inlineConfig ?? {}, { rpc });
|
|
509
|
+
context.logger.info(`Starting ${titleCase(options.framework?.name) || "Powerlines"} - ${titleCase(method)} execution (${options.executionId})`);
|
|
352
510
|
await resolvePluginConfig(context);
|
|
353
511
|
await fn(context);
|
|
354
512
|
}]));
|