plug-code 1.2.0 → 2.0.1

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 (49) hide show
  1. package/README.md +135 -94
  2. package/dist/core/helpers/core.d.ts +2 -0
  3. package/dist/core/helpers/core.js +32 -0
  4. package/dist/core/hooks/plcHooks.d.ts +15 -0
  5. package/dist/core/hooks/plcHooks.js +47 -0
  6. package/dist/core/plcAPI.d.ts +83 -0
  7. package/dist/core/plcAPI.js +472 -0
  8. package/dist/core/plcPipeline.d.ts +8 -0
  9. package/dist/core/plcPipeline.js +35 -0
  10. package/dist/core/plcScheduler.d.ts +7 -0
  11. package/dist/core/plcScheduler.js +22 -0
  12. package/dist/core/plcStore.d.ts +33 -0
  13. package/dist/core/plcStore.js +159 -0
  14. package/dist/core/ui/plcCore.d.ts +8 -0
  15. package/dist/core/ui/plcCore.js +40 -0
  16. package/dist/core/ui/plcErrorBoundary.d.ts +17 -0
  17. package/dist/core/ui/plcErrorBoundary.js +17 -0
  18. package/dist/core/ui/plcInspector.d.ts +5 -0
  19. package/dist/core/ui/plcInspector.js +27 -0
  20. package/dist/core/ui/plcLayout.d.ts +28 -0
  21. package/dist/core/ui/plcLayout.js +125 -0
  22. package/dist/index.d.ts +8 -0
  23. package/dist/index.js +8 -0
  24. package/dist/types/core/api.d.ts +7 -0
  25. package/dist/types/core/api.js +1 -0
  26. package/dist/types/core/general.d.ts +15 -0
  27. package/dist/types/core/general.js +1 -0
  28. package/dist/types/core/registry.d.ts +7 -0
  29. package/dist/types/core/registry.js +1 -0
  30. package/dist/types/core/ui.d.ts +7 -0
  31. package/dist/types/core/ui.js +1 -0
  32. package/dist/types/registry.d.ts +20 -0
  33. package/dist/types/registry.js +1 -0
  34. package/package.json +16 -22
  35. package/index.d.ts +0 -1
  36. package/src/contexts/pipeline.tsx +0 -4
  37. package/src/core/plcAPI.tsx +0 -393
  38. package/src/core/plcPipeline.tsx +0 -87
  39. package/src/core/plcStore.tsx +0 -94
  40. package/src/helpers/core.ts +0 -10
  41. package/src/plug-code.tsx +0 -64
  42. package/src/types/api.ts +0 -8
  43. package/src/types/features.ts +0 -7
  44. package/src/types/general.ts +0 -2
  45. package/src/types/pipeline.ts +0 -3
  46. package/src/types/registry.ts +0 -4
  47. package/src/types/store.ts +0 -2
  48. package/tsconfig.json +0 -15
  49. package/types/plug-code.d.ts +0 -164
@@ -1,393 +0,0 @@
1
- import { produce } from "immer";
2
- import type { ObjectType } from "../types/general";
3
- import { useEffect, useRef, useState } from "react";
4
- import { PlcPipeline } from "./plcPipeline";
5
- import type { PlcStore } from "./plcStore";
6
- import type { CommandFn, transformerType } from "../types/api";
7
-
8
- import type { ChannelRegistry, CommandRegistry, SlotRegistry } from "../types/registry";
9
- import { isEqual } from "../helpers/core";
10
-
11
- type ChannelKey = keyof ChannelRegistry | (string & {});
12
- type ChannelData<K> = K extends keyof ChannelRegistry ? ChannelRegistry[K] : any;
13
-
14
- type CommandKey = keyof CommandRegistry | (string & {});
15
- type CommandPayload<K> = K extends keyof CommandRegistry
16
- ? (CommandRegistry[K] extends { payload: infer P } ? P : any)
17
- : any;
18
- type CommandResult<K> = K extends keyof CommandRegistry
19
- ? (CommandRegistry[K] extends { result: infer R } ? R : any)
20
- : any;
21
-
22
- type SlotKey = keyof SlotRegistry | (string & {});
23
-
24
- export class PlcAPI<S extends ObjectType> {
25
- private store: PlcStore<S>
26
- private pipeline: PlcPipeline<S>
27
- private substores = new Map<string, any>()
28
-
29
- private transformers = new Map<string, transformerType[]>()
30
- private commands = new Map<string, CommandFn>();
31
-
32
- constructor(store: PlcStore<S>) {
33
- this.store = store
34
- this.pipeline = new PlcPipeline(store)
35
- }
36
-
37
- redraw(key: string): void {
38
- const currentData = this.substores.get(key);
39
- if (currentData === undefined) return;
40
-
41
- const dataRef = typeof currentData === 'object' && currentData !== null
42
- ? (Array.isArray(currentData) ? [...currentData] : { ...currentData })
43
- : currentData;
44
-
45
- this.substores.set(key, dataRef);
46
- this.store.set(key as any, dataRef);
47
- }
48
-
49
- watch<T>(
50
- storeKey: string,
51
- selector: (data: any) => T,
52
- callback: (newValue: T, oldValue: T) => void
53
- ): () => void {
54
- let previousValue = selector(this.getData(storeKey));
55
- const unsubscribe = this.store.subscribe(storeKey as any, () => {
56
- const currentData = this.getData(storeKey);
57
- const newValue = selector(currentData);
58
-
59
- if (newValue !== previousValue) {
60
- const old = previousValue;
61
- previousValue = newValue;
62
- callback(newValue, old);
63
- }
64
- });
65
-
66
- return unsubscribe;
67
- }
68
-
69
- override<K extends string>(key: K & "root", data: any, slot?: string) {
70
- this.substores.set(key, data);
71
- this.store.set(key as any, data);
72
-
73
- if (slot) {
74
- this.invalidate(slot);
75
- }
76
- }
77
-
78
- replace<K extends string>(key: K & "root", data: Partial<any>, slot?: string) {
79
- const currentSub = this.substores.get(key) || {};
80
- const newSub = { ...currentSub, ...data };
81
-
82
- this.substores.set(key, newSub);
83
- this.store.set(key as any, newSub);
84
-
85
- if (slot) {
86
- this.invalidate(slot);
87
- }
88
- }
89
-
90
- derive<K extends string>(
91
- outputKey: K,
92
- dependencies: string[],
93
- calculator: () => any
94
- ) {
95
- let lastValue: any
96
- let isComputing = false
97
-
98
- let scheduled = false
99
-
100
- const scheduleUpdate = () => {
101
- if (scheduled) return
102
- scheduled = true
103
-
104
- queueMicrotask(() => {
105
- scheduled = false
106
- runCompute()
107
- })
108
- }
109
-
110
- const runCompute = () => {
111
- if (isComputing) return
112
-
113
- isComputing = true
114
- try {
115
- const result = calculator()
116
- lastValue = result
117
- this.replace("root" as any, { [outputKey]: result })
118
- } finally {
119
- isComputing = false
120
- }
121
- }
122
-
123
-
124
- runCompute()
125
-
126
- dependencies.forEach(dep => {
127
- this.store.subscribe(dep as any, () => {
128
- if (isComputing) return
129
- scheduleUpdate()
130
- })
131
- })
132
-
133
- return () => lastValue
134
- }
135
-
136
- register(slot: SlotKey, node: (props?: any) => React.ReactNode): void;
137
- register<K extends string>(slot: SlotKey, node: (data: any, props?: any) => React.ReactNode, dependencyKey: K): void;
138
- register(slot: SlotKey, node: (arg1?: any, arg2?: any) => React.ReactNode, dependencyKey?: string) {
139
- if (dependencyKey) {
140
- const ConnectedWrapper = (props: any) => {
141
- const [storeData, setStoreData] = useState(() => this.substores.get(dependencyKey));
142
-
143
- useEffect(() => {
144
- const unsubscribe = this.store.subscribe(dependencyKey as any, () => {
145
- setStoreData(this.substores.get(dependencyKey));
146
- });
147
- return unsubscribe;
148
- }, []);
149
-
150
- return <>{node(storeData, props)}</>;
151
- };
152
-
153
- this.store.batch(() => {
154
- this.pipeline.register(slot as string, (p: any) => <ConnectedWrapper {...p} />);
155
- });
156
- }
157
- else {
158
- this.store.batch(() => {
159
- this.pipeline.register(slot as string, node);
160
- });
161
- }
162
- }
163
-
164
- scope<T = any>(key: string | "root"): {
165
- get: () => T;
166
- update: (updater: (draft: T) => void, slot?: string, triggerKey?: string) => void;
167
- connect: <P = {}, R = any>(
168
- selector: (data: T, props: P) => R
169
- ) => (WrappedComponent: React.ComponentType<P & R>) => React.FC<P>;
170
-
171
- render: (slotName: SlotKey) => React.FC;
172
- receive: (context?: any) => any;
173
- root: PlcAPI<S>;
174
- } {
175
- return {
176
- get: (): T => this.getData(key),
177
-
178
- update: (updater: (draft: T) => void, slot?: string, triggerKey?: string) => {
179
- this.update(key as any, updater, slot, triggerKey);
180
- },
181
-
182
- connect: <P = {}, R = any>(
183
- selector: (data: T, props: P) => R
184
- ) => {
185
- return this.connect(key, selector);
186
- },
187
-
188
- render: (slotName: SlotKey) => {
189
- const ScopedSlotRenderer = ({ _scopeData }: { _scopeData: T }) => {
190
- return <>{this.pipeline.render(slotName as string, _scopeData)}</>;
191
- };
192
-
193
- return this.connect(
194
- key,
195
- (data: T) => ({ _scopeData: data })
196
- )(ScopedSlotRenderer) as any;
197
- },
198
-
199
- receive: (context: any = {}) => {
200
- const currentData = this.getData(key);
201
- return this.receive(key as any, currentData, context);
202
- },
203
-
204
- root: this
205
- };
206
- }
207
-
208
- connect<State = any, OwnProps = {}, ResultProps = {}>(
209
- key: string,
210
- selector: (state: State, props: OwnProps) => ResultProps
211
- ): (WrappedComponent: React.ComponentType<OwnProps & ResultProps>) => React.FC<OwnProps> {
212
- return (WrappedComponent: React.ComponentType<OwnProps & ResultProps>) => {
213
-
214
- const ConnectedComponent: React.FC<OwnProps> = (props) => {
215
- const propsRef = useRef(props);
216
- propsRef.current = props;
217
-
218
- const [slice, setSlice] = useState<ResultProps>(() => {
219
- const data = this.substores.get(key);
220
- return selector(data, props);
221
- });
222
-
223
- useEffect(() => {
224
- const unsubscribe = this.store.subscribe(key as any, () => {
225
- const currentData = this.substores.get(key);
226
- const newSlice = selector(currentData, propsRef.current);
227
- setSlice(prev => {
228
- if (isEqual(prev, newSlice)) return prev;
229
- return newSlice;
230
- });
231
- });
232
- return unsubscribe;
233
- }, []);
234
-
235
- useEffect(() => {
236
- const currentData = this.substores.get(key);
237
- const newSlice = selector(currentData, props);
238
-
239
- setSlice(prev => {
240
- if (isEqual(prev, newSlice)) return prev;
241
- return newSlice;
242
- });
243
- }, [props]);
244
-
245
- if (slice === undefined && this.substores.get(key) === undefined) return null;
246
-
247
- return <WrappedComponent {...props} {...slice} />;
248
- };
249
-
250
- const displayName = WrappedComponent.displayName || WrappedComponent.name || 'Component';
251
- ConnectedComponent.displayName = `Connect(${displayName})`;
252
-
253
- return ConnectedComponent;
254
- };
255
- }
256
-
257
- wrap(slot: SlotKey, fn: (next: () => React.ReactNode) => () => React.ReactNode) {
258
- this.store.batch(() => {
259
- this.pipeline.wrap(slot as string, fn)
260
- })
261
- }
262
-
263
- after(slot: SlotKey, node: () => React.ReactNode) {
264
- this.store.batch(() => {
265
- this.pipeline.register(slot as string, node)
266
- })
267
- }
268
-
269
- render(slot: SlotKey, props?: any) {
270
- return this.pipeline.render(slot as string, props)
271
- }
272
-
273
- invalidate(slot?: SlotKey) {
274
- this.pipeline.invalidate(slot as string)
275
- }
276
-
277
- send<K extends ChannelKey>(
278
- channel: K,
279
- id: string,
280
- fn: (data: ChannelData<K>, context: any) => ChannelData<K>,
281
- priority: number = 0
282
- ) {
283
- const channelStr = channel as string;
284
- if (!this.transformers.has(channelStr)) {
285
- this.transformers.set(channelStr, []);
286
- }
287
-
288
- const channelList = this.transformers.get(channelStr)!;
289
-
290
- const existingIdx = channelList.findIndex(t => t.id === id);
291
- if (existingIdx >= 0) {
292
- channelList[existingIdx] = { id, priority, fn };
293
- } else {
294
- channelList.push({ id, priority, fn });
295
- }
296
-
297
- channelList.sort((a, b) => a.priority - b.priority);
298
- }
299
-
300
- receive<K extends ChannelKey>(
301
- channel: K,
302
- initialData: ChannelData<K>,
303
- context: any = {}
304
- ): ChannelData<K> {
305
- let currentData = initialData;
306
- const channelList = this.transformers.get(channel as string) || [];
307
-
308
- for (const transformer of channelList) {
309
- try {
310
- currentData = transformer.fn(currentData, context);
311
- } catch (error) {
312
- console.error(`[PlcAPI] Error in transform '${channel as string}/${transformer.id}':`, error);
313
- }
314
- }
315
-
316
- return currentData as ChannelData<K>;
317
- }
318
-
319
- registerCommand<K extends CommandKey>(
320
- id: K,
321
- fn: CommandFn<CommandPayload<K>, CommandResult<K>>
322
- ) {
323
- if (this.commands.has(id as string)) {
324
- console.warn(`[PlcAPI] Overwriting command '${id as string}'`);
325
- }
326
- this.commands.set(id as string, fn as any);
327
- }
328
-
329
- wrapCommand<K extends CommandKey>(
330
- id: K,
331
- wrapper: (next: CommandFn<CommandPayload<K>, CommandResult<K>>) => CommandFn<CommandPayload<K>, CommandResult<K>>
332
- ) {
333
- const currentFn = this.commands.get(id as string);
334
- if (!currentFn) {
335
- console.error(`[PlcAPI] Cannot wrap '${id as string}', command does not exist.`);
336
- return;
337
- }
338
- this.commands.set(id as string, wrapper(currentFn) as any);
339
- }
340
-
341
- async execute<K extends CommandKey>(
342
- id: K,
343
- payload?: CommandPayload<K>
344
- ): Promise<CommandResult<K>> {
345
- const fn = this.commands.get(id as string);
346
- if (!fn) {
347
- throw new Error(`[PlcAPI] Command '${id as string}' not found.`);
348
- }
349
-
350
- try {
351
- return await fn(payload);
352
- } catch (error) {
353
- console.error(`[PlcAPI] Error executing '${id as string}':`, error);
354
- throw error;
355
- }
356
- }
357
-
358
- getData(key: string): any {
359
- return this.substores.get(key)
360
- }
361
-
362
- subscribe(listener: () => void) {
363
- return this.store.subscribe(listener);
364
- }
365
-
366
- createData<K extends string, T>(key: K, initialState: T) {
367
- if (this.substores.has(key)) return
368
- this.substores.set(key, initialState)
369
- }
370
-
371
- update<K extends keyof S>(key: string & "root", updater: (draft: any) => void, slot?: string, triggerKey?: string) {
372
- const sub = this.substores.get(key)
373
- if (!sub) return
374
-
375
- const newSub = produce(sub, updater)
376
- this.substores.set(key, newSub)
377
-
378
- this.store.set(key as K, newSub as S[K])
379
- if (slot) {
380
- this.invalidate(slot)
381
- }
382
-
383
- if (triggerKey && triggerKey !== key) {
384
- const triggerData = this.substores.get(triggerKey);
385
-
386
- if (triggerData) {
387
- const newTriggerRef = { ...triggerData };
388
- this.substores.set(triggerKey, newTriggerRef);
389
- this.store.set(triggerKey as any, newTriggerRef);
390
- }
391
- }
392
- }
393
- }
@@ -1,87 +0,0 @@
1
- import React, { useContext } from "react";
2
- import { ScopeContext } from "../contexts/pipeline";
3
- import type { ObjectType } from "../types/general";
4
- import type { ScheduledSlot, Slot } from "../types/pipeline";
5
- import type { PlcStore } from "./plcStore";
6
-
7
- export class PlcPipeline<S extends ObjectType> {
8
- private slots = new Map<string, Slot[]>()
9
- private store: PlcStore<S>
10
- private cache = new Map<string, React.ReactNode[]>()
11
- private scheduleQueue: ScheduledSlot[] = []
12
-
13
- constructor(store: PlcStore<S>) {
14
- this.store = store
15
- }
16
-
17
- register(slot: string, fn: Slot, priority: number = 0) {
18
- if (!this.slots.has(slot)) this.slots.set(slot, [])
19
- this.slots.get(slot)!.push(fn)
20
-
21
- this.scheduleQueue.push({ slot, fn, priority })
22
- this.store.set(`slot:${slot}`, Math.random() as any)
23
- }
24
-
25
- wrap(slot: string, wrapper: (next: Slot) => Slot, priority: number = 0) {
26
- const current = this.slots.get(slot) || []
27
- this.slots.set(
28
- slot,
29
- current.map(fn => wrapper(fn))
30
- )
31
-
32
- current.forEach(fn => this.scheduleQueue.push({ slot, fn, priority }))
33
- this.store.set(`slot:${slot}`, Math.random() as any)
34
- }
35
-
36
- render(slot: string, contextData?: any) {
37
- if (this.scheduleQueue.length > 0) {
38
- this.scheduleQueue.sort((a, b) => b.priority - a.priority);
39
-
40
- const slotsToUpdate = new Set<string>();
41
- this.scheduleQueue.forEach(item => slotsToUpdate.add(item.slot));
42
-
43
- slotsToUpdate.forEach(slotName => {
44
- this.regenerateCache(slotName);
45
- });
46
-
47
- this.scheduleQueue = [];
48
- }
49
-
50
- if (!this.cache.has(slot) && this.slots.has(slot)) {
51
- this.regenerateCache(slot);
52
- }
53
-
54
- const content = this.cache.get(slot);
55
-
56
- if (contextData !== undefined) {
57
- return (
58
- <ScopeContext.Provider value={contextData}>
59
- {content}
60
- </ScopeContext.Provider>
61
- );
62
- }
63
-
64
- return content;
65
- }
66
-
67
- invalidate(slot?: string) {
68
- if (slot) {
69
- this.cache.delete(slot)
70
- } else {
71
- this.cache.clear()
72
- }
73
- }
74
-
75
- private regenerateCache(slot: string) {
76
- const nodes = this.slots.get(slot)?.map((fn, i) => {
77
- const SlotBridge = () => {
78
- const dynamicProps = useContext(ScopeContext);
79
- return <React.Fragment>{fn(dynamicProps)}</React.Fragment>;
80
- };
81
-
82
- return <SlotBridge key={i} />;
83
- }) || [];
84
-
85
- this.cache.set(slot, nodes);
86
- }
87
- }
@@ -1,94 +0,0 @@
1
- import { produce, type Draft } from "immer";
2
- import type { ObjectType } from "../types/general";
3
- import type { Listener } from "../types/store";
4
-
5
- export class PlcStore<S extends ObjectType> {
6
- private state: S;
7
- private listeners = new Set<Listener<S>>();
8
- private batchQueue = new Set<keyof S | undefined>();
9
- private debug: boolean;
10
-
11
- private isBatching = false
12
-
13
- constructor(initial: S, debug: boolean) {
14
- debug = false;
15
-
16
- this.state = initial;
17
- this.debug = debug;
18
- }
19
-
20
- get<K extends keyof S>(key: K): S[K] {
21
- return this.state[key]
22
- }
23
-
24
- getState(): S {
25
- return this.state
26
- }
27
-
28
- set<K extends keyof S>(key: K, value: S[K]) {
29
- if (this.state[key] === value) return
30
-
31
- const oldValue = this.state[key]
32
- this.state = produce(this.state, draft => {
33
- (draft as any)[key] = value
34
- })
35
-
36
- if (this.debug) {
37
- console.log(`[Store][set] ${String(key)}:`, { oldValue, newValue: value })
38
- }
39
-
40
-
41
- if (this.isBatching) {
42
- this.batchQueue.add(key)
43
- } else {
44
- this.emit(key)
45
- }
46
- }
47
-
48
- batch(updater: (draft: Draft<S>) => void) {
49
- this.isBatching = true
50
-
51
- const nextState = produce(this.state, draft => {
52
- updater(draft)
53
- })
54
-
55
- if (nextState === this.state) {
56
- this.isBatching = false
57
- return
58
- }
59
-
60
- this.state = nextState
61
- this.isBatching = false
62
-
63
- this.batchQueue.forEach(key => this.emit(key))
64
- this.batchQueue.clear()
65
- }
66
-
67
- subscribe(listener: () => void): () => void
68
- subscribe<K extends keyof S>(key: K, listener: () => void): () => void
69
- subscribe<K extends keyof S>(keyOrListener: K | (() => void), maybeListener?: () => void): () => void {
70
- let listenerObj: Listener<S>
71
-
72
- if (typeof keyOrListener === "function") {
73
- listenerObj = { callback: keyOrListener }
74
- } else {
75
- listenerObj = { key: keyOrListener, callback: maybeListener! }
76
- }
77
-
78
- this.listeners.add(listenerObj)
79
- return () => {
80
- this.listeners.delete(listenerObj)
81
- }
82
- }
83
-
84
- private emit(changedKey?: keyof S) {
85
- this.listeners.forEach(l => {
86
- if (!l.key || l.key === changedKey) {
87
- if (this.debug) {
88
- console.log(`[Store][emit] key: ${String(changedKey)}`, l)
89
- }
90
- l.callback()
91
- }
92
- })
93
- }
94
- }
@@ -1,10 +0,0 @@
1
- export const isEqual = (a: any, b: any) => {
2
- if (a === b) return true;
3
- if (typeof a === 'object' && a !== null && typeof b === 'object' && b !== null) {
4
- const keysA = Object.keys(a);
5
- const keysB = Object.keys(b);
6
- if (keysA.length !== keysB.length) return false;
7
- return keysA.every(k => a[k] === b[k]);
8
- }
9
- return false;
10
- }
package/src/plug-code.tsx DELETED
@@ -1,64 +0,0 @@
1
- import { enableMapSet } from "immer";
2
- import type { ObjectType } from "./types/general";
3
- import { PlcAPI } from "./core/plcAPI";
4
- import { useEffect, useMemo, useState } from "react";
5
- import { PlcStore } from "./core/plcStore";
6
-
7
- enableMapSet();
8
-
9
- export function createPlugAndCode<S extends ObjectType>(
10
- setupSystem: (api: PlcAPI<S>) => void
11
- ) {
12
- const FeatureHost = ({ api, children }: { api: PlcAPI<any>, children?: React.ReactNode }) => (
13
- <>
14
- {api.render("root")}
15
- {children}
16
- </>
17
- )
18
-
19
- function SystemPlcRoot({ api, children }: { api: PlcAPI<any>, children?: React.ReactNode }) {
20
- if (!api) return null;
21
- return (
22
- <FeatureHost api={api}>
23
- {children}
24
- </FeatureHost>
25
- )
26
- }
27
-
28
- function useSystemPlc<T extends object>(initialProps: T) {
29
-
30
- const api = useMemo(() => {
31
- const store = new PlcStore({}, true);
32
- const api = new PlcAPI(store);
33
-
34
- api.createData("root", initialProps);
35
-
36
- setupSystem(api as unknown as PlcAPI<S>);
37
-
38
- return api;
39
- }, []);
40
-
41
- useEffect(() => {
42
- api.override("root", initialProps)
43
- }, [initialProps, api]);
44
-
45
- const useSelector = <Result,>(selector: (state: any) => Result): Result => {
46
- const [snap, setSnap] = useState(() => selector(api.getData("root")));
47
-
48
- useEffect(() => {
49
- return api.subscribe(() => {
50
- const fullState = api.getData("root");
51
- setSnap(selector(fullState));
52
- });
53
- }, [selector]);
54
-
55
- return snap;
56
- }
57
-
58
- return {
59
- api,
60
- useSelector
61
- }
62
- }
63
- return { useSystemPlc, SystemPlcRoot }
64
- }
package/src/types/api.ts DELETED
@@ -1,8 +0,0 @@
1
-
2
- export type transformerType = {
3
- id: string,
4
- priority: number,
5
- fn: (data: any, context: any) => any
6
- }
7
-
8
- export type CommandFn<T = any, R = any> = (payload: T) => Promise<R> | R;
@@ -1,7 +0,0 @@
1
- import type { PlcAPI } from "../core/plcAPI"
2
- import type { ObjectType } from "./general"
3
-
4
- export type FeatureType<S extends ObjectType> = {
5
- name: string
6
- setup?: (api: PlcAPI<S>) => void | (() => void),
7
- }
@@ -1,2 +0,0 @@
1
-
2
- export type ObjectType = Record<string, any>;
@@ -1,3 +0,0 @@
1
-
2
- export type Slot = (props?: any) => React.ReactNode
3
- export type ScheduledSlot = { slot: string, fn: Slot, priority: number }
@@ -1,4 +0,0 @@
1
-
2
- export interface ChannelRegistry {}
3
- export interface CommandRegistry {}
4
- export interface SlotRegistry {}
@@ -1,2 +0,0 @@
1
-
2
- export type Listener<S> = { key?: keyof S; callback: () => void }