@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.
Files changed (55) hide show
  1. package/dist/api/build.d.cts +1 -1
  2. package/dist/api/build.d.mts +1 -1
  3. package/dist/api/clean.d.cts +1 -1
  4. package/dist/api/clean.d.mts +1 -1
  5. package/dist/api/create.d.cts +1 -1
  6. package/dist/api/create.d.mts +1 -1
  7. package/dist/api/deploy.d.cts +1 -1
  8. package/dist/api/deploy.d.mts +1 -1
  9. package/dist/api/docs.d.cts +1 -1
  10. package/dist/api/docs.d.mts +1 -1
  11. package/dist/api/lint.d.cts +1 -1
  12. package/dist/api/lint.d.mts +1 -1
  13. package/dist/api/prepare.d.cts +1 -1
  14. package/dist/api/prepare.d.mts +1 -1
  15. package/dist/api/test.d.cts +1 -1
  16. package/dist/api/test.d.mts +1 -1
  17. package/dist/api/types.d.cts +1 -1
  18. package/dist/api/types.d.mts +1 -1
  19. package/dist/{api-Bw-RpQgX.d.cts → api-Bi_h4LMX.d.cts} +5 -4
  20. package/dist/api-Bi_h4LMX.d.cts.map +1 -0
  21. package/dist/{api-D9bpSxPB.d.mts → api-oIs2Wp3t.d.mts} +5 -4
  22. package/dist/api-oIs2Wp3t.d.mts.map +1 -0
  23. package/dist/context/index.d.cts +1 -1
  24. package/dist/context/index.d.mts +1 -1
  25. package/dist/{context-DrNGEC0b.d.mts → context-DrNQXXRC.d.mts} +2 -2
  26. package/dist/{context-C_P-KYJX.d.cts.map → context-DrNQXXRC.d.mts.map} +1 -1
  27. package/dist/{context-C_P-KYJX.d.cts → context-LQBeYY23.d.cts} +2 -2
  28. package/dist/{context-DrNGEC0b.d.mts.map → context-LQBeYY23.d.cts.map} +1 -1
  29. package/dist/{engine-context-BXjBJuHe.d.mts → engine-context-BBSMtv0b.d.mts} +2 -2
  30. package/dist/{engine-context-BXjBJuHe.d.mts.map → engine-context-BBSMtv0b.d.mts.map} +1 -1
  31. package/dist/{engine-context-CPYw-aGB.d.cts → engine-context-C6bNxumd.d.cts} +2 -2
  32. package/dist/{engine-context-CPYw-aGB.d.cts.map → engine-context-C6bNxumd.d.cts.map} +1 -1
  33. package/dist/engine.d.cts +3 -3
  34. package/dist/engine.d.mts +3 -3
  35. package/dist/helpers/create-execution-host.cjs +27 -2
  36. package/dist/helpers/create-execution-host.d.cts +2 -2
  37. package/dist/helpers/create-execution-host.d.cts.map +1 -1
  38. package/dist/helpers/create-execution-host.d.mts +2 -2
  39. package/dist/helpers/create-execution-host.d.mts.map +1 -1
  40. package/dist/helpers/create-execution-host.mjs +27 -2
  41. package/dist/helpers/create-execution-host.mjs.map +1 -1
  42. package/dist/helpers/execution-host-worker.d.cts +2 -2
  43. package/dist/helpers/execution-host-worker.d.mts +2 -2
  44. package/dist/index.d.cts +2 -2
  45. package/dist/index.d.mts +2 -2
  46. package/dist/worker/execution-host.cjs +160 -2
  47. package/dist/worker/execution-host.d.cts +52 -2
  48. package/dist/worker/execution-host.d.cts.map +1 -1
  49. package/dist/worker/execution-host.d.mts +52 -2
  50. package/dist/worker/execution-host.d.mts.map +1 -1
  51. package/dist/worker/execution-host.mjs +161 -3
  52. package/dist/worker/execution-host.mjs.map +1 -1
  53. package/package.json +6 -6
  54. package/dist/api-Bw-RpQgX.d.cts.map +0 -1
  55. 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 context = await _powerlines_core_context_execution_context.PowerlinesExecutionContext.from(params.options, params.inlineConfig ?? {});
381
- context.logger.info(`Starting ${method} execution (${params.options.executionId})`);
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: ExecutionOptions;
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":";;UA4IiB,mBAAA;EC3FE;;;ED+FjB,OAAA,EAAS,gBAAA;EC/FQ;;;EDoGjB,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
+ {"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: ExecutionOptions;
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":";;UA4IiB,mBAAA;EC3FE;;;ED+FjB,OAAA,EAAS,gBAAA;EC/FQ;;;EDoGjB,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
+ {"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 context = await PowerlinesExecutionContext.from(params.options, params.inlineConfig ?? {});
351
- context.logger.info(`Starting ${method} execution (${params.options.executionId})`);
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
  }]));