plug-code 1.1.14 β 1.1.15
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/README.md +83 -102
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,171 +1,152 @@
|
|
|
1
|
-
# Plug&Code
|
|
1
|
+
# π Plug&Code
|
|
2
2
|
|
|
3
|
-
**Plug&Code** is a multipurpose React framework designed for **scalability, reusability, and modular organization**.
|
|
3
|
+
**Plug&Code** is a multipurpose React framework designed for **scalability, reusability, and modular organization**.
|
|
4
|
+
It empowers developers to build complex applications by **plugging in independent feature modules** without tightly coupling the codebase.
|
|
4
5
|
|
|
5
|
-
> **License
|
|
6
|
+
> **License**
|
|
7
|
+
> You may use Plug&Code in personal or commercial projects.
|
|
8
|
+
> **Modification or redistribution of the framework source code is prohibited** without explicit permission.
|
|
6
9
|
|
|
7
10
|
---
|
|
8
11
|
|
|
9
12
|
## π¦ Installation
|
|
10
13
|
|
|
11
|
-
Install the framework via npm or yarn:
|
|
12
|
-
|
|
13
14
|
```bash
|
|
14
15
|
npm install plug-code
|
|
15
16
|
# or
|
|
16
17
|
yarn add plug-code
|
|
17
|
-
|
|
18
|
-
Plug&Code is built around the PLC (Pipeline-Logic-Command) pattern combined with a specialized Reactive State Machine:
|
|
18
|
+
```
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
---
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
## π§ Core Concepts
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
Plug&Code is built around the **PLC (PipelineβLogicβCommand)** pattern combined with a specialized **Reactive State Machine**.
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
| Concept | Description |
|
|
27
|
+
| ----------------------- | -------------------------------------------------------- |
|
|
28
|
+
| **Features** | Independent modules that encapsulate logic, UI, and data |
|
|
29
|
+
| **Stores (State)** | Isolated substores with reactive linking |
|
|
30
|
+
| **Slots (UI Pipeline)** | Injection points for UI from any feature |
|
|
31
|
+
| **Commands (Logic)** | Executable business actions with middleware |
|
|
32
|
+
| **Transforms (Data)** | Data pipelines modified by multiple features |
|
|
27
33
|
|
|
28
|
-
|
|
34
|
+
---
|
|
29
35
|
|
|
30
|
-
π Quick Start
|
|
31
|
-
1. Create a Feature Module
|
|
32
|
-
Define features in separate files. A feature is simply a function that receives the api.
|
|
36
|
+
## π Quick Start
|
|
33
37
|
|
|
34
|
-
|
|
38
|
+
### 1οΈβ£ Create a Feature Module
|
|
35
39
|
|
|
40
|
+
```ts
|
|
36
41
|
// features/PaginationFeature.ts
|
|
37
42
|
import type { PlcAPI } from 'plug-code';
|
|
38
43
|
|
|
39
44
|
export const PaginationFeature = (api: PlcAPI<any>) => {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
// Use the extended update to modify data
|
|
53
|
-
const goNext = () => api.update(
|
|
54
|
-
"pagination", // Store to update
|
|
55
|
-
d => { d.currentPage++ } // Updater (Immer draft)
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
return <button onClick={goNext}>Page {currentPage}</button>;
|
|
59
|
-
}, "pagination");
|
|
45
|
+
api.createData("pagination", { currentPage: 1, pageSize: 10, total: 0 });
|
|
46
|
+
|
|
47
|
+
api.derive("activePage", ["pagination"], () => api.getData("pagination"));
|
|
48
|
+
|
|
49
|
+
api.register("table-footer", (pageData) => {
|
|
50
|
+
const { currentPage } = pageData;
|
|
51
|
+
|
|
52
|
+
const goNext = () => api.update("pagination", d => { d.currentPage++ });
|
|
53
|
+
|
|
54
|
+
return <button onClick={goNext}>Page {currentPage}</button>;
|
|
55
|
+
}, "pagination");
|
|
60
56
|
};
|
|
61
|
-
|
|
62
|
-
Import your feature functions and inject them into the system.
|
|
57
|
+
```
|
|
63
58
|
|
|
64
|
-
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
### 2οΈβ£ Initialize the System
|
|
65
62
|
|
|
63
|
+
```ts
|
|
66
64
|
// system.ts
|
|
67
65
|
import { createPlugAndCode } from 'plug-code';
|
|
68
66
|
import { PaginationFeature } from './features/PaginationFeature';
|
|
69
67
|
import { SalesFeature } from './features/SalesFeature';
|
|
70
68
|
|
|
71
69
|
export const { useSystemPlc, SystemPlcRoot } = createPlugAndCode((api) => {
|
|
72
|
-
|
|
73
|
-
api.createData("root", { appName: "My Dashboard", theme: "dark" });
|
|
70
|
+
api.createData("root", { appName: "My Dashboard", theme: "dark" });
|
|
74
71
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
SalesFeature(api);
|
|
72
|
+
PaginationFeature(api);
|
|
73
|
+
SalesFeature(api);
|
|
78
74
|
});
|
|
79
|
-
|
|
80
|
-
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
81
78
|
|
|
82
|
-
|
|
79
|
+
### 3οΈβ£ Wrap Your Application
|
|
83
80
|
|
|
81
|
+
```tsx
|
|
84
82
|
// App.tsx
|
|
85
83
|
import { useSystemPlc, SystemPlcRoot } from './system';
|
|
86
84
|
|
|
87
85
|
function App() {
|
|
88
|
-
// Initialize system with props (synced to "root" store automatically)
|
|
89
86
|
const { api, useSelector } = useSystemPlc({ mode: "production" });
|
|
90
87
|
|
|
91
88
|
return (
|
|
92
89
|
<SystemPlcRoot api={api}>
|
|
93
90
|
<main>
|
|
94
91
|
<h1>Welcome to {useSelector(s => s.root.appName)}</h1>
|
|
95
|
-
|
|
96
|
-
{/* Render slots: The pipeline assembles all registered components */}
|
|
97
92
|
<div className="footer-area">
|
|
98
|
-
|
|
93
|
+
{api.render("table-footer")}
|
|
99
94
|
</div>
|
|
100
95
|
</main>
|
|
101
96
|
</SystemPlcRoot>
|
|
102
97
|
);
|
|
103
98
|
}
|
|
104
|
-
|
|
105
|
-
State Management & Reactivity
|
|
106
|
-
The framework uses an isolated store architecture with reactive capabilities using Immer.
|
|
107
|
-
|
|
108
|
-
api.createData(key, initialData)
|
|
109
|
-
Initializes a new substore.
|
|
110
|
-
|
|
111
|
-
key: Unique identifier (e.g., "pagination").
|
|
99
|
+
```
|
|
112
100
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
api.getData(key)
|
|
116
|
-
Imperatively retrieves the current snapshot of a store.
|
|
117
|
-
|
|
118
|
-
api.update(key, updater, [slot], [triggerKey])
|
|
119
|
-
Updates the state using Immer-powered drafts.
|
|
120
|
-
|
|
121
|
-
key: The store to update.
|
|
122
|
-
|
|
123
|
-
updater: (draft) => void. Mutate the draft directly.
|
|
124
|
-
|
|
125
|
-
slot (Optional): Name of the UI slot to invalidate (clears visual cache).
|
|
126
|
-
|
|
127
|
-
triggerKey (Optional): Name of another store to force-update (useful for manual dependency triggering without derive).
|
|
128
|
-
|
|
129
|
-
api.derive(targetKey, dependencies, calculator)
|
|
130
|
-
Creates a reactive link. When dependencies change, the target is recalculated automatically.
|
|
131
|
-
|
|
132
|
-
targetKey: Where to save the result.
|
|
101
|
+
---
|
|
133
102
|
|
|
134
|
-
|
|
103
|
+
## π API Reference
|
|
135
104
|
|
|
136
|
-
|
|
137
|
-
Listens for changes to perform side effects (logging, analytics, etc.).
|
|
105
|
+
### 𧬠State & Reactivity
|
|
138
106
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
107
|
+
| Method | Description |
|
|
108
|
+
| --------------------------------------- | ------------------------ |
|
|
109
|
+
| `createData(key, initial)` | Create a new store |
|
|
110
|
+
| `getData(key)` | Get snapshot of store |
|
|
111
|
+
| `update(key, updater, slot?, trigger?)` | Mutate store using Immer |
|
|
112
|
+
| `derive(target, deps, calc)` | Create reactive linkage |
|
|
113
|
+
| `watch(key, selector, cb)` | Listen to store changes |
|
|
142
114
|
|
|
143
|
-
|
|
115
|
+
---
|
|
144
116
|
|
|
145
|
-
|
|
117
|
+
### π¨ UI Slots
|
|
146
118
|
|
|
147
|
-
|
|
119
|
+
| Method | Description |
|
|
120
|
+
| ------------------------------------ | -------------------- |
|
|
121
|
+
| `register(slot, component, depKey?)` | Attach UI to slot |
|
|
122
|
+
| `render(slot, props?)` | Render slot pipeline |
|
|
148
123
|
|
|
149
|
-
|
|
150
|
-
Renders the pipeline for the given slot name.
|
|
124
|
+
---
|
|
151
125
|
|
|
152
|
-
Business Logic (Commands)
|
|
153
|
-
api.registerCommand(id, fn): Registers an executable action.
|
|
126
|
+
### π§ Business Logic (Commands)
|
|
154
127
|
|
|
155
|
-
|
|
128
|
+
| Method | Description |
|
|
129
|
+
| ----------------------------- | ----------------- |
|
|
130
|
+
| `registerCommand(id, fn)` | Register action |
|
|
131
|
+
| `execute(id, payload)` | Run command |
|
|
132
|
+
| `wrapCommand(id, middleware)` | Intercept command |
|
|
156
133
|
|
|
157
|
-
|
|
134
|
+
---
|
|
158
135
|
|
|
159
|
-
Data
|
|
160
|
-
api.send(channel, id, fn, priority): Adds a transformation step to a data pipeline.
|
|
136
|
+
### π Data Transforms
|
|
161
137
|
|
|
162
|
-
|
|
138
|
+
| Method | Description |
|
|
139
|
+
| --------------------------------- | ------------- |
|
|
140
|
+
| `send(channel, id, fn, priority)` | Add transform |
|
|
141
|
+
| `receive(channel, data)` | Run pipeline |
|
|
163
142
|
|
|
164
|
-
|
|
165
|
-
Independent Files: Keep each feature in its own file (e.g., AuthFeature.ts, TableFeature.ts).
|
|
143
|
+
---
|
|
166
144
|
|
|
167
|
-
|
|
145
|
+
## π Best Practices
|
|
168
146
|
|
|
169
|
-
|
|
147
|
+
* Keep **one feature per file**
|
|
148
|
+
* Prefer `derive` over manual syncing
|
|
149
|
+
* Always specify `dependencyKey` in `register`
|
|
150
|
+
* Avoid putting everything in `root` β create focused stores
|
|
170
151
|
|
|
171
|
-
|
|
152
|
+
---
|