alemonjs 2.1.85 → 2.1.87
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/lib/application/define-router.js +1 -0
- package/lib/application/runtime/client-runtime.d.ts +9 -1
- package/lib/application/runtime/client-runtime.js +9 -0
- package/lib/application/runtime/http/routers/hello.html.js +215 -137
- package/lib/application/runtime/http/routers/router.js +7 -7
- package/lib/application/runtime/load-modules/loadChild.js +67 -2
- package/lib/application/runtime/store.js +2 -2
- package/lib/common/react.js +4 -6
- package/lib/global.d.ts +6 -1
- package/package.json +1 -1
|
@@ -1 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import '../define-children.js';
|
|
2
|
+
import '../define-response.js';
|
|
3
|
+
import '../define-middleware.js';
|
|
4
|
+
import '../define-router.js';
|
|
5
|
+
import '../format/message-api.js';
|
|
6
|
+
import './event-response.js';
|
|
7
|
+
import './event-middleware.js';
|
|
8
|
+
import './event-utils.js';
|
|
9
|
+
import './event-group.js';
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
import '../define-children.js';
|
|
2
|
+
import '../define-response.js';
|
|
3
|
+
import '../define-middleware.js';
|
|
4
|
+
import '../define-router.js';
|
|
5
|
+
import '../format/message-api.js';
|
|
6
|
+
import './event-response.js';
|
|
7
|
+
import './event-middleware.js';
|
|
8
|
+
import './event-utils.js';
|
|
9
|
+
import './event-group.js';
|
|
1
10
|
import { cbpClient } from './cbp/connects/client.js';
|
|
2
11
|
import 'flatted';
|
|
3
12
|
import 'fs';
|
|
@@ -1,103 +1,135 @@
|
|
|
1
1
|
import { DOCTYPE, renderToString, createElement, Component, Html, Head, Title, Style, Body, Div, P } from '../../../../common/react.js';
|
|
2
2
|
|
|
3
|
-
const escapeHtml = (value) =>
|
|
3
|
+
const escapeHtml = (value) => {
|
|
4
|
+
return String(value).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');
|
|
5
|
+
};
|
|
4
6
|
const styles = `
|
|
5
7
|
:root {
|
|
6
|
-
--bg: #
|
|
7
|
-
--
|
|
8
|
-
--panel
|
|
8
|
+
--bg: #ece5d6;
|
|
9
|
+
--bg-deep: #e4dac6;
|
|
10
|
+
--panel: rgba(255, 251, 244, 0.76);
|
|
11
|
+
--panel-strong: rgba(255, 250, 242, 0.92);
|
|
9
12
|
--text: #17212b;
|
|
10
|
-
--muted: #
|
|
11
|
-
--line: rgba(
|
|
12
|
-
--
|
|
13
|
-
--accent
|
|
14
|
-
--
|
|
13
|
+
--muted: #667281;
|
|
14
|
+
--line: rgba(20, 29, 36, 0.09);
|
|
15
|
+
--line-strong: rgba(20, 29, 36, 0.16);
|
|
16
|
+
--accent: #cf6a2c;
|
|
17
|
+
--accent-strong: #9b4717;
|
|
18
|
+
--accent-soft: rgba(207, 106, 44, 0.16);
|
|
19
|
+
--shadow: 0 24px 80px rgba(49, 34, 17, 0.14);
|
|
20
|
+
--shadow-card: 0 18px 40px rgba(33, 37, 41, 0.08);
|
|
15
21
|
}
|
|
16
22
|
* { box-sizing: border-box; }
|
|
17
23
|
html, body { margin: 0; min-height: 100%; }
|
|
18
24
|
body {
|
|
19
|
-
font-family: "SF Pro Display", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
|
|
25
|
+
font-family: "Avenir Next", "SF Pro Display", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
|
|
20
26
|
color: var(--text);
|
|
21
27
|
background:
|
|
22
|
-
radial-gradient(circle at
|
|
23
|
-
radial-gradient(circle at
|
|
24
|
-
|
|
28
|
+
radial-gradient(circle at 12% 12%, rgba(207, 106, 44, 0.22), transparent 0 26%),
|
|
29
|
+
radial-gradient(circle at 88% 18%, rgba(69, 119, 104, 0.18), transparent 0 24%),
|
|
30
|
+
radial-gradient(circle at 50% 120%, rgba(33, 58, 78, 0.08), transparent 0 28%),
|
|
31
|
+
linear-gradient(180deg, #f8f4ec 0%, var(--bg) 48%, var(--bg-deep) 100%);
|
|
32
|
+
background-attachment: fixed;
|
|
33
|
+
}
|
|
34
|
+
body::before {
|
|
35
|
+
content: "";
|
|
36
|
+
position: fixed;
|
|
37
|
+
inset: 0;
|
|
38
|
+
background:
|
|
39
|
+
linear-gradient(rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.1)),
|
|
40
|
+
repeating-linear-gradient(
|
|
41
|
+
90deg,
|
|
42
|
+
transparent 0,
|
|
43
|
+
transparent 31px,
|
|
44
|
+
rgba(255, 255, 255, 0.18) 31px,
|
|
45
|
+
rgba(255, 255, 255, 0.18) 32px
|
|
46
|
+
);
|
|
47
|
+
opacity: 0.22;
|
|
48
|
+
pointer-events: none;
|
|
25
49
|
}
|
|
26
50
|
.page {
|
|
27
|
-
|
|
51
|
+
position: relative;
|
|
52
|
+
width: min(1520px, calc(100vw - 32px));
|
|
28
53
|
margin: 0 auto;
|
|
29
|
-
padding: clamp(
|
|
54
|
+
padding: clamp(24px, 3vw, 44px) 0 72px;
|
|
30
55
|
}
|
|
31
56
|
.hero {
|
|
32
57
|
position: relative;
|
|
33
58
|
overflow: hidden;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
59
|
+
isolation: isolate;
|
|
60
|
+
display: grid;
|
|
61
|
+
align-items: end;
|
|
62
|
+
min-height: clamp(240px, 32vw, 380px);
|
|
63
|
+
padding: clamp(28px, 4vw, 52px);
|
|
64
|
+
border-radius: 36px;
|
|
65
|
+
background:
|
|
66
|
+
linear-gradient(135deg, rgba(255, 250, 242, 0.84), rgba(247, 236, 220, 0.88)),
|
|
67
|
+
linear-gradient(180deg, rgba(255, 255, 255, 0.24), rgba(255, 255, 255, 0));
|
|
68
|
+
border: 1px solid rgba(255, 255, 255, 0.68);
|
|
38
69
|
box-shadow: var(--shadow);
|
|
70
|
+
backdrop-filter: blur(20px);
|
|
39
71
|
}
|
|
72
|
+
.hero::before,
|
|
40
73
|
.hero::after {
|
|
41
74
|
content: "";
|
|
42
75
|
position: absolute;
|
|
43
|
-
inset: auto -8% -48% auto;
|
|
44
|
-
width: min(38vw, 520px);
|
|
45
|
-
aspect-ratio: 1;
|
|
46
76
|
border-radius: 999px;
|
|
47
|
-
background: radial-gradient(circle, rgba(217, 108, 40, 0.18), transparent 62%);
|
|
48
77
|
pointer-events: none;
|
|
49
78
|
}
|
|
79
|
+
.hero::before {
|
|
80
|
+
inset: -18% auto auto -8%;
|
|
81
|
+
width: min(34vw, 420px);
|
|
82
|
+
aspect-ratio: 1;
|
|
83
|
+
background: radial-gradient(circle, rgba(244, 161, 85, 0.28), transparent 62%);
|
|
84
|
+
filter: blur(8px);
|
|
85
|
+
opacity: 0.95;
|
|
86
|
+
}
|
|
87
|
+
.hero::after {
|
|
88
|
+
inset: auto -8% -44% auto;
|
|
89
|
+
width: min(42vw, 560px);
|
|
90
|
+
aspect-ratio: 1;
|
|
91
|
+
background: radial-gradient(circle, rgba(49, 83, 104, 0.22), transparent 62%);
|
|
92
|
+
filter: blur(16px);
|
|
93
|
+
}
|
|
50
94
|
.hero-kicker {
|
|
51
|
-
|
|
52
|
-
|
|
95
|
+
position: relative;
|
|
96
|
+
z-index: 1;
|
|
97
|
+
display: inline-flex;
|
|
98
|
+
width: fit-content;
|
|
99
|
+
margin: 0 0 16px;
|
|
100
|
+
padding: 10px 14px;
|
|
101
|
+
border-radius: 999px;
|
|
102
|
+
border: 1px solid rgba(155, 71, 23, 0.14);
|
|
103
|
+
background: rgba(255, 255, 255, 0.62);
|
|
104
|
+
box-shadow: 0 8px 22px rgba(155, 71, 23, 0.08);
|
|
105
|
+
font-size: clamp(12px, 1vw, 14px);
|
|
53
106
|
letter-spacing: 0.18em;
|
|
54
107
|
text-transform: uppercase;
|
|
55
108
|
color: var(--accent-strong);
|
|
56
109
|
}
|
|
57
110
|
.hero-title {
|
|
111
|
+
position: relative;
|
|
112
|
+
z-index: 1;
|
|
58
113
|
margin: 0;
|
|
59
|
-
max-width:
|
|
60
|
-
font-size: clamp(
|
|
61
|
-
line-height: 0.
|
|
62
|
-
letter-spacing: -0.
|
|
63
|
-
|
|
64
|
-
.hero-desc {
|
|
65
|
-
margin: 18px 0 0;
|
|
66
|
-
max-width: 56rem;
|
|
67
|
-
font-size: clamp(18px, 2vw, 28px);
|
|
68
|
-
line-height: 1.6;
|
|
69
|
-
color: var(--muted);
|
|
70
|
-
}
|
|
71
|
-
.hero-meta {
|
|
72
|
-
display: flex;
|
|
73
|
-
flex-wrap: wrap;
|
|
74
|
-
gap: 14px;
|
|
75
|
-
margin-top: 28px;
|
|
76
|
-
}
|
|
77
|
-
.hero-pill {
|
|
78
|
-
display: inline-flex;
|
|
79
|
-
align-items: center;
|
|
80
|
-
gap: 10px;
|
|
81
|
-
padding: 12px 18px;
|
|
82
|
-
border-radius: 999px;
|
|
83
|
-
background: rgba(255, 255, 255, 0.78);
|
|
84
|
-
border: 1px solid rgba(23, 33, 43, 0.08);
|
|
85
|
-
font-size: clamp(14px, 1.4vw, 18px);
|
|
86
|
-
}
|
|
87
|
-
.hero-pill strong {
|
|
88
|
-
color: var(--accent-strong);
|
|
114
|
+
max-width: 9ch;
|
|
115
|
+
font-size: clamp(42px, 8vw, 96px);
|
|
116
|
+
line-height: 0.88;
|
|
117
|
+
letter-spacing: -0.06em;
|
|
118
|
+
text-wrap: balance;
|
|
89
119
|
}
|
|
90
120
|
.section-head {
|
|
91
121
|
display: flex;
|
|
92
122
|
align-items: end;
|
|
93
123
|
justify-content: space-between;
|
|
94
124
|
gap: 20px;
|
|
95
|
-
margin:
|
|
125
|
+
margin: 34px 0 22px;
|
|
96
126
|
padding: 0 6px;
|
|
97
127
|
}
|
|
98
128
|
.section-title {
|
|
99
129
|
margin: 0;
|
|
100
|
-
font-size: clamp(28px, 3vw,
|
|
130
|
+
font-size: clamp(28px, 3vw, 40px);
|
|
131
|
+
line-height: 1;
|
|
132
|
+
letter-spacing: -0.04em;
|
|
101
133
|
}
|
|
102
134
|
.section-note {
|
|
103
135
|
margin: 0;
|
|
@@ -106,27 +138,72 @@ const styles = `
|
|
|
106
138
|
}
|
|
107
139
|
.app-grid {
|
|
108
140
|
display: grid;
|
|
109
|
-
grid-template-columns: repeat(auto-fit, minmax(min(100%,
|
|
110
|
-
gap:
|
|
141
|
+
grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
|
|
142
|
+
gap: 20px;
|
|
111
143
|
}
|
|
112
144
|
.app-card {
|
|
145
|
+
position: relative;
|
|
113
146
|
display: flex;
|
|
114
147
|
flex-direction: column;
|
|
115
|
-
|
|
116
|
-
|
|
148
|
+
justify-content: space-between;
|
|
149
|
+
gap: 24px;
|
|
150
|
+
min-height: 240px;
|
|
117
151
|
padding: 24px;
|
|
118
|
-
border-radius:
|
|
152
|
+
border-radius: 30px;
|
|
119
153
|
text-decoration: none;
|
|
120
154
|
color: inherit;
|
|
121
|
-
background:
|
|
155
|
+
background:
|
|
156
|
+
linear-gradient(180deg, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.14)),
|
|
157
|
+
var(--panel);
|
|
122
158
|
border: 1px solid var(--line);
|
|
123
|
-
box-shadow:
|
|
124
|
-
|
|
159
|
+
box-shadow: var(--shadow-card);
|
|
160
|
+
backdrop-filter: blur(18px);
|
|
161
|
+
transition: transform 180ms ease, box-shadow 180ms ease, border-color 180ms ease, background 180ms ease;
|
|
162
|
+
}
|
|
163
|
+
.app-card::before,
|
|
164
|
+
.app-card::after {
|
|
165
|
+
content: "";
|
|
166
|
+
position: absolute;
|
|
167
|
+
pointer-events: none;
|
|
168
|
+
}
|
|
169
|
+
.app-card::before {
|
|
170
|
+
inset: 0;
|
|
171
|
+
border-radius: inherit;
|
|
172
|
+
padding: 1px;
|
|
173
|
+
background: linear-gradient(135deg, rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0), rgba(207, 106, 44, 0.12));
|
|
174
|
+
-webkit-mask:
|
|
175
|
+
linear-gradient(#000 0 0) content-box,
|
|
176
|
+
linear-gradient(#000 0 0);
|
|
177
|
+
-webkit-mask-composite: xor;
|
|
178
|
+
mask-composite: exclude;
|
|
179
|
+
opacity: 0.85;
|
|
180
|
+
}
|
|
181
|
+
.app-card::after {
|
|
182
|
+
top: -24%;
|
|
183
|
+
right: -10%;
|
|
184
|
+
width: 56%;
|
|
185
|
+
aspect-ratio: 1;
|
|
186
|
+
border-radius: 999px;
|
|
187
|
+
background: radial-gradient(circle, rgba(207, 106, 44, 0.16), transparent 68%);
|
|
188
|
+
transition: transform 180ms ease, opacity 180ms ease;
|
|
125
189
|
}
|
|
126
190
|
.app-card:hover {
|
|
127
|
-
transform: translateY(-
|
|
128
|
-
border-color: rgba(
|
|
129
|
-
box-shadow: 0
|
|
191
|
+
transform: translateY(-6px);
|
|
192
|
+
border-color: rgba(207, 106, 44, 0.3);
|
|
193
|
+
box-shadow: 0 28px 60px rgba(30, 37, 44, 0.14);
|
|
194
|
+
background:
|
|
195
|
+
linear-gradient(180deg, rgba(255, 255, 255, 0.62), rgba(255, 255, 255, 0.18)),
|
|
196
|
+
rgba(255, 251, 244, 0.92);
|
|
197
|
+
}
|
|
198
|
+
.app-card:hover::after {
|
|
199
|
+
transform: scale(1.08);
|
|
200
|
+
opacity: 1;
|
|
201
|
+
}
|
|
202
|
+
.app-card:nth-child(3n + 2)::after {
|
|
203
|
+
background: radial-gradient(circle, rgba(72, 122, 107, 0.18), transparent 68%);
|
|
204
|
+
}
|
|
205
|
+
.app-card:nth-child(3n + 3)::after {
|
|
206
|
+
background: radial-gradient(circle, rgba(53, 92, 128, 0.16), transparent 68%);
|
|
130
207
|
}
|
|
131
208
|
.app-card__top,
|
|
132
209
|
.app-card__bottom {
|
|
@@ -135,107 +212,114 @@ const styles = `
|
|
|
135
212
|
justify-content: space-between;
|
|
136
213
|
gap: 16px;
|
|
137
214
|
}
|
|
215
|
+
.app-card__top {
|
|
216
|
+
align-items: start;
|
|
217
|
+
}
|
|
138
218
|
.app-eyebrow {
|
|
139
|
-
|
|
140
|
-
|
|
219
|
+
display: inline-flex;
|
|
220
|
+
margin: 0 0 14px;
|
|
221
|
+
padding: 8px 12px;
|
|
222
|
+
border-radius: 999px;
|
|
223
|
+
background: rgba(255, 255, 255, 0.58);
|
|
224
|
+
border: 1px solid rgba(155, 71, 23, 0.1);
|
|
225
|
+
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.5);
|
|
226
|
+
font-size: 11px;
|
|
141
227
|
letter-spacing: 0.16em;
|
|
142
228
|
text-transform: uppercase;
|
|
143
229
|
color: var(--accent-strong);
|
|
144
230
|
}
|
|
145
231
|
.app-title {
|
|
146
232
|
margin: 0;
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
font-size: clamp(16px, 1.4vw, 20px);
|
|
153
|
-
line-height: 1.7;
|
|
154
|
-
color: var(--muted);
|
|
155
|
-
}
|
|
156
|
-
.app-tags {
|
|
157
|
-
display: flex;
|
|
158
|
-
flex-wrap: wrap;
|
|
159
|
-
gap: 10px;
|
|
160
|
-
}
|
|
161
|
-
.app-tag {
|
|
162
|
-
padding: 8px 12px;
|
|
163
|
-
border-radius: 999px;
|
|
164
|
-
background: rgba(217, 108, 40, 0.1);
|
|
165
|
-
color: var(--accent-strong);
|
|
166
|
-
font-size: 14px;
|
|
167
|
-
}
|
|
168
|
-
.app-rank {
|
|
169
|
-
min-width: 84px;
|
|
170
|
-
text-align: right;
|
|
233
|
+
max-width: 11ch;
|
|
234
|
+
font-size: clamp(28px, 2.8vw, 40px);
|
|
235
|
+
line-height: 0.95;
|
|
236
|
+
letter-spacing: -0.05em;
|
|
237
|
+
overflow-wrap: anywhere;
|
|
171
238
|
}
|
|
172
|
-
.app-rank__label,
|
|
173
239
|
.app-link {
|
|
174
240
|
display: block;
|
|
241
|
+
max-width: 100%;
|
|
242
|
+
font-family: "SF Mono", "ui-monospace", "Menlo", monospace;
|
|
175
243
|
font-size: 13px;
|
|
244
|
+
letter-spacing: 0.02em;
|
|
176
245
|
color: var(--muted);
|
|
177
|
-
|
|
178
|
-
.app-rank__value {
|
|
179
|
-
font-size: clamp(24px, 2vw, 30px);
|
|
180
|
-
font-weight: 700;
|
|
246
|
+
overflow-wrap: anywhere;
|
|
181
247
|
}
|
|
182
248
|
.app-action {
|
|
249
|
+
flex-shrink: 0;
|
|
183
250
|
padding: 12px 18px;
|
|
184
251
|
border-radius: 999px;
|
|
185
252
|
background: #1d2d38;
|
|
186
253
|
color: #fff;
|
|
187
|
-
|
|
254
|
+
border: 1px solid rgba(255, 255, 255, 0.14);
|
|
255
|
+
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
|
|
256
|
+
font-size: 14px;
|
|
257
|
+
letter-spacing: 0.08em;
|
|
258
|
+
text-transform: uppercase;
|
|
259
|
+
transition: transform 180ms ease, background 180ms ease;
|
|
260
|
+
}
|
|
261
|
+
.app-card:hover .app-action {
|
|
262
|
+
transform: translateX(2px);
|
|
263
|
+
background: #223746;
|
|
188
264
|
}
|
|
189
265
|
.empty-state {
|
|
190
|
-
padding: 32px;
|
|
191
|
-
border-radius:
|
|
192
|
-
background:
|
|
193
|
-
|
|
266
|
+
padding: 40px 32px;
|
|
267
|
+
border-radius: 30px;
|
|
268
|
+
background:
|
|
269
|
+
linear-gradient(180deg, rgba(255, 255, 255, 0.45), rgba(255, 255, 255, 0.12)),
|
|
270
|
+
var(--panel-strong);
|
|
271
|
+
border: 1px dashed var(--line-strong);
|
|
272
|
+
box-shadow: var(--shadow-card);
|
|
194
273
|
}
|
|
195
274
|
.empty-state__title {
|
|
196
275
|
margin: 0;
|
|
197
276
|
font-size: 24px;
|
|
277
|
+
letter-spacing: -0.03em;
|
|
198
278
|
}
|
|
199
279
|
.empty-state__desc {
|
|
200
280
|
margin: 10px 0 0;
|
|
201
281
|
color: var(--muted);
|
|
202
282
|
font-size: 16px;
|
|
283
|
+
line-height: 1.7;
|
|
203
284
|
}
|
|
204
285
|
@media (max-width: 820px) {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
.
|
|
286
|
+
body::before {
|
|
287
|
+
opacity: 0.12;
|
|
288
|
+
}
|
|
289
|
+
.page {
|
|
290
|
+
width: min(100vw - 20px, 100%);
|
|
291
|
+
padding-top: 18px;
|
|
292
|
+
}
|
|
293
|
+
.hero {
|
|
294
|
+
min-height: 220px;
|
|
295
|
+
border-radius: 26px;
|
|
296
|
+
padding: 22px;
|
|
297
|
+
}
|
|
298
|
+
.section-head {
|
|
299
|
+
align-items: start;
|
|
300
|
+
flex-direction: column;
|
|
301
|
+
margin-top: 28px;
|
|
302
|
+
}
|
|
303
|
+
.app-card {
|
|
304
|
+
min-height: 0;
|
|
305
|
+
padding: 20px;
|
|
306
|
+
border-radius: 24px;
|
|
307
|
+
}
|
|
209
308
|
.app-card__top,
|
|
210
|
-
.app-card__bottom {
|
|
211
|
-
|
|
309
|
+
.app-card__bottom {
|
|
310
|
+
align-items: start;
|
|
311
|
+
flex-direction: column;
|
|
312
|
+
}
|
|
313
|
+
.app-title {
|
|
314
|
+
max-width: none;
|
|
315
|
+
}
|
|
212
316
|
}
|
|
213
317
|
`;
|
|
214
318
|
const appHref = (app) => {
|
|
215
319
|
return app.kind === 'main' ? '/app/' : `/apps/${app.name}/`;
|
|
216
320
|
};
|
|
217
|
-
const appTags = (app) => {
|
|
218
|
-
const tags = [app.kind === 'main' ? '主应用' : '插件'];
|
|
219
|
-
if (app.capabilities.web) {
|
|
220
|
-
tags.push('页面');
|
|
221
|
-
}
|
|
222
|
-
if (app.capabilities.httpApi) {
|
|
223
|
-
tags.push('接口');
|
|
224
|
-
}
|
|
225
|
-
if (app.capabilities.event) {
|
|
226
|
-
tags.push('事件');
|
|
227
|
-
}
|
|
228
|
-
if (app.capabilities.expose) {
|
|
229
|
-
tags.push('Expose');
|
|
230
|
-
}
|
|
231
|
-
return tags;
|
|
232
|
-
};
|
|
233
321
|
const renderCardHtml = (app) => {
|
|
234
322
|
const href = appHref(app);
|
|
235
|
-
const tags = appTags(app)
|
|
236
|
-
.map(tag => `<span class="app-tag">${escapeHtml(tag)}</span>`)
|
|
237
|
-
.join('');
|
|
238
|
-
const desc = app.kind === 'main' ? '访问主应用页面、接口与默认资源。' : '访问插件页面、接口与公开入口。';
|
|
239
323
|
return `
|
|
240
324
|
<a
|
|
241
325
|
class="app-card"
|
|
@@ -249,13 +333,7 @@ const renderCardHtml = (app) => {
|
|
|
249
333
|
<p class="app-eyebrow">${app.kind === 'main' ? 'Main App' : 'Plugin App'}</p>
|
|
250
334
|
<h2 class="app-title">${escapeHtml(app.name)}</h2>
|
|
251
335
|
</div>
|
|
252
|
-
<div class="app-rank">
|
|
253
|
-
<span class="app-rank__label">热度</span>
|
|
254
|
-
<span class="app-rank__value" data-click-count>0</span>
|
|
255
|
-
</div>
|
|
256
336
|
</div>
|
|
257
|
-
<p class="app-desc">${escapeHtml(desc)}</p>
|
|
258
|
-
<div class="app-tags">${tags}</div>
|
|
259
337
|
<div class="app-card__bottom">
|
|
260
338
|
<span class="app-link">${escapeHtml(href)}</span>
|
|
261
339
|
<span class="app-action">进入</span>
|
|
@@ -352,7 +430,7 @@ class LaunchpadPage extends Component {
|
|
|
352
430
|
});
|
|
353
431
|
const cards = visibleApps.length ? visibleApps.map(renderCardHtml).join('') : renderEmptyHtml();
|
|
354
432
|
const script = renderLaunchpadScript(visibleApps);
|
|
355
|
-
return Html({ lang: 'zh-CN' }, Head(createElement('meta', { charset: 'utf-8' }), createElement('meta', { name: 'viewport', content: 'width=device-width, initial-scale=1, viewport-fit=cover' }), Title('ALemonJS 应用入口'), Style(styles)), Body(createElement('main', { className: 'page' }, createElement('section', { className: 'hero' }, P({ className: 'hero-kicker' }, 'ALemonJS Launchpad'), createElement('h1', { className: 'hero-title' }, '阿柠檬机器人')
|
|
433
|
+
return Html({ lang: 'zh-CN' }, Head(createElement('meta', { charset: 'utf-8' }), createElement('meta', { name: 'viewport', content: 'width=device-width, initial-scale=1, viewport-fit=cover' }), Title('ALemonJS 应用入口'), Style(styles)), Body(createElement('main', { className: 'page' }, createElement('section', { className: 'hero' }, P({ className: 'hero-kicker' }, 'ALemonJS Launchpad'), createElement('h1', { className: 'hero-title' }, '阿柠檬机器人')), createElement('section', null, Div({ className: 'section-head' }, Div(null, createElement('h2', { className: 'section-title' }, '应用列表'), P({ className: 'section-note' }, '点击次数越高,卡片排序越靠前。'))), Div({ className: 'app-grid', id: 'app-grid', dangerouslySetInnerHTML: { __html: cards } }))), createElement('script', { dangerouslySetInnerHTML: { __html: script } })));
|
|
356
434
|
}
|
|
357
435
|
}
|
|
358
436
|
const renderHelloHtml = (apps) => {
|
|
@@ -184,12 +184,12 @@ const dispatchAppKoaRouters = async (ctx, appName) => {
|
|
|
184
184
|
const afterMatched = Array.isArray(matchedContext.matched) ? matchedContext.matched.length : 0;
|
|
185
185
|
const afterMatchedRoute = ctx._matchedRoute;
|
|
186
186
|
const afterRouterPath = ctx.routerPath;
|
|
187
|
-
const handled = afterMatched > beforeMatched
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
187
|
+
const handled = afterMatched > beforeMatched ||
|
|
188
|
+
afterMatchedRoute !== beforeMatchedRoute ||
|
|
189
|
+
afterRouterPath !== beforeRouterPath ||
|
|
190
|
+
ctx.status !== beforeStatus ||
|
|
191
|
+
ctx.body !== beforeBody ||
|
|
192
|
+
!fallthrough;
|
|
193
193
|
if (!handled) {
|
|
194
194
|
continue;
|
|
195
195
|
}
|
|
@@ -237,7 +237,7 @@ const isNamespacedHtmlRequest = (ctx) => {
|
|
|
237
237
|
if (!ctx.path.startsWith('/apps/')) {
|
|
238
238
|
return false;
|
|
239
239
|
}
|
|
240
|
-
const [, , appName
|
|
240
|
+
const [, , appName] = ctx.path.split('/');
|
|
241
241
|
if (!appName) {
|
|
242
242
|
return false;
|
|
243
243
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { dirname, join } from 'path';
|
|
2
|
-
import { existsSync } from 'fs';
|
|
2
|
+
import { existsSync, readFileSync } from 'fs';
|
|
3
3
|
import { showErrorModule, getRecursiveDirFiles, createEventName } from '../../../common/utils.js';
|
|
4
4
|
import { registerRuntimeApp, updateRuntimeAppStatus, ChildrenApp, clearRuntimeAppKoaRouters, setRuntimeAppKoaRouters, updateRuntimeAppCapabilities } from '../store.js';
|
|
5
5
|
import { registerExpose } from '../../expose.js';
|
|
@@ -11,6 +11,50 @@ import { dispatchRuntimeStatusChange, dispatchAppDispose, dispatchAppReady } fro
|
|
|
11
11
|
const initRequire = () => { };
|
|
12
12
|
initRequire.resolve = () => '';
|
|
13
13
|
const require$1 = module$1?.createRequire?.(import.meta.url) ?? initRequire;
|
|
14
|
+
const resolvePackageDir = (appName) => {
|
|
15
|
+
const resolveWithPaths = require$1.resolve;
|
|
16
|
+
const candidatePaths = resolveWithPaths?.paths?.(appName) ?? [];
|
|
17
|
+
for (const basePath of candidatePaths) {
|
|
18
|
+
const packageDir = join(basePath, appName);
|
|
19
|
+
if (existsSync(join(packageDir, 'package.json'))) {
|
|
20
|
+
return packageDir;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
};
|
|
25
|
+
const resolvePackageEntryFromPackageJson = (packageDir) => {
|
|
26
|
+
const packageJsonPath = join(packageDir, 'package.json');
|
|
27
|
+
if (!existsSync(packageJsonPath)) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const pkg = JSON.parse(readFileSync(packageJsonPath, 'utf-8')) ?? {};
|
|
32
|
+
const exportsField = pkg?.exports;
|
|
33
|
+
let entry = null;
|
|
34
|
+
if (typeof exportsField === 'string') {
|
|
35
|
+
entry = exportsField;
|
|
36
|
+
}
|
|
37
|
+
else if (exportsField && typeof exportsField === 'object') {
|
|
38
|
+
const rootExport = exportsField['.'];
|
|
39
|
+
if (typeof rootExport === 'string') {
|
|
40
|
+
entry = rootExport;
|
|
41
|
+
}
|
|
42
|
+
else if (rootExport && typeof rootExport === 'object') {
|
|
43
|
+
entry = rootExport.import ?? rootExport.default ?? rootExport.require ?? null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (!entry) {
|
|
47
|
+
entry = pkg?.module ?? pkg?.main ?? 'index.js';
|
|
48
|
+
}
|
|
49
|
+
if (typeof entry !== 'string' || !entry.trim()) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
return join(packageDir, entry);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
14
58
|
const resolvePackageRoot = (startDir) => {
|
|
15
59
|
let currentDir = startDir;
|
|
16
60
|
while (currentDir && currentDir !== dirname(currentDir)) {
|
|
@@ -253,7 +297,14 @@ const loadChildrenFile = (appName) => {
|
|
|
253
297
|
return;
|
|
254
298
|
}
|
|
255
299
|
try {
|
|
256
|
-
|
|
300
|
+
let mainPath = require$1.resolve(appName);
|
|
301
|
+
if (!existsSync(mainPath)) {
|
|
302
|
+
const packageDir = resolvePackageDir(appName);
|
|
303
|
+
const fallbackMainPath = packageDir ? resolvePackageEntryFromPackageJson(packageDir) : null;
|
|
304
|
+
if (fallbackMainPath) {
|
|
305
|
+
mainPath = fallbackMainPath;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
257
308
|
if (!existsSync(mainPath)) {
|
|
258
309
|
updateRuntimeAppStatus(appName, 'failed', new Error('The main file does not exist,' + mainPath));
|
|
259
310
|
logger.error({
|
|
@@ -274,6 +325,20 @@ const loadChildrenFile = (appName) => {
|
|
|
274
325
|
void loadChildren(mainPath, appName);
|
|
275
326
|
}
|
|
276
327
|
catch (e) {
|
|
328
|
+
const packageDir = resolvePackageDir(appName);
|
|
329
|
+
const fallbackMainPath = packageDir ? resolvePackageEntryFromPackageJson(packageDir) : null;
|
|
330
|
+
if (fallbackMainPath && existsSync(fallbackMainPath)) {
|
|
331
|
+
registerRuntimeApp({
|
|
332
|
+
name: appName,
|
|
333
|
+
kind: 'plugin',
|
|
334
|
+
enabled: true,
|
|
335
|
+
status: 'discovered',
|
|
336
|
+
rootDir: dirname(fallbackMainPath),
|
|
337
|
+
mainPath: fallbackMainPath
|
|
338
|
+
});
|
|
339
|
+
void loadChildren(fallbackMainPath, appName);
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
277
342
|
updateRuntimeAppStatus(appName, 'failed', e);
|
|
278
343
|
showErrorModule(e);
|
|
279
344
|
}
|
|
@@ -107,8 +107,8 @@ const registerRuntimeApp = (record) => {
|
|
|
107
107
|
createdAt: current?.createdAt ?? now,
|
|
108
108
|
updatedAt: now
|
|
109
109
|
};
|
|
110
|
-
if (current?.status !== record.status) {
|
|
111
|
-
logRuntimeAppStatus(
|
|
110
|
+
if (current?.status !== record.status && process.env.NODE_ENV === 'development') {
|
|
111
|
+
logRuntimeAppStatus('debug', runtimeApps[record.name]);
|
|
112
112
|
}
|
|
113
113
|
return runtimeApps[record.name];
|
|
114
114
|
};
|
package/lib/common/react.js
CHANGED
|
@@ -102,7 +102,9 @@ function renderToString(vnode) {
|
|
|
102
102
|
if (voidTags.has(tag.toLowerCase())) {
|
|
103
103
|
return `<${tag}${attrs} />`;
|
|
104
104
|
}
|
|
105
|
-
const children = rawTextTags.has(tag.toLowerCase())
|
|
105
|
+
const children = rawTextTags.has(tag.toLowerCase())
|
|
106
|
+
? (vnode.children ?? []).map(renderRawText).join('')
|
|
107
|
+
: (vnode.children ?? []).map(renderToString).join('');
|
|
106
108
|
return `<${tag}${attrs}>${children}</${tag}>`;
|
|
107
109
|
}
|
|
108
110
|
function makeTag(tag) {
|
|
@@ -112,11 +114,7 @@ function makeTag(tag) {
|
|
|
112
114
|
!Array.isArray(first) &&
|
|
113
115
|
Object.prototype.toString.call(first) === '[object Object]' &&
|
|
114
116
|
('type' in first || 'children' in first);
|
|
115
|
-
const looksLikeProps = first !== null &&
|
|
116
|
-
typeof first === 'object' &&
|
|
117
|
-
!Array.isArray(first) &&
|
|
118
|
-
Object.prototype.toString.call(first) === '[object Object]' &&
|
|
119
|
-
!looksLikeVNode;
|
|
117
|
+
const looksLikeProps = first !== null && typeof first === 'object' && !Array.isArray(first) && Object.prototype.toString.call(first) === '[object Object]' && !looksLikeVNode;
|
|
120
118
|
if (looksLikeProps) {
|
|
121
119
|
return createElement(tag, first, ...restChildren);
|
|
122
120
|
}
|
package/lib/global.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DefineChildrenFunc, OnResponseReversalFunc, OnMiddlewareReversalFunc, OnSelectsFunc, OnDataFormatFunc, OnResponseReversalFuncBack, OnGroupFunc, OnMiddlewareReversalFuncBack, DefineResponseFunc, defineMiddlewareFunc, StoreChildrenApp, StateSubscribeMap, SubscribeKeysMap, LoggerUtils, ResponseState, StartOptions } from './types';
|
|
1
|
+
import type { DefineChildrenFunc, OnResponseReversalFunc, OnMiddlewareReversalFunc, OnSelectsFunc, OnDataFormatFunc, OnResponseReversalFuncBack, OnGroupFunc, OnMiddlewareReversalFuncBack, DefineResponseFunc, defineMiddlewareFunc, DefineRouterFunc, StoreChildrenApp, StateSubscribeMap, SubscribeKeysMap, LoggerUtils, ResponseState, StartOptions } from './types';
|
|
2
2
|
import { type Server } from 'ws';
|
|
3
3
|
import type WebSocket from 'ws';
|
|
4
4
|
import type { IncomingMessage } from 'http';
|
|
@@ -7,6 +7,9 @@ import type { RuntimeAppRecord } from './application/runtime/store.js';
|
|
|
7
7
|
declare global {
|
|
8
8
|
var __config: any;
|
|
9
9
|
var __options: StartOptions;
|
|
10
|
+
var __sandbox: boolean | undefined;
|
|
11
|
+
var __client_loaded: boolean | undefined;
|
|
12
|
+
var __publicIp: string | undefined;
|
|
10
13
|
var logger: LoggerUtils;
|
|
11
14
|
var alemonjsCore: {
|
|
12
15
|
storeState: ResponseState;
|
|
@@ -25,6 +28,7 @@ declare global {
|
|
|
25
28
|
var chatbotServer: Server<typeof WebSocket, typeof IncomingMessage>;
|
|
26
29
|
var chatbotPlatform: WebSocket;
|
|
27
30
|
var chatbotClient: WebSocket;
|
|
31
|
+
var testoneClient: WebSocket | undefined;
|
|
28
32
|
var onResponse: OnResponseReversalFunc;
|
|
29
33
|
var OnResponse: OnResponseReversalFuncBack;
|
|
30
34
|
var onMiddleware: OnMiddlewareReversalFunc;
|
|
@@ -32,6 +36,7 @@ declare global {
|
|
|
32
36
|
var defineChildren: DefineChildrenFunc;
|
|
33
37
|
var defineResponse: DefineResponseFunc;
|
|
34
38
|
var defineMiddleware: defineMiddlewareFunc;
|
|
39
|
+
var defineRouter: DefineRouterFunc;
|
|
35
40
|
var onSelects: OnSelectsFunc;
|
|
36
41
|
var format: OnDataFormatFunc;
|
|
37
42
|
var onGroup: OnGroupFunc;
|