c0ckp1t 1.0.10 → 1.0.12
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/Config.mjs +248 -0
- package/README.md +4 -1
- package/components/code-mirror.vue +23 -8
- package/components/tools.sh +9 -0
- package/components/xmarkdown.vue +1 -1
- package/core/CoreUtils.mjs +103 -35
- package/core/GlobalStore.mjs +18 -10
- package/core/Island.mjs +15 -3
- package/core/IslandDefault.mjs +1 -1
- package/core/PageMain.vue +15 -10
- package/core/img/logo_v2.svg +3 -3
- package/core/nodes/_api.vue +1 -1
- package/core/nodes/place-holder.vue +6 -15
- package/core/notify/toast.vue +1 -1
- package/core/pages/frontend/ComponentsAdv.vue +0 -2
- package/core/sfc/info-api.vue +2 -2
- package/docs/Issues.md +13 -0
- package/index.html +9 -6
- package/package.json +2 -1
- package/CdnConfig.mjs +0 -177
- package/DefaultConfig.mjs +0 -177
package/Config.mjs
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import {deepMerge, DEFAULTS} from "CoreUtils";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration Factory for C0ckp1t Applications
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* import { createConfig } from './Config.mjs';
|
|
7
|
+
*
|
|
8
|
+
* // Local mode (all defaults)
|
|
9
|
+
* const config = createConfig();
|
|
10
|
+
*
|
|
11
|
+
* // CDN mode
|
|
12
|
+
* const config = createConfig({
|
|
13
|
+
* appEndpoint: "https://cdn.jsdelivr.net/npm/c0ckp1t@latest"
|
|
14
|
+
* });
|
|
15
|
+
*
|
|
16
|
+
* // Custom instance
|
|
17
|
+
* const config = createConfig({
|
|
18
|
+
* instanceId: "myapp",
|
|
19
|
+
* appName: "My App",
|
|
20
|
+
* isDev: false,
|
|
21
|
+
* });
|
|
22
|
+
*/
|
|
23
|
+
// ________________________________________________________________________________
|
|
24
|
+
// Default Nav Tree Builder
|
|
25
|
+
// ________________________________________________________________________________
|
|
26
|
+
function buildNavTree(instanceId) {
|
|
27
|
+
return {
|
|
28
|
+
icon: "fa-house",
|
|
29
|
+
depth: 0,
|
|
30
|
+
endpoint: "/",
|
|
31
|
+
isLeaf: false,
|
|
32
|
+
isRoot: true,
|
|
33
|
+
name: "",
|
|
34
|
+
path: [],
|
|
35
|
+
children: [
|
|
36
|
+
{
|
|
37
|
+
depth: 1,
|
|
38
|
+
endpoint: `/${instanceId}/connections`,
|
|
39
|
+
isLeaf: true,
|
|
40
|
+
isRoot: false,
|
|
41
|
+
path: ["connections"],
|
|
42
|
+
name: "Connections",
|
|
43
|
+
children: []
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
depth: 1,
|
|
47
|
+
endpoint: `/${instanceId}/cache`,
|
|
48
|
+
isLeaf: true,
|
|
49
|
+
isRoot: false,
|
|
50
|
+
path: ["cache"],
|
|
51
|
+
name: "Cache",
|
|
52
|
+
children: []
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
icon: "fa-network-wired",
|
|
56
|
+
depth: 1,
|
|
57
|
+
endpoint: `/${instanceId}/traffic`,
|
|
58
|
+
isLeaf: true,
|
|
59
|
+
isRoot: false,
|
|
60
|
+
path: ["traffic"],
|
|
61
|
+
name: "Traffic",
|
|
62
|
+
children: []
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
icon: "fa-bell",
|
|
66
|
+
depth: 1,
|
|
67
|
+
endpoint: `/${instanceId}/notifies`,
|
|
68
|
+
isLeaf: true,
|
|
69
|
+
isRoot: false,
|
|
70
|
+
path: ["notifies"],
|
|
71
|
+
name: "Notifies",
|
|
72
|
+
children: []
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
icon: "fa-info",
|
|
76
|
+
depth: 1,
|
|
77
|
+
endpoint: `/${instanceId}/docs`,
|
|
78
|
+
isLeaf: true,
|
|
79
|
+
isRoot: false,
|
|
80
|
+
path: ["docs"],
|
|
81
|
+
name: "Documentation",
|
|
82
|
+
children: []
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
icon: "fa-info",
|
|
86
|
+
depth: 1,
|
|
87
|
+
endpoint: `/${instanceId}/components`,
|
|
88
|
+
isLeaf: true,
|
|
89
|
+
isRoot: false,
|
|
90
|
+
path: ["components"],
|
|
91
|
+
name: "Components",
|
|
92
|
+
children: [
|
|
93
|
+
{
|
|
94
|
+
icon: "fa-info",
|
|
95
|
+
depth: 2,
|
|
96
|
+
endpoint: `/${instanceId}/components/bootstrap`,
|
|
97
|
+
isLeaf: true,
|
|
98
|
+
isRoot: false,
|
|
99
|
+
path: ["bootstrap"],
|
|
100
|
+
name: "Bootstrap",
|
|
101
|
+
children: []
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
icon: "fa-info",
|
|
105
|
+
depth: 2,
|
|
106
|
+
endpoint: `/${instanceId}/components/basic`,
|
|
107
|
+
isLeaf: true,
|
|
108
|
+
isRoot: false,
|
|
109
|
+
path: ["basic"],
|
|
110
|
+
name: "Basic",
|
|
111
|
+
children: []
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
icon: "fa-info",
|
|
115
|
+
depth: 2,
|
|
116
|
+
endpoint: `/${instanceId}/components/advanced`,
|
|
117
|
+
isLeaf: true,
|
|
118
|
+
isRoot: false,
|
|
119
|
+
path: ["advanced"],
|
|
120
|
+
name: "Advanced",
|
|
121
|
+
children: []
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
icon: "fa-info",
|
|
125
|
+
depth: 2,
|
|
126
|
+
endpoint: `/${instanceId}/components/theme`,
|
|
127
|
+
isLeaf: true,
|
|
128
|
+
isRoot: false,
|
|
129
|
+
path: ["theme"],
|
|
130
|
+
name: "Theme",
|
|
131
|
+
children: []
|
|
132
|
+
},
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
]
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ________________________________________________________________________________
|
|
140
|
+
// Routes Builder
|
|
141
|
+
// ________________________________________________________________________________
|
|
142
|
+
function buildRoutes(instanceId = "default", prefix = "") {
|
|
143
|
+
return [
|
|
144
|
+
{ path: '/', name: 'root', children: [
|
|
145
|
+
{path: '', redirect: `/${instanceId}/docs/Introduction.md`},
|
|
146
|
+
{path: `${instanceId}`, children: [
|
|
147
|
+
{path: 'docs', redirect: `/${instanceId}/docs/Introduction.md`},
|
|
148
|
+
{path: 'docs/:pathMatch(.*)*', location: `${prefix}/core/pages/Documentation.vue`},
|
|
149
|
+
{path: 'connections', location: `${prefix}/core/pages/Connections.vue`},
|
|
150
|
+
{path: 'connections/:id', location: `${prefix}/core/pages/Connection.vue`},
|
|
151
|
+
{path: 'cache', location: `${prefix}/core/pages/Cache.vue`},
|
|
152
|
+
{path: 'traffic', location: `${prefix}/core/pages/Traffic.vue`},
|
|
153
|
+
{path: 'notifies', location: `${prefix}/core/pages/Notifies.vue`},
|
|
154
|
+
{path: 'components', location: `${prefix}/core/pages/frontend/Components.vue`, children: [
|
|
155
|
+
{path: 'basic', location: `${prefix}/core/pages/frontend/ComponentsBasic.vue`},
|
|
156
|
+
{path: 'advanced', location: `${prefix}/core/pages/frontend/ComponentsAdv.vue`},
|
|
157
|
+
{path: 'theme', location: `${prefix}/core/pages/frontend/Theme.vue`},
|
|
158
|
+
{path: 'bootstrap', location: `${prefix}/core/pages/frontend/Bootstrap.vue`},
|
|
159
|
+
]},
|
|
160
|
+
]}
|
|
161
|
+
] },
|
|
162
|
+
{ path: '/:pathMatch(.*)*', name: '404', location: `${prefix}/core/Page404.vue` }
|
|
163
|
+
];
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// ________________________________________________________________________________
|
|
167
|
+
// Components
|
|
168
|
+
// ________________________________________________________________________________
|
|
169
|
+
/**
|
|
170
|
+
* Return the default Vue components
|
|
171
|
+
* using sha1 hashes
|
|
172
|
+
* @returns {Object}
|
|
173
|
+
*/
|
|
174
|
+
export function defaultVueComponents(prefix = "") {
|
|
175
|
+
return {
|
|
176
|
+
ExecButton: { path: `${prefix}/components/ExecButton.vue`, hash: `97e3d2ce89808c5a69f41404e1337f743015f0cc` },
|
|
177
|
+
XInput: { path: `${prefix}/components/xinput.vue`, hash: `cd47d7d038316367df6fd7e265aa3625b72a7777` },
|
|
178
|
+
XInput2: { path: `${prefix}/components/xinput2.vue`, hash: `320e52ac991baebded7c2a9f52a4cfc2cde47b55` },
|
|
179
|
+
XLabel: { path: `${prefix}/components/xlabel.vue`, hash: `90a9837aa8e06f1d3a5b7601337afd78a872d181` },
|
|
180
|
+
XDropdown: { path: `${prefix}/components/xdropdown.vue`, hash: `52b29b72fd6512eefccd9caa76e26dd91d9f9f9e` },
|
|
181
|
+
XDropdown2: { path: `${prefix}/components/xdropdown2.vue`, hash: `e7b163eda42fb7e1a6f07b011c423f8f275eb65d` },
|
|
182
|
+
XSection: { path: `${prefix}/components/xsection.vue`, hash: `27285d606f57d13f80156bb11cd34449f88df950` },
|
|
183
|
+
XTableOpen: { path: `${prefix}/components/xtable-open.vue`, hash: `a1b9a4f670817978022a4c596e2e2f89dd4568c2` },
|
|
184
|
+
XCollapse: { path: `${prefix}/components/xcollapse.vue`, hash: `ba1479bd1080a4fa5abdf6c91c7328ae679f78e6` },
|
|
185
|
+
XToggle: { path: `${prefix}/components/xtoggle.vue`, hash: `2f6871d2d3069ac8f35b6bf76de6c2109f42d9d1` },
|
|
186
|
+
XToggle3: { path: `${prefix}/components/xtoggle3.vue`, hash: `61d0464e6ed9983e817eb0cde928dceb7c0fdc75` },
|
|
187
|
+
XCheck: { path: `${prefix}/components/xcheck.vue`, hash: `ee0d6b30600fb41589123f6d66f2791f1332d4f7` },
|
|
188
|
+
XCheckbox: { path: `${prefix}/components/xcheckbox.vue`, hash: `a290c0cbb7bffce83c235dd5a1c98ed9c441a5b0` },
|
|
189
|
+
XTextarea: { path: `${prefix}/components/xtextarea.vue`, hash: `f8bb08419082aa5443630ab07172674b50c7a248` },
|
|
190
|
+
XHidden: { path: `${prefix}/components/xhidden.vue`, hash: `ecb396e12dd894040e715c0854275e4d5016fcb9` },
|
|
191
|
+
XCode: { path: `${prefix}/components/xcode.vue`, hash: `4d9d9165fea0539c9a983fcdffae8dedcfd537ae` },
|
|
192
|
+
XButton: { path: `${prefix}/components/xbutton.vue`, hash: `2e956caa47e46377ea5a809f7438d0fc38be73b9` },
|
|
193
|
+
XTabs: { path: `${prefix}/components/xtabs.vue`, hash: `83dc219106bdc86ae86dcd16cf95ebd7f11bc952` },
|
|
194
|
+
XKv: { path: `${prefix}/components/xkv.vue`, hash: `8951d3a5e3786cfc9c705b13c1f71e3f90dd2552` },
|
|
195
|
+
XNav: { path: `${prefix}/components/xnav.vue`, hash: `8d51c73e5716deed3577652e362c50526ddbe4e1` },
|
|
196
|
+
XMap: { path: `${prefix}/components/xmap.vue`, hash: `daee357d9e2ef96df0166dd7add0339d46a1cc01` },
|
|
197
|
+
XList: { path: `${prefix}/components/xlist.vue`, hash: `217ced04a333238d169c300a721b75f0ddd5e95b` },
|
|
198
|
+
XJson: { path: `${prefix}/components/xjson.vue`, hash: `0a3ef6265b4070b0f002d659776c02756cc1da5a` },
|
|
199
|
+
XCard: { path: `${prefix}/components/xcard.vue`, hash: `de3fbb23ae7b00d4c90a717dd361cb9315e9ded6` },
|
|
200
|
+
XCardH: { path: `${prefix}/components/xcard-h.vue`, hash: `de4d42f1056c5d2b8431f15e6b1180d9f9898ac2` },
|
|
201
|
+
XColor: { path: `${prefix}/components/xcolor.vue`, hash: `9bf9497ff66e213277f17af290c21c0a35752510` },
|
|
202
|
+
"v-ace-editor": { path: `${prefix}/components/vue3-ace-editor.vue`, hash: `70ce4a39152af5cf0f7cb6b1d4fdafc8b6225edc` },
|
|
203
|
+
XMarkdown: { path: `${prefix}/components/xmarkdown.vue`, hash: `15f835547fab8a8c8aad47d72640c8e918a7b9da` },
|
|
204
|
+
XSound: { path: `${prefix}/components/xsound.vue`, hash: `3e8ad4aa3c767f757dd49b99aa6f961547caf970` },
|
|
205
|
+
XUpload: { path: `${prefix}/components/xupload.vue`, hash: `7a872277e0047fca11e950efe08f2bffa670abdb` },
|
|
206
|
+
XTree: { path: `${prefix}/components/xtree.vue`, hash: `3b6534e86996c48ab05072a9b793ecc78d83a0eb` },
|
|
207
|
+
CodeMirror: { path: `${prefix}/components/code-mirror.vue`, hash: `3ce1028adb75831e01c4264d5764c14f60a1bd00` },
|
|
208
|
+
XTerminal: { path: `${prefix}/components/xterminal.vue`, hash: `1c01f92c0a08bd4937f9768a1d49f12a9a84feea` },
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
// ________________________________________________________________________________
|
|
214
|
+
// Factory
|
|
215
|
+
// ________________________________________________________________________________
|
|
216
|
+
/**
|
|
217
|
+
* Create a C0ckp1t configuration object.
|
|
218
|
+
*
|
|
219
|
+
* @param {Object} overrides - Properties to override.
|
|
220
|
+
* @returns {Object} The configuration object.
|
|
221
|
+
*/
|
|
222
|
+
export function createConfig(overrides = {}) {
|
|
223
|
+
// 1. Separate root/routes from scalar overrides so deepMerge handles scalars
|
|
224
|
+
const { root: rootOverride, components: componentsOverride, routes: routesOverride, ...scalarOverrides } = overrides;
|
|
225
|
+
|
|
226
|
+
// 2. Merge scalar defaults with overrides
|
|
227
|
+
const merged = deepMerge(DEFAULTS, scalarOverrides);
|
|
228
|
+
|
|
229
|
+
// 3. Resolve the key variables that nav/routes depend on
|
|
230
|
+
const { instanceId, routePrefix, componentPrefix } = merged;
|
|
231
|
+
|
|
232
|
+
// 4. Build or use provided root nav tree
|
|
233
|
+
const root = rootOverride !== undefined ? rootOverride : buildNavTree(instanceId);
|
|
234
|
+
|
|
235
|
+
// 5. Build or use provided routes
|
|
236
|
+
const routes = routesOverride !== undefined ? routesOverride : buildRoutes(instanceId, routePrefix);
|
|
237
|
+
|
|
238
|
+
const components = componentsOverride !== undefined ? componentsOverride : defaultVueComponents(componentPrefix);
|
|
239
|
+
// 6. Assemble final config
|
|
240
|
+
return {
|
|
241
|
+
...merged,
|
|
242
|
+
root,
|
|
243
|
+
routes,
|
|
244
|
+
components
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export default createConfig;
|
package/README.md
CHANGED
|
@@ -45,12 +45,15 @@ tar -zxvf c0ckp1t-1.0.2.tgz
|
|
|
45
45
|
# package/js_ext/Makefile
|
|
46
46
|
# package/css/bootstrap-c0ckp1t.css
|
|
47
47
|
# ...
|
|
48
|
+
|
|
49
|
+
# to expand to webroot directory
|
|
50
|
+
tar -zxvf c0ckp1t-1.0.2.tgz --strip-components=1 -C webroot
|
|
48
51
|
```
|
|
49
52
|
|
|
50
53
|
|
|
51
54
|
## Releases
|
|
52
55
|
|
|
53
|
-
* 1.0.
|
|
56
|
+
* 1.0.12 - Beta: fixing cdn index-cdn.html making sure it works with jsfiddle.net
|
|
54
57
|
* Had to publish many times to get CDN working with different configurations
|
|
55
58
|
* 1.0.2 - Beta: fixing cdn index-cdn.html example
|
|
56
59
|
* 1.0.1 - Beta: removing `Constants.mjs` dependencies
|
|
@@ -73,6 +73,9 @@ let _ro = null;
|
|
|
73
73
|
let _contentBackup = '';
|
|
74
74
|
let _isSettingContent = false;
|
|
75
75
|
|
|
76
|
+
let _mounted = false;
|
|
77
|
+
let _initAborted = false;
|
|
78
|
+
|
|
76
79
|
// CodeMirror modules - loaded dynamically
|
|
77
80
|
let EditorView = null;
|
|
78
81
|
let EditorState = null;
|
|
@@ -215,6 +218,12 @@ watch(() => local.currentReadonly, (val) => {
|
|
|
215
218
|
});
|
|
216
219
|
|
|
217
220
|
onMounted(async () => {
|
|
221
|
+
_mounted = true;
|
|
222
|
+
// --- guard helper ---
|
|
223
|
+
const alive = () => _mounted && root.value != null;
|
|
224
|
+
if (!alive()) return;
|
|
225
|
+
|
|
226
|
+
|
|
218
227
|
// Load core CodeMirror modules
|
|
219
228
|
const [stateModule, viewModule, basicSetupModule] = await Promise.all([
|
|
220
229
|
import('https://esm.sh/@codemirror/state'),
|
|
@@ -222,6 +231,9 @@ onMounted(async () => {
|
|
|
222
231
|
import('https://esm.sh/codemirror'),
|
|
223
232
|
]);
|
|
224
233
|
|
|
234
|
+
// Bail if component unmounted during async load
|
|
235
|
+
if (!alive()) return;
|
|
236
|
+
|
|
225
237
|
EditorState = stateModule.EditorState;
|
|
226
238
|
Compartment = stateModule.Compartment;
|
|
227
239
|
EditorView = viewModule.EditorView;
|
|
@@ -239,6 +251,9 @@ onMounted(async () => {
|
|
|
239
251
|
getThemeExtension(props.theme),
|
|
240
252
|
]);
|
|
241
253
|
|
|
254
|
+
// Bail again after second async gap
|
|
255
|
+
if (!alive()) return;
|
|
256
|
+
|
|
242
257
|
const extensions = [
|
|
243
258
|
basicSetup,
|
|
244
259
|
languageCompartment.of(langExt),
|
|
@@ -301,14 +316,14 @@ onMounted(async () => {
|
|
|
301
316
|
});
|
|
302
317
|
|
|
303
318
|
onBeforeUnmount(() => {
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
319
|
+
_mounted = false;
|
|
320
|
+
|
|
321
|
+
_ro?.disconnect();
|
|
322
|
+
_ro = null;
|
|
323
|
+
|
|
324
|
+
_editor?.destroy();
|
|
325
|
+
_editor = null;
|
|
326
|
+
|
|
312
327
|
});
|
|
313
328
|
|
|
314
329
|
// Public methods
|
package/components/xmarkdown.vue
CHANGED
|
@@ -17,7 +17,7 @@ import {reactive, ref, markRaw, onMounted, watch, computed, onErrorCaptured, de
|
|
|
17
17
|
import {getLogger} from "Logging"
|
|
18
18
|
import {md} from "./Markdown.mjs"
|
|
19
19
|
|
|
20
|
-
import CodeItem from "
|
|
20
|
+
import CodeItem from "../core/sfc/code-item.vue"
|
|
21
21
|
|
|
22
22
|
import {
|
|
23
23
|
replaceHrefLinks,
|
package/core/CoreUtils.mjs
CHANGED
|
@@ -11,6 +11,9 @@ export function findHostnamePortProtocol() {
|
|
|
11
11
|
return {hostname, port, protocol, isSecure, serverUrl}
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
// ________________________________________________________________________________
|
|
15
|
+
// Island Configuration
|
|
16
|
+
// ________________________________________________________________________________
|
|
14
17
|
/**
|
|
15
18
|
* Validate and set defaults for the island config object.
|
|
16
19
|
* @param config
|
|
@@ -35,43 +38,108 @@ export function validateIslandConfig(config) {
|
|
|
35
38
|
return config
|
|
36
39
|
}
|
|
37
40
|
|
|
41
|
+
// ________________________________________________________________________________
|
|
42
|
+
// Application Configuration
|
|
43
|
+
// ________________________________________________________________________________
|
|
44
|
+
export const DEFAULTS = {
|
|
45
|
+
isDev: true,
|
|
46
|
+
// XMLHttpRequest from a different domain cannot set cookie values for their own
|
|
47
|
+
// domain unless withCredentials is set to true before making the request.
|
|
48
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials
|
|
49
|
+
WITH_CREDENTIALS: false,
|
|
50
|
+
|
|
51
|
+
defaultInstanceId: "default",
|
|
52
|
+
instanceId: "default",
|
|
53
|
+
type: "LOCAL",
|
|
54
|
+
// Determines GlobalStore.name
|
|
55
|
+
appName: "C0ckp1t Application",
|
|
56
|
+
// Used for default routes prefix (used only in config)
|
|
57
|
+
routePrefix: "",
|
|
58
|
+
// Used for default components prefix (used only in config)
|
|
59
|
+
componentPrefix: "",
|
|
60
|
+
// Main entry point
|
|
61
|
+
appMainComponent: "/core/PageMain.vue",
|
|
62
|
+
// Used for requestion app components and files (GlobalStore.appEndpoint)
|
|
63
|
+
appEndpoint: "",
|
|
64
|
+
|
|
65
|
+
// Nav Configuration
|
|
66
|
+
navCloseLogo: "/core/img/logo_v1.svg",
|
|
67
|
+
navOpenLogo: "/core/img/logo_v2.svg",
|
|
68
|
+
navHasSearch: false,
|
|
69
|
+
navHasThemeSel: true,
|
|
70
|
+
|
|
71
|
+
// Determine if VueRouter is createWebHashHistory or createWebHistory
|
|
72
|
+
vueRouterModeIsHash: true,
|
|
73
|
+
|
|
74
|
+
// Logger Config (see Logging.mjs)
|
|
75
|
+
defaultLogLevel: "INFO",
|
|
76
|
+
defaultLoggerLevels: {
|
|
77
|
+
"GlobalStore.mjs": "INFO",
|
|
78
|
+
"VueUtils.mjs": "INFO",
|
|
79
|
+
"Connection.mjs": "INFO",
|
|
80
|
+
"default": "INFO",
|
|
81
|
+
"anonymous": "INFO",
|
|
82
|
+
"demo": "INFO"
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
|
|
38
87
|
/**
|
|
39
|
-
*
|
|
40
|
-
* @
|
|
88
|
+
* Validate and set defaults for the config object.
|
|
89
|
+
* @param config
|
|
90
|
+
* @returns {*}
|
|
41
91
|
*/
|
|
42
|
-
export function
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
XCheckbox: `/components/xcheckbox.vue`,
|
|
56
|
-
XTextarea: `/components/xtextarea.vue`,
|
|
57
|
-
XHidden: `/components/xhidden.vue`,
|
|
58
|
-
|
|
59
|
-
XTabs: `/components/xtabs.vue`,
|
|
60
|
-
XKv: `/components/xkv.vue`,
|
|
61
|
-
XNav: `/components/xnav.vue`,
|
|
62
|
-
XMap: `/components/xmap.vue`,
|
|
63
|
-
XList: `/components/xlist.vue`,
|
|
64
|
-
XJson: `/components/xjson.vue`,
|
|
65
|
-
XCard: `/components/xcard.vue`,
|
|
66
|
-
XCardH: `/components/xcard-h.vue`,
|
|
67
|
-
XColor: `/components/xcolor.vue`,
|
|
92
|
+
export function validateAppConfig(config) {
|
|
93
|
+
if (!config) {
|
|
94
|
+
throw new Error("config is required")
|
|
95
|
+
}
|
|
96
|
+
if (typeof config !== 'object') {
|
|
97
|
+
throw new Error("Config must be an object must was `" + typeof config + "`")
|
|
98
|
+
}
|
|
99
|
+
if (!Array.isArray(config?.routes) || config.routes.length === 0) {
|
|
100
|
+
config.routes = []
|
|
101
|
+
}
|
|
102
|
+
if (typeof config.components !== 'object' || config.components === null) {
|
|
103
|
+
config.components = {}
|
|
104
|
+
}
|
|
68
105
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
CodeMirror: `/components/CodeMirror.vue`,
|
|
75
|
-
XTerminal: `/components/XTerminal.vue`,
|
|
106
|
+
if (typeof config.instanceId !== `string` || config.instanceId.trim() === ``) {
|
|
107
|
+
config.instanceId = DEFAULTS.instanceId
|
|
108
|
+
}
|
|
109
|
+
if (typeof config.type !== `string` || config.type.trim() === ``) {
|
|
110
|
+
config.type = DEFAULTS.type
|
|
76
111
|
}
|
|
112
|
+
|
|
113
|
+
return config
|
|
77
114
|
}
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
// ________________________________________________________________________________
|
|
118
|
+
// Deep Merge Utility
|
|
119
|
+
// ________________________________________________________________________________
|
|
120
|
+
/**
|
|
121
|
+
* Deep merge source into target. Returns a new object.
|
|
122
|
+
* - Objects are recursively merged (source keys override target keys)
|
|
123
|
+
* - Arrays are replaced entirely (source array wins)
|
|
124
|
+
* - Scalars are replaced (source wins)
|
|
125
|
+
*/
|
|
126
|
+
export function deepMerge(target, source) {
|
|
127
|
+
const result = { ...target };
|
|
128
|
+
for (const key of Object.keys(source)) {
|
|
129
|
+
const sourceVal = source[key];
|
|
130
|
+
const targetVal = target[key];
|
|
131
|
+
if (
|
|
132
|
+
sourceVal !== null &&
|
|
133
|
+
typeof sourceVal === 'object' &&
|
|
134
|
+
!Array.isArray(sourceVal) &&
|
|
135
|
+
targetVal !== null &&
|
|
136
|
+
typeof targetVal === 'object' &&
|
|
137
|
+
!Array.isArray(targetVal)
|
|
138
|
+
) {
|
|
139
|
+
result[key] = deepMerge(targetVal, sourceVal);
|
|
140
|
+
} else {
|
|
141
|
+
result[key] = sourceVal;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return result;
|
|
145
|
+
}
|
package/core/GlobalStore.mjs
CHANGED
|
@@ -8,8 +8,8 @@ import {markRaw, reactive, watch, defineAsyncComponent, createApp} from 'vue'
|
|
|
8
8
|
import * as VueRouter from 'vue-router'
|
|
9
9
|
import {getLogger} from 'Logging';
|
|
10
10
|
import {transformRoutes, loadModule, options} from "VueUtils";
|
|
11
|
-
import {validateIslandConfig, findHostnamePortProtocol,
|
|
12
|
-
import {substrAfterFirstSlash} from "JsUtils";
|
|
11
|
+
import {validateIslandConfig, findHostnamePortProtocol, validateAppConfig} from 'CoreUtils'
|
|
12
|
+
import {substrAfterFirstSlash, extractLastPath} from "JsUtils";
|
|
13
13
|
|
|
14
14
|
import IslandDefault from 'IslandDefault'
|
|
15
15
|
import Island from 'Island'
|
|
@@ -46,6 +46,7 @@ export const store = reactive({
|
|
|
46
46
|
name: "C0ckp1t",
|
|
47
47
|
id: LOG_HEADER,
|
|
48
48
|
config: null,
|
|
49
|
+
appEndpoint: "",
|
|
49
50
|
serverInfo: findHostnamePortProtocol(),
|
|
50
51
|
|
|
51
52
|
// ________________________________________________________________________________
|
|
@@ -217,8 +218,15 @@ export const api = {
|
|
|
217
218
|
},
|
|
218
219
|
|
|
219
220
|
routeByEndpoint: async (endpoint) => {
|
|
220
|
-
|
|
221
|
+
const path = endpoint.split("/")
|
|
222
|
+
logger.info(`[routeByEndpoint] - endpoint=${endpoint}, path=${path}`)
|
|
221
223
|
try {
|
|
224
|
+
if(path.length > 3) {
|
|
225
|
+
extractLastPath(endpoint)
|
|
226
|
+
document.title = `${path[2]}-${path[3]}`
|
|
227
|
+
} else if (path.length === 3) {
|
|
228
|
+
document.title = `${path[2]}`
|
|
229
|
+
}
|
|
222
230
|
await store.router.push(endpoint)
|
|
223
231
|
} catch (err) {
|
|
224
232
|
console.error("Failed to navigate:", err)
|
|
@@ -283,7 +291,7 @@ export const api = {
|
|
|
283
291
|
return null
|
|
284
292
|
}
|
|
285
293
|
|
|
286
|
-
|
|
294
|
+
validateAppConfig(config)
|
|
287
295
|
//________________________________________________________________________________
|
|
288
296
|
// Create Vue Application
|
|
289
297
|
//________________________________________________________________________________
|
|
@@ -301,21 +309,21 @@ export const api = {
|
|
|
301
309
|
//________________________________________________________________________________
|
|
302
310
|
// Create Default Island
|
|
303
311
|
//________________________________________________________________________________
|
|
312
|
+
config.routes ??= []
|
|
304
313
|
if(config.routes.length === 0) {
|
|
305
314
|
logger.warn(`config.routes is empty`)
|
|
306
315
|
}
|
|
307
|
-
|
|
316
|
+
store.appEndpoint = config.appEndpoint ?? ""
|
|
308
317
|
store.defaultInstanceId = config.instanceId ?? "default"
|
|
309
318
|
store.name = config.appName ?? "C0ckp1t"
|
|
310
319
|
store.config = config
|
|
311
320
|
const vueRouterModeIsHash = config.vueRouterModeIsHash ?? true
|
|
312
321
|
|
|
322
|
+
// Load default island
|
|
313
323
|
const decoratedIslandConfig = {
|
|
314
324
|
...config,
|
|
315
325
|
SERVER_API_URL: store.serverInfo.serverUrl,
|
|
316
326
|
}
|
|
317
|
-
|
|
318
|
-
// Load default island first
|
|
319
327
|
const islandDefault = new IslandDefault(api, decoratedIslandConfig)
|
|
320
328
|
store.r[islandDefault.instanceId] = islandDefault
|
|
321
329
|
await islandDefault.init()
|
|
@@ -328,12 +336,12 @@ export const api = {
|
|
|
328
336
|
store.router = markRaw(router)
|
|
329
337
|
|
|
330
338
|
// Main entry point for the app, this will load the main application
|
|
331
|
-
app.component('app-main', createAsyncComponent(() => api.loadModule(
|
|
339
|
+
app.component('app-main', createAsyncComponent(() => api.loadModule(config.appMainComponent)))
|
|
332
340
|
|
|
333
341
|
// Configure C0ckp1t Vue Components
|
|
334
|
-
const vueComponents =
|
|
342
|
+
const vueComponents = config.components ?? {}
|
|
335
343
|
for (const [key, value] of Object.entries(vueComponents)) {
|
|
336
|
-
app.component(key, defineAsyncComponent(() => api.loadModule(`${
|
|
344
|
+
app.component(key, defineAsyncComponent(() => api.loadModule(`${value.path}`)))
|
|
337
345
|
}
|
|
338
346
|
|
|
339
347
|
app.use(router)
|
package/core/Island.mjs
CHANGED
|
@@ -39,6 +39,7 @@ export default class Island {
|
|
|
39
39
|
constructor(apiMain, config) {
|
|
40
40
|
|
|
41
41
|
this.instanceId = config.instanceId
|
|
42
|
+
this.SERVER_API_URL = config.SERVER_API_URL
|
|
42
43
|
|
|
43
44
|
this.LOG_HEADER = `${this.instanceId}`;
|
|
44
45
|
this.logger = getLogger(this.LOG_HEADER);
|
|
@@ -184,6 +185,7 @@ export default class Island {
|
|
|
184
185
|
await this.apiMain.insertRoutes(`/${this.instanceId}${node.endpoint}`, config)
|
|
185
186
|
} else {
|
|
186
187
|
this.logger.warn(`[node=${node.name}] - failed to load config`)
|
|
188
|
+
this.logger.warn(`path=${node.config.path}`)
|
|
187
189
|
this.logger.warn(`endpoint=/${this.instanceId}${node.endpoint}`)
|
|
188
190
|
this.logger.warn(`depth=${node.depth}`)
|
|
189
191
|
this.logger.warn(`accessLevel=${this.store.context.accessLevel}`)
|
|
@@ -199,6 +201,11 @@ export default class Island {
|
|
|
199
201
|
[{"path": node.name, "location": "/core/nodes/_api.vue"}]
|
|
200
202
|
)
|
|
201
203
|
}
|
|
204
|
+
} else if(node.depth === 2 && node.endpoint.startsWith(`/wf/`)) {
|
|
205
|
+
this.logger.warn(`insert admin`)
|
|
206
|
+
await this.apiMain.insertRoutes(`/${this.instanceId}${node.endpoint}`,
|
|
207
|
+
[{"path": node.name, "location": `/${this.instanceId}/v3/actions/root/admin/_admin.vue`}],
|
|
208
|
+
)
|
|
202
209
|
}
|
|
203
210
|
}
|
|
204
211
|
// NO CONFIG FOUND
|
|
@@ -214,6 +221,11 @@ export default class Island {
|
|
|
214
221
|
)
|
|
215
222
|
}
|
|
216
223
|
}
|
|
224
|
+
if(node.name === "api") {
|
|
225
|
+
await this.apiMain.insertRoutes(`/${this.instanceId}${node.endpoint}`,
|
|
226
|
+
[{"path": node.name, "location": "/core/nodes/place-holder.vue"}]
|
|
227
|
+
)
|
|
228
|
+
}
|
|
217
229
|
}
|
|
218
230
|
|
|
219
231
|
if (node.children) {
|
|
@@ -298,11 +310,11 @@ export default class Island {
|
|
|
298
310
|
// HTTP
|
|
299
311
|
// ________________________________________________________________________________
|
|
300
312
|
resolver = async (endpoint, type) => {
|
|
301
|
-
this.logger.
|
|
313
|
+
this.logger.debug(`[resolver] - endpoint=${endpoint}`)
|
|
302
314
|
|
|
303
315
|
if (endpoint.startsWith('/c0ckp1t/')) {
|
|
304
316
|
const endpointAdjusted = endpoint.replace("/c0ckp1t/", `/`)
|
|
305
|
-
const path = `${this.
|
|
317
|
+
const path = `${this.SERVER_API_URL}${endpointAdjusted}`;
|
|
306
318
|
this.logger.debug(`[resolver] - endpointAdjusted=${path}`);
|
|
307
319
|
const res = await Http.getText(path)
|
|
308
320
|
if (res.isOk) {
|
|
@@ -407,7 +419,7 @@ export default class Island {
|
|
|
407
419
|
// HELPER METHODS
|
|
408
420
|
// ________________________________________________________________________________
|
|
409
421
|
function adjustNode(node) {
|
|
410
|
-
node._expanded
|
|
422
|
+
node._expanded ??= true;
|
|
411
423
|
node.children.forEach((child) => {
|
|
412
424
|
adjustNode(child);
|
|
413
425
|
});
|
package/core/IslandDefault.mjs
CHANGED
|
@@ -210,7 +210,7 @@ export default class IslandDefault {
|
|
|
210
210
|
// HELPER METHODS
|
|
211
211
|
// ________________________________________________________________________________
|
|
212
212
|
function adjustNode(node) {
|
|
213
|
-
node._expanded
|
|
213
|
+
node._expanded ??= true;
|
|
214
214
|
node.children.forEach((child) => {
|
|
215
215
|
adjustNode(child);
|
|
216
216
|
});
|
package/core/PageMain.vue
CHANGED
|
@@ -13,7 +13,7 @@ import {getLogger} from "Logging";
|
|
|
13
13
|
import {api as apiTheme, store as storeTheme} from "./Theme.mjs"
|
|
14
14
|
import PageFallback from "./PageFallback.vue"
|
|
15
15
|
import MainOffcanvas from "./main-offcanvas.vue";
|
|
16
|
-
|
|
16
|
+
import NotifyToast from "./notify/toast.vue";
|
|
17
17
|
|
|
18
18
|
// ________________________________________________________________________________
|
|
19
19
|
// LOGGING
|
|
@@ -29,8 +29,12 @@ logger.debug("[INIT]")
|
|
|
29
29
|
const local = reactive({
|
|
30
30
|
id: LOG_HEADER,
|
|
31
31
|
toggle: false,
|
|
32
|
-
items: [
|
|
33
|
-
|
|
32
|
+
items: [ ],
|
|
33
|
+
|
|
34
|
+
navCloseLogo: storeMain.config?.navCloseLogo ?? "/img/logo_v1.svg",
|
|
35
|
+
navOpenLogo: storeMain.config?.navOpenLogo ?? "/img/logo_v2.svg",
|
|
36
|
+
navHasSearch: storeMain.config?.navHasSearch ?? true,
|
|
37
|
+
navHasThemeSel: storeMain.config?.navHasThemeSel ?? true,
|
|
34
38
|
})
|
|
35
39
|
|
|
36
40
|
|
|
@@ -95,8 +99,8 @@ const mainContentStyle = computed(() => ({
|
|
|
95
99
|
|
|
96
100
|
<a class="navbar-brand" @click.prevent="apiMain.selectLogo()" >
|
|
97
101
|
<span class="me-2 text-warning" v-if="storeMain.showSidebar"><<</span>
|
|
98
|
-
<img src="
|
|
99
|
-
<img src="
|
|
102
|
+
<img :src="local.navCloseLogo" alt="Logo" height="24" class="d-inline-block align-text-top" v-if="!storeMain.showSidebar && local.navCloseLogo">
|
|
103
|
+
<img :src="local.navOpenLogo" alt="Logo" height="24" class="d-inline-block align-text-top" v-if="storeMain.showSidebar && local.navOpenLogo">
|
|
100
104
|
<span class="text-warning fw-bold ms-2 brand-text">{{ storeMain.name }}</span>
|
|
101
105
|
</a>
|
|
102
106
|
|
|
@@ -116,13 +120,13 @@ const mainContentStyle = computed(() => ({
|
|
|
116
120
|
</ul>
|
|
117
121
|
|
|
118
122
|
<form class="d-flex">
|
|
119
|
-
<input class="form-control me-2" type="search" placeholder="Search" v-model="local.searchQuery">
|
|
120
|
-
<button class="btn btn-outline-secondary
|
|
121
|
-
<i class="fa-solid" :class="storeTheme.theme === 'dark' ? 'fa-sun' : 'fa-moon'"></i>
|
|
122
|
-
</button>
|
|
123
|
-
<button class="btn btn-outline-secondary" type="submit">
|
|
123
|
+
<input v-if="local.navHasSearch" class="form-control me-2" type="search" placeholder="Search" v-model="local.searchQuery">
|
|
124
|
+
<button v-if="local.navHasSearch" class="btn btn-outline-secondary" type="submit">
|
|
124
125
|
<i class="fa-solid fa-search"></i>
|
|
125
126
|
</button>
|
|
127
|
+
<button v-if="local.navHasThemeSel" class="btn btn-outline-secondary me-2" type="button" @click="storeTheme.theme = storeTheme.theme === 'dark' ? 'light' : 'dark'" title="Toggle theme">
|
|
128
|
+
<i class="fa-solid" :class="storeTheme.theme === 'dark' ? 'fa-sun' : 'fa-moon'"></i>
|
|
129
|
+
</button>
|
|
126
130
|
</form>
|
|
127
131
|
|
|
128
132
|
</div>
|
|
@@ -135,6 +139,7 @@ const mainContentStyle = computed(() => ({
|
|
|
135
139
|
<RouterView/>
|
|
136
140
|
</main>
|
|
137
141
|
|
|
142
|
+
<NotifyToast/>
|
|
138
143
|
<!-- ========== FOOTER ========== -->
|
|
139
144
|
<footer class="container-fluid p-4 bg-body-tertiary border-top">
|
|
140
145
|
<div class="row mt-4 align-items-center justify-content-center">
|
package/core/img/logo_v2.svg
CHANGED
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
cy="129.01283"
|
|
59
59
|
cx="97.967125"
|
|
60
60
|
id="head"
|
|
61
|
-
style="fill:#
|
|
61
|
+
style="fill:#c4a900;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.264583;stroke-opacity:1" />
|
|
62
62
|
<path
|
|
63
63
|
id="lefEye2"
|
|
64
64
|
d="M 62.802996,126.14677 C 83.82199,101.23898 83.964978,101.06953 83.964978,101.06953"
|
|
@@ -86,9 +86,9 @@
|
|
|
86
86
|
height="8.6218405"
|
|
87
87
|
width="19.292933"
|
|
88
88
|
id="neck1"
|
|
89
|
-
style="fill:#
|
|
89
|
+
style="fill:#c4a900;fill-opacity:1;stroke:#000000;stroke-width:0.264951;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
|
90
90
|
<rect
|
|
91
|
-
style="fill:#
|
|
91
|
+
style="fill:#c4a900;fill-opacity:1;stroke:#000000;stroke-width:0.222;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
|
92
92
|
id="neck2"
|
|
93
93
|
width="12.705888"
|
|
94
94
|
height="6.1260414"
|
package/core/nodes/_api.vue
CHANGED
|
@@ -51,7 +51,7 @@ const local = reactive({
|
|
|
51
51
|
<template>
|
|
52
52
|
|
|
53
53
|
<div class="_api" >
|
|
54
|
-
<x-section
|
|
54
|
+
<x-section :level="4" :visible="true" :k="`API Node for endpoint=${adminEndpoint}`" v-if="selectedNode">
|
|
55
55
|
|
|
56
56
|
<template v-slot:header>
|
|
57
57
|
<ExecButton icon="fa-info" @callback="apiMain.selectDocumentation(storeMain.documentation)"></ExecButton>
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import {reactive, onMounted, onUnmounted, defineAsyncComponent, watch, onErrorCaptured, computed} from 'vue'
|
|
8
8
|
import {store as storeMain, api as apiMain} from 'GlobalStore'
|
|
9
9
|
|
|
10
|
-
const InfoApi = defineAsyncComponent(() => import("
|
|
10
|
+
const InfoApi = defineAsyncComponent(() => import("./_api.vue"))
|
|
11
11
|
|
|
12
12
|
const selectedNode = computed(() => {
|
|
13
13
|
return storeMain.r[storeMain.selectedInstId]?.store?.selectedNode
|
|
@@ -17,22 +17,13 @@ const selectedNode = computed(() => {
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
<template>
|
|
20
|
+
<div class="place-holder">
|
|
21
|
+
<x-section :level="3" :visible="true" :k="`Place Holder Node (endpoint=${selectedNode.endpoint})`" v-if="selectedNode">
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
<x-section extra="fs-4" :visible="true" :k="`Place Holder Node (endpoint=${selectedNode.endpoint})`">
|
|
23
|
-
|
|
24
|
-
<template v-slot:header>
|
|
25
|
-
<x-button icon="fa-info" @callback="apiMain.selectDocumentation(storeMain.documentation)"></x-button>
|
|
26
|
-
</template>
|
|
27
|
-
|
|
28
|
-
<x-section extra="fs-4" :visible="false" :k="`API Information`">
|
|
29
|
-
<info-api :endpoint="selectedNode.endpoint" :instanceId="storeMain.selectedInstId"></info-api>
|
|
30
|
-
</x-section>
|
|
31
|
-
|
|
32
|
-
<x-section extra="fs-4" :visible="false" :k="`Node Information`">
|
|
23
|
+
<x-section :level="4" :visible="true" :k="`Node Information`">
|
|
33
24
|
<div class="row mt-4 mb-4">
|
|
34
|
-
<x-collapse k="Node Entity">
|
|
35
|
-
<x-json :obj="selectedNode"></x-json>
|
|
25
|
+
<x-collapse k="Node Entity" :modelValue="true">
|
|
26
|
+
<x-json :obj="selectedNode" :expanded="true"></x-json>
|
|
36
27
|
</x-collapse>
|
|
37
28
|
</div>
|
|
38
29
|
</x-section>
|
package/core/notify/toast.vue
CHANGED
|
@@ -13,8 +13,6 @@ import {reactive, computed, ref, onMounted, onUnmounted, defineAsyncComponent, w
|
|
|
13
13
|
import {getLogger} from "Logging";
|
|
14
14
|
// !# C0CKP1T_START imports
|
|
15
15
|
import ComponentView from "./component-view.vue";
|
|
16
|
-
import XTerminal from "/components/xterminal.vue";
|
|
17
|
-
import CodeMirror from "/components/code-mirror.vue";
|
|
18
16
|
// !# C0CKP1T_END imports
|
|
19
17
|
|
|
20
18
|
// ________________________________________________________________________________
|
package/core/sfc/info-api.vue
CHANGED
|
@@ -146,12 +146,12 @@ onMounted(async () => { init() })
|
|
|
146
146
|
.functions {
|
|
147
147
|
border: 2px solid black;
|
|
148
148
|
padding: 4px;
|
|
149
|
-
background-color:
|
|
149
|
+
background-color: var(--bs-secondary-bg)
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
.functions2 {
|
|
153
153
|
border: 2px solid black;
|
|
154
154
|
padding: 4px;
|
|
155
|
-
background-color:
|
|
155
|
+
background-color: var(--bs-secondary-bg)
|
|
156
156
|
}
|
|
157
157
|
</style>
|
package/docs/Issues.md
ADDED
package/index.html
CHANGED
|
@@ -57,15 +57,18 @@
|
|
|
57
57
|
|
|
58
58
|
<script type="module">
|
|
59
59
|
import {init as initLogger} from 'Logging';
|
|
60
|
-
import {api as apiMain} from 'GlobalStore'
|
|
61
|
-
|
|
60
|
+
import {api as apiMain} from 'GlobalStore';
|
|
61
|
+
// Application Configuration
|
|
62
|
+
import { createConfig } from './Config.mjs';
|
|
63
|
+
// Islands
|
|
62
64
|
import ConfigAdmin from './ConfigAdmin.mjs'
|
|
63
65
|
import ConfigAnonymous from './ConfigAnonymous.mjs'
|
|
64
66
|
import ConfigDemo from './c0ckp1t-demo/C0ckp1tConfig.mjs'
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
// Create Application
|
|
68
|
+
const config = createConfig();
|
|
69
|
+
initLogger(config)
|
|
70
|
+
await apiMain.init("app-default", config)
|
|
71
|
+
// Create Islands
|
|
69
72
|
await apiMain.registerIsland( ConfigAdmin)
|
|
70
73
|
await apiMain.registerIsland(ConfigAnonymous)
|
|
71
74
|
await apiMain.registerIsland(ConfigDemo)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "c0ckp1t",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.12",
|
|
4
4
|
"description": "A Vue 3 zero-build web dashboard framework with Islands architecture, WebSocket backends, and reusable UI components",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"index-cdn.html",
|
|
27
27
|
"index.html",
|
|
28
28
|
"style.css",
|
|
29
|
+
"Config.mjs",
|
|
29
30
|
"DefaultConfig.mjs",
|
|
30
31
|
"CdnConfig.mjs",
|
|
31
32
|
"favicon.ico",
|
package/CdnConfig.mjs
DELETED
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Default Configuration for a C0ckp1t Application
|
|
3
|
-
*/
|
|
4
|
-
// ________________________________________________________________________________
|
|
5
|
-
// Properties
|
|
6
|
-
// ________________________________________________________________________________
|
|
7
|
-
// XMLHttpRequest from a different domain cannot set cookie values for their own
|
|
8
|
-
// domain unless withCredentials is set to true before making the request.
|
|
9
|
-
// https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials
|
|
10
|
-
const WITH_CREDENTIALS = false
|
|
11
|
-
// Note: VueUtils requires this to be 'default'
|
|
12
|
-
const instanceId = "default";
|
|
13
|
-
// Used for requestion app components and files
|
|
14
|
-
const appEndpoint = "https://cdn.jsdelivr.net/npm/c0ckp1t@latest";
|
|
15
|
-
|
|
16
|
-
// ________________________________________________________________________________
|
|
17
|
-
// GLOBAL CONSTANTS
|
|
18
|
-
// ________________________________________________________________________________
|
|
19
|
-
export default {
|
|
20
|
-
isDev: true,
|
|
21
|
-
WITH_CREDENTIALS: WITH_CREDENTIALS,
|
|
22
|
-
|
|
23
|
-
// logger config
|
|
24
|
-
defaultLogLevel: "INFO",
|
|
25
|
-
defaultLoggerLevels: {
|
|
26
|
-
"GlobalStore.mjs": "INFO",
|
|
27
|
-
"VueUtils.mjs": "INFO",
|
|
28
|
-
"Connection.mjs": "INFO",
|
|
29
|
-
"default": "INFO",
|
|
30
|
-
"anonymous": "INFO",
|
|
31
|
-
"demo": "INFO"
|
|
32
|
-
},
|
|
33
|
-
|
|
34
|
-
instanceId: instanceId,
|
|
35
|
-
type: "LOCAL",
|
|
36
|
-
appName: "C0ckp1t App",
|
|
37
|
-
appEndpoint: appEndpoint,
|
|
38
|
-
|
|
39
|
-
// This creates the navigation tree
|
|
40
|
-
root: {
|
|
41
|
-
icon: "fa-house",
|
|
42
|
-
depth: 0,
|
|
43
|
-
endpoint: "/",
|
|
44
|
-
isLeaf: false,
|
|
45
|
-
isRoot: true,
|
|
46
|
-
name: "",
|
|
47
|
-
path: [],
|
|
48
|
-
children: [
|
|
49
|
-
{
|
|
50
|
-
depth: 1,
|
|
51
|
-
endpoint: `/${instanceId}/connections`,
|
|
52
|
-
isLeaf: true,
|
|
53
|
-
isRoot: false,
|
|
54
|
-
path: ["connections"],
|
|
55
|
-
name: "Connections",
|
|
56
|
-
children: []
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
depth: 1,
|
|
60
|
-
endpoint: `/${instanceId}/cache`,
|
|
61
|
-
isLeaf: true,
|
|
62
|
-
isRoot: false,
|
|
63
|
-
path: ["cache"],
|
|
64
|
-
name: "Cache",
|
|
65
|
-
children: []
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
icon: "fa-network-wired",
|
|
69
|
-
depth: 1,
|
|
70
|
-
endpoint: `/${instanceId}/traffic`,
|
|
71
|
-
isLeaf: true,
|
|
72
|
-
isRoot: false,
|
|
73
|
-
path: ["traffic"],
|
|
74
|
-
name: "Traffic",
|
|
75
|
-
children: []
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
icon: "fa-bell",
|
|
79
|
-
depth: 1,
|
|
80
|
-
endpoint: `/${instanceId}/notifies`,
|
|
81
|
-
isLeaf: true,
|
|
82
|
-
isRoot: false,
|
|
83
|
-
path: ["notifies"],
|
|
84
|
-
name: "Notifies",
|
|
85
|
-
children: []
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
icon: "fa-info",
|
|
89
|
-
depth: 1,
|
|
90
|
-
endpoint: `/${instanceId}/docs`,
|
|
91
|
-
isLeaf: true,
|
|
92
|
-
isRoot: false,
|
|
93
|
-
path: ["docs"],
|
|
94
|
-
name: "Documentation",
|
|
95
|
-
children: []
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
icon: "fa-info",
|
|
99
|
-
depth: 1,
|
|
100
|
-
endpoint: `/${instanceId}/components`,
|
|
101
|
-
isLeaf: true,
|
|
102
|
-
isRoot: false,
|
|
103
|
-
path: ["components"],
|
|
104
|
-
name: "Components",
|
|
105
|
-
children: [
|
|
106
|
-
{
|
|
107
|
-
icon: "fa-info",
|
|
108
|
-
depth: 2,
|
|
109
|
-
endpoint: `/${instanceId}/components/bootstrap`,
|
|
110
|
-
isLeaf: true,
|
|
111
|
-
isRoot: false,
|
|
112
|
-
path: ["bootstrap"],
|
|
113
|
-
name: "Bootstrap",
|
|
114
|
-
children: []
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
icon: "fa-info",
|
|
118
|
-
depth: 2,
|
|
119
|
-
endpoint: `/${instanceId}/components/basic`,
|
|
120
|
-
isLeaf: true,
|
|
121
|
-
isRoot: false,
|
|
122
|
-
path: ["basic"],
|
|
123
|
-
name: "Basic",
|
|
124
|
-
children: []
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
icon: "fa-info",
|
|
128
|
-
depth: 2,
|
|
129
|
-
endpoint: `/${instanceId}/components/advanced`,
|
|
130
|
-
isLeaf: true,
|
|
131
|
-
isRoot: false,
|
|
132
|
-
path: ["advanced"],
|
|
133
|
-
name: "Advanced",
|
|
134
|
-
children: []
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
icon: "fa-info",
|
|
138
|
-
depth: 2,
|
|
139
|
-
endpoint: `/${instanceId}/components/theme`,
|
|
140
|
-
isLeaf: true,
|
|
141
|
-
isRoot: false,
|
|
142
|
-
path: ["theme"],
|
|
143
|
-
name: "Theme",
|
|
144
|
-
children: []
|
|
145
|
-
},
|
|
146
|
-
]
|
|
147
|
-
}
|
|
148
|
-
]
|
|
149
|
-
},
|
|
150
|
-
|
|
151
|
-
// This is used to create routes for the vue router
|
|
152
|
-
routes: [
|
|
153
|
-
{ path: '/', name: 'root', children: [
|
|
154
|
-
{path: '', redirect: '/default/docs/Introduction.md'},
|
|
155
|
-
{path: `${instanceId}`, children :[
|
|
156
|
-
{path: 'docs', redirect: `/${instanceId}/docs/Introduction.md`},
|
|
157
|
-
{path: 'docs/:pathMatch(.*)*', location: `${appEndpoint}/core/pages/Documentation.vue`},
|
|
158
|
-
{path: 'connections', location: `${appEndpoint}/core/pages/Connections.vue`},
|
|
159
|
-
{path: 'connections/:id', location: `${appEndpoint}/core/pages/Connection.vue`},
|
|
160
|
-
{path: 'cache', location: `${appEndpoint}/core/pages/Cache.vue`},
|
|
161
|
-
{path: 'traffic', location: `${appEndpoint}/core/pages/Traffic.vue`},
|
|
162
|
-
{path: 'notifies', location: `${appEndpoint}/core/pages/Notifies.vue`},
|
|
163
|
-
{path: 'components', location: `${appEndpoint}/core/pages/frontend/Components.vue`, children: [
|
|
164
|
-
{path: 'basic', location: `${appEndpoint}/core/pages/frontend/ComponentsBasic.vue`},
|
|
165
|
-
{path: 'advanced', location: `${appEndpoint}/core/pages/frontend/ComponentsAdv.vue`},
|
|
166
|
-
{path: 'theme', location: `${appEndpoint}/core/pages/frontend/Theme.vue`},
|
|
167
|
-
{path: 'bootstrap', location: `${appEndpoint}/core/pages/frontend/Bootstrap.vue`},
|
|
168
|
-
]},
|
|
169
|
-
]}
|
|
170
|
-
] },
|
|
171
|
-
{ path: '/:pathMatch(.*)*', name: '404', location: `${appEndpoint}/core/Page404.vue` }
|
|
172
|
-
|
|
173
|
-
]
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
} // end of Constants
|
|
177
|
-
|
package/DefaultConfig.mjs
DELETED
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Default Configuration for a C0ckp1t Application
|
|
3
|
-
*/
|
|
4
|
-
// ________________________________________________________________________________
|
|
5
|
-
// Properties
|
|
6
|
-
// ________________________________________________________________________________
|
|
7
|
-
// XMLHttpRequest from a different domain cannot set cookie values for their own
|
|
8
|
-
// domain unless withCredentials is set to true before making the request.
|
|
9
|
-
// https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials
|
|
10
|
-
const WITH_CREDENTIALS = false
|
|
11
|
-
// Note: VueUtils requires this to be 'default'
|
|
12
|
-
const instanceId = "default";
|
|
13
|
-
// Used for requestion app components and files
|
|
14
|
-
const appEndpoint = "";
|
|
15
|
-
|
|
16
|
-
// ________________________________________________________________________________
|
|
17
|
-
// GLOBAL CONSTANTS
|
|
18
|
-
// ________________________________________________________________________________
|
|
19
|
-
export default {
|
|
20
|
-
isDev: true,
|
|
21
|
-
WITH_CREDENTIALS: WITH_CREDENTIALS,
|
|
22
|
-
|
|
23
|
-
// logger config
|
|
24
|
-
defaultLogLevel: "INFO",
|
|
25
|
-
defaultLoggerLevels: {
|
|
26
|
-
"GlobalStore.mjs": "INFO",
|
|
27
|
-
"VueUtils.mjs": "INFO",
|
|
28
|
-
"Connection.mjs": "INFO",
|
|
29
|
-
"default": "INFO",
|
|
30
|
-
"anonymous": "INFO",
|
|
31
|
-
"demo": "INFO"
|
|
32
|
-
},
|
|
33
|
-
|
|
34
|
-
instanceId: instanceId,
|
|
35
|
-
type: "LOCAL",
|
|
36
|
-
appName: "C0ckp1t App",
|
|
37
|
-
appEndpoint: appEndpoint,
|
|
38
|
-
|
|
39
|
-
// This creates the navigation tree
|
|
40
|
-
root: {
|
|
41
|
-
icon: "fa-house",
|
|
42
|
-
depth: 0,
|
|
43
|
-
endpoint: "/",
|
|
44
|
-
isLeaf: false,
|
|
45
|
-
isRoot: true,
|
|
46
|
-
name: "",
|
|
47
|
-
path: [],
|
|
48
|
-
children: [
|
|
49
|
-
{
|
|
50
|
-
depth: 1,
|
|
51
|
-
endpoint: `/${instanceId}/connections`,
|
|
52
|
-
isLeaf: true,
|
|
53
|
-
isRoot: false,
|
|
54
|
-
path: ["connections"],
|
|
55
|
-
name: "Connections",
|
|
56
|
-
children: []
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
depth: 1,
|
|
60
|
-
endpoint: `/${instanceId}/cache`,
|
|
61
|
-
isLeaf: true,
|
|
62
|
-
isRoot: false,
|
|
63
|
-
path: ["cache"],
|
|
64
|
-
name: "Cache",
|
|
65
|
-
children: []
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
icon: "fa-network-wired",
|
|
69
|
-
depth: 1,
|
|
70
|
-
endpoint: `/${instanceId}/traffic`,
|
|
71
|
-
isLeaf: true,
|
|
72
|
-
isRoot: false,
|
|
73
|
-
path: ["traffic"],
|
|
74
|
-
name: "Traffic",
|
|
75
|
-
children: []
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
icon: "fa-bell",
|
|
79
|
-
depth: 1,
|
|
80
|
-
endpoint: `/${instanceId}/notifies`,
|
|
81
|
-
isLeaf: true,
|
|
82
|
-
isRoot: false,
|
|
83
|
-
path: ["notifies"],
|
|
84
|
-
name: "Notifies",
|
|
85
|
-
children: []
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
icon: "fa-info",
|
|
89
|
-
depth: 1,
|
|
90
|
-
endpoint: `/${instanceId}/docs`,
|
|
91
|
-
isLeaf: true,
|
|
92
|
-
isRoot: false,
|
|
93
|
-
path: ["docs"],
|
|
94
|
-
name: "Documentation",
|
|
95
|
-
children: []
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
icon: "fa-info",
|
|
99
|
-
depth: 1,
|
|
100
|
-
endpoint: `/${instanceId}/components`,
|
|
101
|
-
isLeaf: true,
|
|
102
|
-
isRoot: false,
|
|
103
|
-
path: ["components"],
|
|
104
|
-
name: "Components",
|
|
105
|
-
children: [
|
|
106
|
-
{
|
|
107
|
-
icon: "fa-info",
|
|
108
|
-
depth: 2,
|
|
109
|
-
endpoint: `/${instanceId}/components/bootstrap`,
|
|
110
|
-
isLeaf: true,
|
|
111
|
-
isRoot: false,
|
|
112
|
-
path: ["bootstrap"],
|
|
113
|
-
name: "Bootstrap",
|
|
114
|
-
children: []
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
icon: "fa-info",
|
|
118
|
-
depth: 2,
|
|
119
|
-
endpoint: `/${instanceId}/components/basic`,
|
|
120
|
-
isLeaf: true,
|
|
121
|
-
isRoot: false,
|
|
122
|
-
path: ["basic"],
|
|
123
|
-
name: "Basic",
|
|
124
|
-
children: []
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
icon: "fa-info",
|
|
128
|
-
depth: 2,
|
|
129
|
-
endpoint: `/${instanceId}/components/advanced`,
|
|
130
|
-
isLeaf: true,
|
|
131
|
-
isRoot: false,
|
|
132
|
-
path: ["advanced"],
|
|
133
|
-
name: "Advanced",
|
|
134
|
-
children: []
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
icon: "fa-info",
|
|
138
|
-
depth: 2,
|
|
139
|
-
endpoint: `/${instanceId}/components/theme`,
|
|
140
|
-
isLeaf: true,
|
|
141
|
-
isRoot: false,
|
|
142
|
-
path: ["theme"],
|
|
143
|
-
name: "Theme",
|
|
144
|
-
children: []
|
|
145
|
-
},
|
|
146
|
-
]
|
|
147
|
-
}
|
|
148
|
-
]
|
|
149
|
-
},
|
|
150
|
-
|
|
151
|
-
// This is used to create routes for the vue router
|
|
152
|
-
routes: [
|
|
153
|
-
{ path: '/', name: 'root', children: [
|
|
154
|
-
{path: '', redirect: '/default/docs/Introduction.md'},
|
|
155
|
-
{path: `${instanceId}`, children :[
|
|
156
|
-
{path: 'docs', redirect: `/${instanceId}/docs/Introduction.md`},
|
|
157
|
-
{path: 'docs/:pathMatch(.*)*', location: `${appEndpoint}/core/pages/Documentation.vue`},
|
|
158
|
-
{path: 'connections', location: `${appEndpoint}/core/pages/Connections.vue`},
|
|
159
|
-
{path: 'connections/:id', location: `${appEndpoint}/core/pages/Connection.vue`},
|
|
160
|
-
{path: 'cache', location: `${appEndpoint}/core/pages/Cache.vue`},
|
|
161
|
-
{path: 'traffic', location: `${appEndpoint}/core/pages/Traffic.vue`},
|
|
162
|
-
{path: 'notifies', location: `${appEndpoint}/core/pages/Notifies.vue`},
|
|
163
|
-
{path: 'components', location: `${appEndpoint}/core/pages/frontend/Components.vue`, children: [
|
|
164
|
-
{path: 'basic', location: `${appEndpoint}/core/pages/frontend/ComponentsBasic.vue`},
|
|
165
|
-
{path: 'advanced', location: `${appEndpoint}/core/pages/frontend/ComponentsAdv.vue`},
|
|
166
|
-
{path: 'theme', location: `${appEndpoint}/core/pages/frontend/Theme.vue`},
|
|
167
|
-
{path: 'bootstrap', location: `${appEndpoint}/core/pages/frontend/Bootstrap.vue`},
|
|
168
|
-
]},
|
|
169
|
-
]}
|
|
170
|
-
] },
|
|
171
|
-
{ path: '/:pathMatch(.*)*', name: '404', location: `${appEndpoint}/core/Page404.vue` }
|
|
172
|
-
|
|
173
|
-
]
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
} // end of Constants
|
|
177
|
-
|