@arcanewizards/sigil 0.1.0

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 (66) hide show
  1. package/dist/chunk-4PMRDURG.js +66 -0
  2. package/dist/chunk-5DRI7C4U.cjs +66 -0
  3. package/dist/chunk-A5LYYZER.cjs +103 -0
  4. package/dist/chunk-BIY5HAXP.js +125 -0
  5. package/dist/chunk-CAYKPJIX.cjs +10 -0
  6. package/dist/chunk-EJNNLQ2S.js +72 -0
  7. package/dist/chunk-FHXT3DAL.js +103 -0
  8. package/dist/chunk-H4U4Z4GM.js +66 -0
  9. package/dist/chunk-LSHKAVON.js +10 -0
  10. package/dist/chunk-MXDDIFIO.cjs +767 -0
  11. package/dist/chunk-PEARNJ5G.cjs +125 -0
  12. package/dist/chunk-RI33QVOD.cjs +66 -0
  13. package/dist/chunk-VZ4A6RRT.cjs +72 -0
  14. package/dist/chunk-XAK7WC3D.js +767 -0
  15. package/dist/frontend/appearance.cjs +88 -0
  16. package/dist/frontend/appearance.d.cts +11 -0
  17. package/dist/frontend/appearance.d.ts +11 -0
  18. package/dist/frontend/appearance.js +88 -0
  19. package/dist/frontend/context.cjs +16 -0
  20. package/dist/frontend/context.d.cts +32 -0
  21. package/dist/frontend/context.d.ts +32 -0
  22. package/dist/frontend/context.js +16 -0
  23. package/dist/frontend/controls/index.cjs +49 -0
  24. package/dist/frontend/controls/index.d.cts +168 -0
  25. package/dist/frontend/controls/index.d.ts +168 -0
  26. package/dist/frontend/controls/index.js +49 -0
  27. package/dist/frontend/dialogs.cjs +17 -0
  28. package/dist/frontend/dialogs.d.cts +36 -0
  29. package/dist/frontend/dialogs.d.ts +36 -0
  30. package/dist/frontend/dialogs.js +17 -0
  31. package/dist/frontend/input.cjs +8 -0
  32. package/dist/frontend/input.d.cts +33 -0
  33. package/dist/frontend/input.d.ts +33 -0
  34. package/dist/frontend/input.js +8 -0
  35. package/dist/frontend/preferences.cjs +54 -0
  36. package/dist/frontend/preferences.d.cts +14 -0
  37. package/dist/frontend/preferences.d.ts +14 -0
  38. package/dist/frontend/preferences.js +54 -0
  39. package/dist/frontend/styles/base.css +321 -0
  40. package/dist/frontend/styles/sigil.css +785 -0
  41. package/dist/frontend/styles/theme.css +625 -0
  42. package/dist/frontend/styling.cjs +18 -0
  43. package/dist/frontend/styling.d.cts +32 -0
  44. package/dist/frontend/styling.d.ts +32 -0
  45. package/dist/frontend/styling.js +18 -0
  46. package/dist/frontend/toolbars.cjs +18 -0
  47. package/dist/frontend/toolbars.d.cts +11 -0
  48. package/dist/frontend/toolbars.d.ts +11 -0
  49. package/dist/frontend/toolbars.js +18 -0
  50. package/dist/frontend/tooltip.cjs +10 -0
  51. package/dist/frontend/tooltip.d.cts +16 -0
  52. package/dist/frontend/tooltip.d.ts +16 -0
  53. package/dist/frontend/tooltip.js +10 -0
  54. package/dist/frontend.cjs +359 -0
  55. package/dist/frontend.d.cts +90 -0
  56. package/dist/frontend.d.ts +90 -0
  57. package/dist/frontend.js +359 -0
  58. package/dist/index.cjs +492 -0
  59. package/dist/index.d.cts +134 -0
  60. package/dist/index.d.ts +134 -0
  61. package/dist/index.js +492 -0
  62. package/dist/proto-B-WcMUOE.d.cts +33 -0
  63. package/dist/proto-kGDF-yWB.d.ts +33 -0
  64. package/dist/types-X8O95zmC.d.cts +23 -0
  65. package/dist/types-X8O95zmC.d.ts +23 -0
  66. package/package.json +123 -0
@@ -0,0 +1,134 @@
1
+ import * as react from 'react';
2
+ import { JSX, ReactNode, FC } from 'react';
3
+ import { Logger } from '@arcanejs/protocol/logging';
4
+ import { ToolkitRenderer } from '@arcanejs/react-toolkit';
5
+ import { Toolkit, ToolkitOptions, ToolkitRenderContext } from '@arcanejs/toolkit';
6
+ import { EventEmitter } from 'node:events';
7
+ import pino from 'pino';
8
+ import { A as AppRootLogEntry, S as SystemInformation } from './types-X8O95zmC.js';
9
+ export { a as AppRootLogEntryStackFrame } from './types-X8O95zmC.js';
10
+ import { AnyClientComponentCall } from '@arcanejs/protocol';
11
+ import { BaseParent, AnyComponent } from '@arcanejs/toolkit/components/base';
12
+ import { IDMap } from '@arcanejs/toolkit/util';
13
+ import { g as SigilNamespace, S as SigilAppRootComponent, a as AppRootGetLogsArgs, b as AppRootGetLogsReturn, e as SigilComponentCalls } from './proto-kGDF-yWB.js';
14
+ export { A as AppRootGetLogs, c as SIGIL_NAMESPACE, d as SigilComponent, h as SigilComponentMessage, i as isSigilComponent, f as isSigilComponentCall } from './proto-kGDF-yWB.js';
15
+ import { NetworkPortStatus } from '@arcanewizards/net-utils';
16
+ import '@arcanejs/diff';
17
+
18
+ type AppInformationContextData = {
19
+ version: string;
20
+ title: string;
21
+ };
22
+ declare const AppInformationContext: react.Context<AppInformationContextData>;
23
+ type ShutdownContextData = {
24
+ addShutdownListener: (listener: () => Promise<void>) => void;
25
+ removeShutdownListener: (listener: () => Promise<void>) => void;
26
+ };
27
+ declare const ShutdownContext: react.Context<ShutdownContextData>;
28
+ declare const useShutdownHandler: (handler: () => Promise<void>) => void;
29
+ declare const LoggerContext: react.Context<{
30
+ logger: Logger;
31
+ }>;
32
+ declare const useLogger: () => Logger;
33
+
34
+ type SigilLogEventEmitter = EventEmitter<{
35
+ logsUpdated: [{
36
+ logs: AppRootLogEntry[];
37
+ }];
38
+ }>;
39
+ type SigilRuntimeAppProps<TAppApi, TExtraAppProps extends object> = TExtraAppProps & {
40
+ title: string;
41
+ version: string;
42
+ toolkit: Toolkit;
43
+ logger: Logger;
44
+ logEventEmitter: SigilLogEventEmitter;
45
+ setAppApi: (api: TAppApi | null) => void;
46
+ setWindowUrl: (windowUrl: URL) => void;
47
+ shutdownContext: ShutdownContextData;
48
+ };
49
+ type SigilRuntimeEventMap<TAppApi> = {
50
+ apiChange: (api: TAppApi | null) => void;
51
+ windowUrlChange: (url: URL) => void;
52
+ };
53
+ type SigilAppInstance<TAppApi> = {
54
+ addEventListener<K extends keyof SigilRuntimeEventMap<TAppApi>>(event: K, listener: SigilRuntimeEventMap<TAppApi>[K]): void;
55
+ shutdown: () => Promise<void>;
56
+ };
57
+ type SigilRuntimeOptions<TAppApi, TExtraAppProps extends object> = {
58
+ logger: pino.Logger;
59
+ title: string;
60
+ version: string;
61
+ appProps: TExtraAppProps;
62
+ toolkitOptions?: Omit<Partial<ToolkitOptions>, 'logger'>;
63
+ createApp: (props: SigilRuntimeAppProps<TAppApi, TExtraAppProps>) => JSX.Element;
64
+ componentNamespaces?: NonNullable<Parameters<typeof ToolkitRenderer.render>[3]>['componentNamespaces'];
65
+ };
66
+ declare const createSystemInformation: ({ dataDirectory, version, }: {
67
+ dataDirectory: string;
68
+ version: string;
69
+ }) => SystemInformation;
70
+ declare const runSigilApp: <TAppApi, TExtraAppProps extends object>({ logger: upstreamLogger, title, version, appProps, toolkitOptions, createApp, componentNamespaces, }: SigilRuntimeOptions<TAppApi, TExtraAppProps>) => SigilAppInstance<TAppApi>;
71
+
72
+ type AppShellProps = {
73
+ title: string;
74
+ version: string;
75
+ dataDirectory: string;
76
+ logger: Logger;
77
+ logEventEmitter: SigilLogEventEmitter;
78
+ shutdownContext: ShutdownContextData;
79
+ children: ReactNode;
80
+ };
81
+ declare const AppShell: ({ title, version, dataDirectory, logger, logEventEmitter, shutdownContext, children, }: AppShellProps) => JSX.Element;
82
+
83
+ type AppRootEvents = {
84
+ getLogs: (args: AppRootGetLogsArgs) => Promise<AppRootGetLogsReturn>;
85
+ };
86
+ type AppRootProps = Pick<SigilAppRootComponent, 'lastLog' | 'system'> & {
87
+ onGetLogs?: AppRootEvents['getLogs'];
88
+ };
89
+ type SupportedCalls = 'app-root-get-logs';
90
+ declare class AppRoot extends BaseParent<SigilNamespace, SigilAppRootComponent, AppRootProps, SigilComponentCalls, SupportedCalls> {
91
+ private readonly events;
92
+ constructor(props: AppRootProps);
93
+ addListener: <T extends "getLogs">(type: T, listener: AppRootEvents[T]) => void;
94
+ removeListener: <T extends "getLogs">(type: T, listener: AppRootEvents[T]) => void;
95
+ validateChildren: (children: AnyComponent[]) => void;
96
+ getProtoInfo(idMap: IDMap, context: ToolkitRenderContext): SigilAppRootComponent;
97
+ handleCall: (call: AnyClientComponentCall) => Promise<AppRootGetLogsReturn>;
98
+ }
99
+ declare const SIGIL_COMPONENTS: {
100
+ _namespace: string;
101
+ _creators: {
102
+ AppRoot: (props: {
103
+ [key: string]: any;
104
+ }) => AnyComponent;
105
+ };
106
+ } & {
107
+ AppRoot: react.ForwardRefExoticComponent<Pick<SigilAppRootComponent, "lastLog" | "system"> & {
108
+ onGetLogs?: AppRootEvents["getLogs"];
109
+ } & {
110
+ children?: react.ReactNode;
111
+ } & react.RefAttributes<AppRoot>>;
112
+ };
113
+
114
+ type ListenerConfig = {
115
+ port: number | {
116
+ from: number;
117
+ to: number;
118
+ };
119
+ interface?: string | undefined;
120
+ };
121
+ type AllListenerConfig = Record<string, ListenerConfig>;
122
+ type AppListenerManagerAppRegistration = {
123
+ removeConnection: (uuid: string) => void;
124
+ setConnection: (uuid: string, details: NetworkPortStatus) => void;
125
+ };
126
+ type AppListenerManagerProps = {
127
+ appRegistration?: AppListenerManagerAppRegistration;
128
+ listenerConfig: AllListenerConfig;
129
+ toolkit: Toolkit;
130
+ setWindowUrl: (windowUrl: URL) => void;
131
+ };
132
+ declare const AppListenerManager: FC<AppListenerManagerProps>;
133
+
134
+ export { type AllListenerConfig, AppInformationContext, type AppInformationContextData, AppListenerManager, type AppListenerManagerAppRegistration, AppRoot, AppRootGetLogsArgs, AppRootGetLogsReturn, AppRootLogEntry, AppShell, type AppShellProps, type ListenerConfig, LoggerContext, SIGIL_COMPONENTS, ShutdownContext, type ShutdownContextData, type SigilAppInstance, SigilAppRootComponent, SigilComponentCalls, type SigilRuntimeAppProps, type SigilRuntimeEventMap, type SigilRuntimeOptions, SystemInformation, createSystemInformation, runSigilApp, useLogger, useShutdownHandler };
package/dist/index.js ADDED
@@ -0,0 +1,492 @@
1
+ import {
2
+ SIGIL_NAMESPACE,
3
+ isSigilComponent,
4
+ isSigilComponentCall
5
+ } from "./chunk-LSHKAVON.js";
6
+
7
+ // src/app-shell.tsx
8
+ import { useEffect as useEffect2, useMemo, useState } from "react";
9
+
10
+ // src/backend/app-root.ts
11
+ import {
12
+ BaseParent,
13
+ EventEmitter
14
+ } from "@arcanejs/toolkit/components/base";
15
+ import { prepareComponents } from "@arcanejs/react-toolkit";
16
+ var DEFAULT_PROPS = {
17
+ lastLog: -1,
18
+ system: {
19
+ version: "unknown",
20
+ appPath: "unknown",
21
+ cwd: "unknown",
22
+ os: "unknown",
23
+ dataDirectory: "unknown"
24
+ }
25
+ };
26
+ var AppRoot = class extends BaseParent {
27
+ events = new EventEmitter();
28
+ constructor(props) {
29
+ super(DEFAULT_PROPS, props, {
30
+ onPropsUpdated: (oldProps) => this.events.processPropChanges(
31
+ {
32
+ onGetLogs: "getLogs"
33
+ },
34
+ oldProps,
35
+ this.props
36
+ )
37
+ });
38
+ this.triggerInitialPropsUpdate();
39
+ }
40
+ addListener = this.events.addListener;
41
+ removeListener = this.events.removeListener;
42
+ validateChildren = (children) => {
43
+ if (children.length > 1) {
44
+ throw new Error("Sigil AppRoot can only have one child");
45
+ }
46
+ };
47
+ getProtoInfo(idMap, context) {
48
+ return {
49
+ namespace: SIGIL_NAMESPACE,
50
+ component: "app-root",
51
+ key: idMap.getId(this),
52
+ child: this.getChildren().slice(0, 1).map((child) => child.getProtoInfo(idMap, context))[0] ?? null,
53
+ lastLog: this.props.lastLog,
54
+ system: this.props.system
55
+ };
56
+ }
57
+ handleCall = async (call) => {
58
+ if (isSigilComponentCall(call, "app-root-get-logs")) {
59
+ return this.events.call("getLogs", { after: call.after });
60
+ }
61
+ throw new Error(`Unhandled call action: ${call.action}`);
62
+ };
63
+ };
64
+ var SIGIL_COMPONENTS = prepareComponents(SIGIL_NAMESPACE, {
65
+ AppRoot
66
+ });
67
+
68
+ // src/context.tsx
69
+ import { createContext, useContext, useEffect } from "react";
70
+ var AppInformationContext = createContext({
71
+ version: "",
72
+ title: ""
73
+ });
74
+ var ShutdownContext = createContext(
75
+ new Proxy({}, {
76
+ get() {
77
+ throw new Error(
78
+ "ShutdownContext is not available outside of the Sigil application environment"
79
+ );
80
+ }
81
+ })
82
+ );
83
+ var useShutdownHandler = (handler) => {
84
+ const { addShutdownListener, removeShutdownListener } = useContext(ShutdownContext);
85
+ useEffect(() => {
86
+ addShutdownListener(handler);
87
+ return () => {
88
+ removeShutdownListener(handler);
89
+ };
90
+ }, [addShutdownListener, removeShutdownListener, handler]);
91
+ };
92
+ var LoggerContext = createContext({
93
+ get logger() {
94
+ throw new Error("Logger not initialized");
95
+ }
96
+ });
97
+ var useLogger = () => {
98
+ return useContext(LoggerContext).logger;
99
+ };
100
+
101
+ // src/runtime.tsx
102
+ import { ArcaneDataFileError } from "@arcanejs/react-toolkit/data";
103
+ import { CoreComponents, ToolkitRenderer } from "@arcanejs/react-toolkit";
104
+ import { Toolkit } from "@arcanejs/toolkit";
105
+ import { EventEmitter as EventEmitter2 } from "events";
106
+ var MAX_LOG_ENTRIES = 1e3;
107
+ var getStackFramesFromError = (error) => {
108
+ if (typeof error === "string") {
109
+ return { message: error, stack: null, cause: null };
110
+ }
111
+ if (!(error instanceof Error)) {
112
+ return { message: String(error), stack: null, cause: null };
113
+ }
114
+ const frame = {
115
+ message: error.message,
116
+ stack: error.stack ?? null,
117
+ cause: error.cause ? getStackFramesFromError(error.cause) : null
118
+ };
119
+ if (error instanceof ArcaneDataFileError) {
120
+ frame.filePath = error.path;
121
+ frame.operation = error.operation;
122
+ frame.contents = error.contents;
123
+ }
124
+ return frame;
125
+ };
126
+ var createSystemInformation = ({
127
+ dataDirectory,
128
+ version
129
+ }) => {
130
+ return {
131
+ appPath: process.execPath,
132
+ cwd: process.cwd(),
133
+ os: process.platform,
134
+ version,
135
+ dataDirectory
136
+ };
137
+ };
138
+ var runSigilApp = ({
139
+ logger: upstreamLogger,
140
+ title,
141
+ version,
142
+ appProps,
143
+ toolkitOptions,
144
+ createApp,
145
+ componentNamespaces = [CoreComponents, SIGIL_COMPONENTS]
146
+ }) => {
147
+ let logs = [];
148
+ const logEventEmitter = new EventEmitter2();
149
+ const addLogEntry = (entry) => {
150
+ const index = (logs[logs.length - 1]?.index ?? -1) + 1;
151
+ const trimEntries = Math.max(0, logs.length - MAX_LOG_ENTRIES + 1);
152
+ logs = [...logs.slice(trimEntries), { index, ...entry }];
153
+ logEventEmitter.emit("logsUpdated", { logs });
154
+ };
155
+ const logError = (level, rootMsg) => {
156
+ upstreamLogger[level](rootMsg);
157
+ let error = rootMsg instanceof Error ? rootMsg : null;
158
+ let message = typeof rootMsg === "string" ? rootMsg : rootMsg.message;
159
+ while (error) {
160
+ if (error !== rootMsg) {
161
+ message += `: ${error.message}`;
162
+ }
163
+ error = error.cause instanceof Error ? error.cause : null;
164
+ }
165
+ addLogEntry({
166
+ level,
167
+ message,
168
+ timestamp: Date.now(),
169
+ stack: getStackFramesFromError(rootMsg)
170
+ });
171
+ };
172
+ const logMessage = (level, message) => {
173
+ upstreamLogger[level](message);
174
+ addLogEntry({
175
+ level,
176
+ message,
177
+ timestamp: Date.now()
178
+ });
179
+ };
180
+ const logger = {
181
+ debug: (message) => logMessage("debug", message),
182
+ info: (message) => logMessage("info", message),
183
+ warn: (message) => logError("warn", message),
184
+ error: (message) => logError("error", message)
185
+ };
186
+ const toolkit = new Toolkit({
187
+ log: {
188
+ ...logger,
189
+ debug: upstreamLogger.debug.bind(upstreamLogger)
190
+ },
191
+ title,
192
+ ...toolkitOptions
193
+ });
194
+ toolkit.start({
195
+ mode: "manual",
196
+ setup: () => {
197
+ logger.info(`${title} ready to start listening`);
198
+ }
199
+ });
200
+ let api = null;
201
+ const apiListeners = /* @__PURE__ */ new Set();
202
+ const setAppApi = (value) => {
203
+ api = value;
204
+ for (const listener of apiListeners) {
205
+ listener(value);
206
+ }
207
+ };
208
+ let windowUrl = null;
209
+ const windowUrlListeners = /* @__PURE__ */ new Set();
210
+ const setWindowUrl = (value) => {
211
+ windowUrl = value;
212
+ for (const listener of windowUrlListeners) {
213
+ listener(value);
214
+ }
215
+ };
216
+ const shutdownListeners = /* @__PURE__ */ new Set();
217
+ const shutdownContext = {
218
+ addShutdownListener: (listener) => {
219
+ shutdownListeners.add(listener);
220
+ },
221
+ removeShutdownListener: (listener) => {
222
+ shutdownListeners.delete(listener);
223
+ }
224
+ };
225
+ const shutdown = async () => {
226
+ logger.info(`Shutting down ${title}...`);
227
+ await Promise.all(
228
+ Array.from(shutdownListeners).map((listener) => listener())
229
+ );
230
+ logger.info(`${title} shutdown complete`);
231
+ };
232
+ ToolkitRenderer.render(
233
+ createApp({
234
+ title,
235
+ version,
236
+ toolkit,
237
+ logger,
238
+ logEventEmitter,
239
+ setAppApi,
240
+ setWindowUrl,
241
+ shutdownContext,
242
+ ...appProps
243
+ }),
244
+ toolkit,
245
+ {},
246
+ {
247
+ componentNamespaces
248
+ }
249
+ );
250
+ return {
251
+ addEventListener: (event, listener) => {
252
+ if (event === "apiChange") {
253
+ const apiListener = listener;
254
+ apiListeners.add(apiListener);
255
+ if (api) {
256
+ apiListener(api);
257
+ }
258
+ return;
259
+ }
260
+ const windowUrlListener = listener;
261
+ windowUrlListeners.add(windowUrlListener);
262
+ if (windowUrl) {
263
+ windowUrlListener(windowUrl);
264
+ }
265
+ },
266
+ shutdown
267
+ };
268
+ };
269
+
270
+ // src/app-shell.tsx
271
+ import { jsx } from "react/jsx-runtime";
272
+ var AppShell = ({
273
+ title,
274
+ version,
275
+ dataDirectory,
276
+ logger,
277
+ logEventEmitter,
278
+ shutdownContext,
279
+ children
280
+ }) => {
281
+ const [logs, setLogs] = useState([]);
282
+ const lastLogIndex = logs[logs.length - 1]?.index ?? -1;
283
+ useEffect2(() => {
284
+ const listener = ({ logs: logs2 }) => setImmediate(() => setLogs(logs2));
285
+ logEventEmitter.addListener("logsUpdated", listener);
286
+ return () => {
287
+ logEventEmitter.removeListener("logsUpdated", listener);
288
+ };
289
+ }, [logEventEmitter]);
290
+ const system = useMemo(
291
+ () => createSystemInformation({ dataDirectory, version }),
292
+ [dataDirectory, version]
293
+ );
294
+ const appInformation = useMemo(
295
+ () => ({ version, title }),
296
+ [version, title]
297
+ );
298
+ return /* @__PURE__ */ jsx(ShutdownContext.Provider, { value: shutdownContext, children: /* @__PURE__ */ jsx(AppInformationContext.Provider, { value: appInformation, children: /* @__PURE__ */ jsx(LoggerContext.Provider, { value: { logger }, children: /* @__PURE__ */ jsx(
299
+ SIGIL_COMPONENTS.AppRoot,
300
+ {
301
+ lastLog: lastLogIndex,
302
+ system,
303
+ onGetLogs: async ({ after }) => {
304
+ return {
305
+ logs: logs.filter((log) => log.index > after)
306
+ };
307
+ },
308
+ children
309
+ }
310
+ ) }) }) });
311
+ };
312
+
313
+ // src/listener.tsx
314
+ import {
315
+ getNetworkInterfaces
316
+ } from "@arcanewizards/net-utils";
317
+ import isEqual from "lodash/isEqual";
318
+ import { useCallback, useEffect as useEffect3, useRef, useState as useState2 } from "react";
319
+ var connectionDescription = (listener) => {
320
+ return `${listener.host ?? "0.0.0.0"}:${listener.port}`;
321
+ };
322
+ var AppListenerManager = ({
323
+ appRegistration,
324
+ listenerConfig,
325
+ toolkit,
326
+ setWindowUrl
327
+ }) => {
328
+ const logger = useLogger();
329
+ const listenerStateRef = useRef({});
330
+ const [listenerState, setListenerState] = useState2(listenerStateRef.current);
331
+ const updateReactState = useCallback(() => {
332
+ setListenerState({ ...listenerStateRef.current });
333
+ }, []);
334
+ useEffect3(() => {
335
+ Object.entries(listenerStateRef.current).forEach(([key, state]) => {
336
+ if (!listenerConfig[key] || !isEqual(listenerConfig[key], state.config)) {
337
+ if (state.state === "connected") {
338
+ const delay = 500;
339
+ setTimeout(() => {
340
+ state.listener.close();
341
+ logger.info(`Closing listener: ${key}`);
342
+ }, delay);
343
+ logger.info(
344
+ `Will close listener ${key} on ${connectionDescription(state)} in ${delay}ms`
345
+ );
346
+ appRegistration?.removeConnection(key);
347
+ }
348
+ delete listenerStateRef.current[key];
349
+ }
350
+ });
351
+ getNetworkInterfaces().then(async (interfaces) => {
352
+ listenerLoop: for (const [key, config] of Object.entries(
353
+ listenerConfig
354
+ )) {
355
+ const basePortInformation = {
356
+ direction: "input",
357
+ target: config.interface ? {
358
+ type: "interface",
359
+ interface: config.interface
360
+ } : {
361
+ type: "host",
362
+ host: "0.0.0.0"
363
+ },
364
+ port: config.port
365
+ };
366
+ if (!listenerStateRef.current[key]) {
367
+ let host = void 0;
368
+ if (config.interface) {
369
+ const iface = interfaces[config.interface];
370
+ if (!iface) {
371
+ const error = new Error(
372
+ `Network interface ${config.interface} not found`
373
+ );
374
+ appRegistration?.setConnection(key, {
375
+ ...basePortInformation,
376
+ status: "error",
377
+ errors: [error.message]
378
+ });
379
+ logger.error(error);
380
+ listenerStateRef.current[key] = {
381
+ state: "error",
382
+ config,
383
+ error: error.message
384
+ };
385
+ continue listenerLoop;
386
+ }
387
+ host = iface.address;
388
+ }
389
+ listenerStateRef.current[key] = { state: "connecting", config };
390
+ const from = typeof config.port === "number" ? config.port : config.port.from;
391
+ const to = typeof config.port === "number" ? config.port : config.port.to;
392
+ portRange: for (let port = from; port <= to; port++) {
393
+ const resolvedConnectionDetails = {
394
+ config,
395
+ host,
396
+ port
397
+ };
398
+ try {
399
+ const listener = await toolkit.listen({
400
+ port,
401
+ host
402
+ });
403
+ if (!listenerStateRef.current[key]) {
404
+ listener.close();
405
+ } else {
406
+ listenerStateRef.current[key] = {
407
+ state: "connected",
408
+ listener,
409
+ ...resolvedConnectionDetails
410
+ };
411
+ appRegistration?.setConnection(key, {
412
+ ...basePortInformation,
413
+ port,
414
+ status: "active"
415
+ });
416
+ logger.info(
417
+ `App listener ${key} started on ${connectionDescription(resolvedConnectionDetails)}`
418
+ );
419
+ break portRange;
420
+ }
421
+ } catch (err) {
422
+ if (port === to) {
423
+ const error = new Error(
424
+ `Failed to start listener on ${connectionDescription(
425
+ resolvedConnectionDetails
426
+ )}${from !== to ? ` (for port range ${from}-${to}) latest error` : ""}`,
427
+ { cause: err }
428
+ );
429
+ listenerStateRef.current[key] = {
430
+ state: "error",
431
+ config,
432
+ error: `${error}`
433
+ };
434
+ appRegistration?.setConnection(key, {
435
+ ...basePortInformation,
436
+ status: "error",
437
+ errors: [error.message]
438
+ });
439
+ logger.error(error);
440
+ }
441
+ } finally {
442
+ updateReactState();
443
+ }
444
+ }
445
+ }
446
+ }
447
+ }).catch((err) => {
448
+ const error = new Error("Failed to get network interfaces:", {
449
+ cause: err
450
+ });
451
+ logger.error(error);
452
+ Object.entries(listenerConfig).forEach(([key, config]) => {
453
+ if (!listenerStateRef.current[key]) {
454
+ listenerStateRef.current[key] = {
455
+ state: "error",
456
+ config,
457
+ error: `Failed to get network interfaces: ${error}`
458
+ };
459
+ }
460
+ });
461
+ updateReactState();
462
+ });
463
+ updateReactState();
464
+ }, [appRegistration, listenerConfig, logger, toolkit, updateReactState]);
465
+ useEffect3(() => {
466
+ for (const state of Object.values(listenerState)) {
467
+ if (state.state === "connected") {
468
+ setWindowUrl(
469
+ new URL(`http://${state.host ?? "localhost"}:${state.port}/`)
470
+ );
471
+ return;
472
+ }
473
+ }
474
+ });
475
+ return null;
476
+ };
477
+ export {
478
+ AppInformationContext,
479
+ AppListenerManager,
480
+ AppRoot,
481
+ AppShell,
482
+ LoggerContext,
483
+ SIGIL_COMPONENTS,
484
+ SIGIL_NAMESPACE,
485
+ ShutdownContext,
486
+ createSystemInformation,
487
+ isSigilComponent,
488
+ isSigilComponentCall,
489
+ runSigilApp,
490
+ useLogger,
491
+ useShutdownHandler
492
+ };
@@ -0,0 +1,33 @@
1
+ import { BaseClientComponentCall, BaseComponentProto, AnyComponentProto } from '@arcanejs/protocol';
2
+ import { A as AppRootLogEntry, S as SystemInformation } from './types-X8O95zmC.cjs';
3
+
4
+ declare const SIGIL_NAMESPACE = "sigil";
5
+ type SigilNamespace = typeof SIGIL_NAMESPACE;
6
+ type SigilAppRootComponent = BaseComponentProto<SigilNamespace, 'app-root'> & {
7
+ child: AnyComponentProto | null;
8
+ /**
9
+ * Timestamp of last log entry.
10
+ * Used to trigger log polling when the frontend debugger is active.
11
+ */
12
+ lastLog: number;
13
+ system: SystemInformation;
14
+ };
15
+ type SigilComponent = SigilAppRootComponent;
16
+ declare const isSigilComponent: (component: AnyComponentProto) => component is SigilComponent;
17
+ type AppRootGetLogsArgs = {
18
+ after: number;
19
+ };
20
+ type AppRootGetLogsReturn = {
21
+ logs: AppRootLogEntry[];
22
+ };
23
+ type AppRootGetLogs = BaseClientComponentCall<SigilNamespace, 'app-root-get-logs'> & AppRootGetLogsArgs;
24
+ type SigilComponentCalls = {
25
+ 'app-root-get-logs': {
26
+ call: AppRootGetLogs;
27
+ return: AppRootGetLogsReturn;
28
+ };
29
+ };
30
+ type SigilComponentMessage = never;
31
+ declare const isSigilComponentCall: <A extends keyof SigilComponentCalls>(call: BaseClientComponentCall<string, string>, action: A) => call is SigilComponentCalls[A]["call"];
32
+
33
+ export { type AppRootGetLogs as A, type SigilAppRootComponent as S, type AppRootGetLogsArgs as a, type AppRootGetLogsReturn as b, SIGIL_NAMESPACE as c, type SigilComponent as d, type SigilComponentCalls as e, isSigilComponentCall as f, type SigilNamespace as g, type SigilComponentMessage as h, isSigilComponent as i };
@@ -0,0 +1,33 @@
1
+ import { BaseClientComponentCall, BaseComponentProto, AnyComponentProto } from '@arcanejs/protocol';
2
+ import { A as AppRootLogEntry, S as SystemInformation } from './types-X8O95zmC.js';
3
+
4
+ declare const SIGIL_NAMESPACE = "sigil";
5
+ type SigilNamespace = typeof SIGIL_NAMESPACE;
6
+ type SigilAppRootComponent = BaseComponentProto<SigilNamespace, 'app-root'> & {
7
+ child: AnyComponentProto | null;
8
+ /**
9
+ * Timestamp of last log entry.
10
+ * Used to trigger log polling when the frontend debugger is active.
11
+ */
12
+ lastLog: number;
13
+ system: SystemInformation;
14
+ };
15
+ type SigilComponent = SigilAppRootComponent;
16
+ declare const isSigilComponent: (component: AnyComponentProto) => component is SigilComponent;
17
+ type AppRootGetLogsArgs = {
18
+ after: number;
19
+ };
20
+ type AppRootGetLogsReturn = {
21
+ logs: AppRootLogEntry[];
22
+ };
23
+ type AppRootGetLogs = BaseClientComponentCall<SigilNamespace, 'app-root-get-logs'> & AppRootGetLogsArgs;
24
+ type SigilComponentCalls = {
25
+ 'app-root-get-logs': {
26
+ call: AppRootGetLogs;
27
+ return: AppRootGetLogsReturn;
28
+ };
29
+ };
30
+ type SigilComponentMessage = never;
31
+ declare const isSigilComponentCall: <A extends keyof SigilComponentCalls>(call: BaseClientComponentCall<string, string>, action: A) => call is SigilComponentCalls[A]["call"];
32
+
33
+ export { type AppRootGetLogs as A, type SigilAppRootComponent as S, type AppRootGetLogsArgs as a, type AppRootGetLogsReturn as b, SIGIL_NAMESPACE as c, type SigilComponent as d, type SigilComponentCalls as e, isSigilComponentCall as f, type SigilNamespace as g, type SigilComponentMessage as h, isSigilComponent as i };