@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.
- package/dist/chunk-4PMRDURG.js +66 -0
- package/dist/chunk-5DRI7C4U.cjs +66 -0
- package/dist/chunk-A5LYYZER.cjs +103 -0
- package/dist/chunk-BIY5HAXP.js +125 -0
- package/dist/chunk-CAYKPJIX.cjs +10 -0
- package/dist/chunk-EJNNLQ2S.js +72 -0
- package/dist/chunk-FHXT3DAL.js +103 -0
- package/dist/chunk-H4U4Z4GM.js +66 -0
- package/dist/chunk-LSHKAVON.js +10 -0
- package/dist/chunk-MXDDIFIO.cjs +767 -0
- package/dist/chunk-PEARNJ5G.cjs +125 -0
- package/dist/chunk-RI33QVOD.cjs +66 -0
- package/dist/chunk-VZ4A6RRT.cjs +72 -0
- package/dist/chunk-XAK7WC3D.js +767 -0
- package/dist/frontend/appearance.cjs +88 -0
- package/dist/frontend/appearance.d.cts +11 -0
- package/dist/frontend/appearance.d.ts +11 -0
- package/dist/frontend/appearance.js +88 -0
- package/dist/frontend/context.cjs +16 -0
- package/dist/frontend/context.d.cts +32 -0
- package/dist/frontend/context.d.ts +32 -0
- package/dist/frontend/context.js +16 -0
- package/dist/frontend/controls/index.cjs +49 -0
- package/dist/frontend/controls/index.d.cts +168 -0
- package/dist/frontend/controls/index.d.ts +168 -0
- package/dist/frontend/controls/index.js +49 -0
- package/dist/frontend/dialogs.cjs +17 -0
- package/dist/frontend/dialogs.d.cts +36 -0
- package/dist/frontend/dialogs.d.ts +36 -0
- package/dist/frontend/dialogs.js +17 -0
- package/dist/frontend/input.cjs +8 -0
- package/dist/frontend/input.d.cts +33 -0
- package/dist/frontend/input.d.ts +33 -0
- package/dist/frontend/input.js +8 -0
- package/dist/frontend/preferences.cjs +54 -0
- package/dist/frontend/preferences.d.cts +14 -0
- package/dist/frontend/preferences.d.ts +14 -0
- package/dist/frontend/preferences.js +54 -0
- package/dist/frontend/styles/base.css +321 -0
- package/dist/frontend/styles/sigil.css +785 -0
- package/dist/frontend/styles/theme.css +625 -0
- package/dist/frontend/styling.cjs +18 -0
- package/dist/frontend/styling.d.cts +32 -0
- package/dist/frontend/styling.d.ts +32 -0
- package/dist/frontend/styling.js +18 -0
- package/dist/frontend/toolbars.cjs +18 -0
- package/dist/frontend/toolbars.d.cts +11 -0
- package/dist/frontend/toolbars.d.ts +11 -0
- package/dist/frontend/toolbars.js +18 -0
- package/dist/frontend/tooltip.cjs +10 -0
- package/dist/frontend/tooltip.d.cts +16 -0
- package/dist/frontend/tooltip.d.ts +16 -0
- package/dist/frontend/tooltip.js +10 -0
- package/dist/frontend.cjs +359 -0
- package/dist/frontend.d.cts +90 -0
- package/dist/frontend.d.ts +90 -0
- package/dist/frontend.js +359 -0
- package/dist/index.cjs +492 -0
- package/dist/index.d.cts +134 -0
- package/dist/index.d.ts +134 -0
- package/dist/index.js +492 -0
- package/dist/proto-B-WcMUOE.d.cts +33 -0
- package/dist/proto-kGDF-yWB.d.ts +33 -0
- package/dist/types-X8O95zmC.d.cts +23 -0
- package/dist/types-X8O95zmC.d.ts +23 -0
- package/package.json +123 -0
package/dist/index.d.ts
ADDED
|
@@ -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 };
|