@pactor-app/app 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +76 -0
- package/dist/index.cjs +680 -0
- package/dist/index.d.cts +278 -0
- package/dist/index.d.ts +278 -0
- package/dist/index.js +672 -0
- package/package.json +78 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,680 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
Application: () => Application,
|
|
24
|
+
DslPageLoader: () => DslPageLoader,
|
|
25
|
+
PageErrorBoundary: () => PageErrorBoundary,
|
|
26
|
+
ReactRouterBinding: () => ReactRouterBinding,
|
|
27
|
+
createPactorApplication: () => createPactorApplication
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(index_exports);
|
|
30
|
+
|
|
31
|
+
// src/application.ts
|
|
32
|
+
var import_core2 = require("@pactor-app/core");
|
|
33
|
+
var import_components = require("@pactor-app/ui/components");
|
|
34
|
+
var import_interaction = require("@pactor-app/ui/interaction");
|
|
35
|
+
var import_layout2 = require("@pactor-app/ui/layout");
|
|
36
|
+
var import_permission = require("@pactor-app/permission");
|
|
37
|
+
var import_resource = require("@pactor-app/resource");
|
|
38
|
+
var import_router2 = require("@pactor-app/router");
|
|
39
|
+
var import_runtime3 = require("@pactor-app/runtime");
|
|
40
|
+
var import_react5 = require("react");
|
|
41
|
+
var import_client = require("react-dom/client");
|
|
42
|
+
|
|
43
|
+
// src/app-shell.tsx
|
|
44
|
+
var import_core = require("@pactor-app/core");
|
|
45
|
+
var import_layout = require("@pactor-app/ui/layout");
|
|
46
|
+
var import_router = require("@pactor-app/router");
|
|
47
|
+
var import_react3 = require("@pactor-app/router/react");
|
|
48
|
+
var import_runtime2 = require("@pactor-app/runtime");
|
|
49
|
+
var import_react4 = require("react");
|
|
50
|
+
var import_react_router_dom = require("react-router-dom");
|
|
51
|
+
|
|
52
|
+
// src/feedback.tsx
|
|
53
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
54
|
+
var centerStyle = {
|
|
55
|
+
minHeight: "100vh",
|
|
56
|
+
display: "flex",
|
|
57
|
+
alignItems: "center",
|
|
58
|
+
justifyContent: "center"
|
|
59
|
+
};
|
|
60
|
+
function BootstrapSpinner({
|
|
61
|
+
style
|
|
62
|
+
}) {
|
|
63
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "pactor-app-spin", style: { ...centerStyle, ...style }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
64
|
+
"svg",
|
|
65
|
+
{
|
|
66
|
+
width: "32",
|
|
67
|
+
height: "32",
|
|
68
|
+
viewBox: "0 0 32 32",
|
|
69
|
+
role: "status",
|
|
70
|
+
"aria-label": "\u52A0\u8F7D\u4E2D",
|
|
71
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
72
|
+
"circle",
|
|
73
|
+
{
|
|
74
|
+
cx: "16",
|
|
75
|
+
cy: "16",
|
|
76
|
+
r: "12",
|
|
77
|
+
fill: "none",
|
|
78
|
+
stroke: "#1677ff",
|
|
79
|
+
strokeWidth: "3",
|
|
80
|
+
strokeLinecap: "round",
|
|
81
|
+
strokeDasharray: "56",
|
|
82
|
+
strokeDashoffset: "28",
|
|
83
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
84
|
+
"animateTransform",
|
|
85
|
+
{
|
|
86
|
+
attributeName: "transform",
|
|
87
|
+
type: "rotate",
|
|
88
|
+
from: "0 16 16",
|
|
89
|
+
to: "360 16 16",
|
|
90
|
+
dur: "0.8s",
|
|
91
|
+
repeatCount: "indefinite"
|
|
92
|
+
}
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
) });
|
|
98
|
+
}
|
|
99
|
+
function ResultView({
|
|
100
|
+
className,
|
|
101
|
+
title,
|
|
102
|
+
subTitle,
|
|
103
|
+
extra
|
|
104
|
+
}) {
|
|
105
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className, style: { ...centerStyle, padding: 24 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { textAlign: "center", maxWidth: 480 }, children: [
|
|
106
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontSize: 24, fontWeight: 600, marginBottom: 8 }, children: title }),
|
|
107
|
+
subTitle !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { color: "rgba(0, 0, 0, 0.45)", marginBottom: 16 }, children: subTitle }),
|
|
108
|
+
extra
|
|
109
|
+
] }) });
|
|
110
|
+
}
|
|
111
|
+
function PrimaryButton({
|
|
112
|
+
onClick,
|
|
113
|
+
children
|
|
114
|
+
}) {
|
|
115
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
116
|
+
"button",
|
|
117
|
+
{
|
|
118
|
+
type: "button",
|
|
119
|
+
onClick: () => onClick?.(),
|
|
120
|
+
style: {
|
|
121
|
+
padding: "6px 16px",
|
|
122
|
+
border: "none",
|
|
123
|
+
borderRadius: 6,
|
|
124
|
+
background: "#1677ff",
|
|
125
|
+
color: "#fff",
|
|
126
|
+
fontSize: 14,
|
|
127
|
+
cursor: "pointer"
|
|
128
|
+
},
|
|
129
|
+
children
|
|
130
|
+
}
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// src/page-loader.tsx
|
|
135
|
+
var import_runtime = require("@pactor-app/runtime");
|
|
136
|
+
var import_react2 = require("react");
|
|
137
|
+
|
|
138
|
+
// src/error-boundary.tsx
|
|
139
|
+
var import_react = require("react");
|
|
140
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
141
|
+
var PageErrorBoundary = class extends import_react.Component {
|
|
142
|
+
constructor() {
|
|
143
|
+
super(...arguments);
|
|
144
|
+
this.state = { error: null };
|
|
145
|
+
}
|
|
146
|
+
static getDerivedStateFromError(error) {
|
|
147
|
+
return { error };
|
|
148
|
+
}
|
|
149
|
+
componentDidCatch(error, info) {
|
|
150
|
+
console.error("[@pactor-app/app] \u9875\u9762\u6E32\u67D3\u5F02\u5E38", error, info.componentStack);
|
|
151
|
+
}
|
|
152
|
+
render() {
|
|
153
|
+
const { error } = this.state;
|
|
154
|
+
if (error !== null) {
|
|
155
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
156
|
+
ResultView,
|
|
157
|
+
{
|
|
158
|
+
className: "pactor-app-page-render-error",
|
|
159
|
+
title: "\u9875\u9762\u6E32\u67D3\u5F02\u5E38",
|
|
160
|
+
subTitle: error.message,
|
|
161
|
+
extra: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PrimaryButton, { onClick: () => this.setState({ error: null }), children: "\u91CD\u8BD5" })
|
|
162
|
+
}
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
return this.props.children;
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// src/page-loader.tsx
|
|
170
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
171
|
+
function DslPageLoader({ app, pageId, route }) {
|
|
172
|
+
const [state, setState] = (0, import_react2.useState)({ status: "loading" });
|
|
173
|
+
const [retryTick, setRetryTick] = (0, import_react2.useState)(0);
|
|
174
|
+
(0, import_react2.useEffect)(() => {
|
|
175
|
+
let cancelled = false;
|
|
176
|
+
let runtime = null;
|
|
177
|
+
void (async () => {
|
|
178
|
+
try {
|
|
179
|
+
const pageDsl = await app.resolvePage(pageId);
|
|
180
|
+
if (cancelled) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
runtime = app.createPageRuntime(pageDsl, route);
|
|
184
|
+
setState({ status: "ready", runtime });
|
|
185
|
+
void runtime.ready();
|
|
186
|
+
void runtime.show();
|
|
187
|
+
} catch (cause) {
|
|
188
|
+
if (!cancelled) {
|
|
189
|
+
setState({
|
|
190
|
+
status: "error",
|
|
191
|
+
error: cause instanceof Error ? cause : new Error(String(cause))
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
})();
|
|
196
|
+
return () => {
|
|
197
|
+
cancelled = true;
|
|
198
|
+
if (runtime !== null && !runtime.destroyed) {
|
|
199
|
+
void runtime.hide();
|
|
200
|
+
void runtime.destroy();
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
}, [app, pageId, retryTick]);
|
|
204
|
+
if (state.status === "loading") {
|
|
205
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "pactor-app-page-loading", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(BootstrapSpinner, { style: { minHeight: 0, padding: 48 } }) });
|
|
206
|
+
}
|
|
207
|
+
if (state.status === "error") {
|
|
208
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
209
|
+
ResultView,
|
|
210
|
+
{
|
|
211
|
+
className: "pactor-app-page-load-error",
|
|
212
|
+
title: "\u9875\u9762\u52A0\u8F7D\u5931\u8D25",
|
|
213
|
+
subTitle: state.error.message,
|
|
214
|
+
extra: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PrimaryButton, { onClick: () => setRetryTick((n) => n + 1), children: "\u91CD\u8BD5" })
|
|
215
|
+
}
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
const OverlayHostView = app.interactionKit.OverlayHost;
|
|
219
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PageErrorBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_runtime.PageRuntimeView, { runtime: state.runtime, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
220
|
+
OverlayHostView,
|
|
221
|
+
{
|
|
222
|
+
manager: app.overlayManager,
|
|
223
|
+
resolvePage: app.resolvePage
|
|
224
|
+
}
|
|
225
|
+
) }) });
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// src/app-shell.tsx
|
|
229
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
230
|
+
function Application({ app }) {
|
|
231
|
+
const [state, setState] = (0, import_react4.useState)({ status: "loading" });
|
|
232
|
+
const [retryTick, setRetryTick] = (0, import_react4.useState)(0);
|
|
233
|
+
(0, import_react4.useEffect)(() => {
|
|
234
|
+
let cancelled = false;
|
|
235
|
+
void app.loadSession().then(
|
|
236
|
+
(session) => {
|
|
237
|
+
if (!cancelled) {
|
|
238
|
+
setState({ status: "ready", session });
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
(cause) => {
|
|
242
|
+
if (!cancelled) {
|
|
243
|
+
setState({
|
|
244
|
+
status: "error",
|
|
245
|
+
error: cause instanceof Error ? cause : new Error(String(cause))
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
);
|
|
250
|
+
return () => {
|
|
251
|
+
cancelled = true;
|
|
252
|
+
};
|
|
253
|
+
}, [app, retryTick]);
|
|
254
|
+
if (state.status === "loading") {
|
|
255
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "pactor-app-bootstrap-loading", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(BootstrapSpinner, {}) });
|
|
256
|
+
}
|
|
257
|
+
if (state.status === "error") {
|
|
258
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
259
|
+
ResultView,
|
|
260
|
+
{
|
|
261
|
+
className: "pactor-app-bootstrap-error",
|
|
262
|
+
title: "\u5E94\u7528\u542F\u52A8\u5931\u8D25",
|
|
263
|
+
subTitle: state.error.message,
|
|
264
|
+
extra: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PrimaryButton, { onClick: () => setRetryTick((n) => n + 1), children: "\u91CD\u8BD5" })
|
|
265
|
+
}
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AppShell, { app, session: state.session });
|
|
269
|
+
}
|
|
270
|
+
function AppShell({
|
|
271
|
+
app,
|
|
272
|
+
session
|
|
273
|
+
}) {
|
|
274
|
+
const Router = app.routerOptions.type === "hash" ? import_react_router_dom.HashRouter : import_react_router_dom.BrowserRouter;
|
|
275
|
+
const InteractionKit = app.interactionKit.Provider;
|
|
276
|
+
const Providers = app.providers;
|
|
277
|
+
const i18n = (0, import_core.createI18nContext)({
|
|
278
|
+
locale: session.locale,
|
|
279
|
+
defaultLocale: session.defaultLocale,
|
|
280
|
+
messages: session.messages
|
|
281
|
+
});
|
|
282
|
+
const shell = /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_runtime2.I18nContextProvider, { value: i18n, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(InteractionKit, { bridge: app.uiBridge, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ShellLayout, { app, session }) }) });
|
|
283
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Router, { basename: app.routerOptions.basename, children: [
|
|
284
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RouterBridgeSync, { binding: app.navigation }),
|
|
285
|
+
Providers !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Providers, { children: shell }) : shell
|
|
286
|
+
] });
|
|
287
|
+
}
|
|
288
|
+
function RouterBridgeSync({ binding }) {
|
|
289
|
+
const bridge = (0, import_react3.useReactRouterBridge)();
|
|
290
|
+
const location = (0, import_react_router_dom.useLocation)();
|
|
291
|
+
(0, import_react4.useEffect)(() => {
|
|
292
|
+
binding.bind(bridge, {
|
|
293
|
+
pathname: location.pathname,
|
|
294
|
+
search: location.search
|
|
295
|
+
});
|
|
296
|
+
}, [bridge, binding]);
|
|
297
|
+
(0, import_react4.useEffect)(() => {
|
|
298
|
+
binding.sync({ pathname: location.pathname, search: location.search });
|
|
299
|
+
}, [binding, location.pathname, location.search]);
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
function ShellLayout({
|
|
303
|
+
app,
|
|
304
|
+
session
|
|
305
|
+
}) {
|
|
306
|
+
const location = (0, import_react_router_dom.useLocation)();
|
|
307
|
+
const route = (0, import_router.resolveRoute)(session.menuRegistry, {
|
|
308
|
+
pathname: location.pathname,
|
|
309
|
+
search: location.search
|
|
310
|
+
});
|
|
311
|
+
const LayoutComponent = (0, import_layout.resolveLayout)(app.layoutRegistry, session.layoutType);
|
|
312
|
+
const outlet = /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_router_dom.Routes, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
313
|
+
import_react_router_dom.Route,
|
|
314
|
+
{
|
|
315
|
+
path: "*",
|
|
316
|
+
element: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
317
|
+
import_react3.DynamicDslRoute,
|
|
318
|
+
{
|
|
319
|
+
registry: session.menuRegistry,
|
|
320
|
+
permissionChecker: app.permissionStore,
|
|
321
|
+
fallback: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(NotFoundPage, {}),
|
|
322
|
+
forbidden: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ForbiddenPage, {}),
|
|
323
|
+
render: ({ pageId, route: pageRoute }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
324
|
+
DslPageLoader,
|
|
325
|
+
{
|
|
326
|
+
app,
|
|
327
|
+
pageId,
|
|
328
|
+
route: pageRoute
|
|
329
|
+
},
|
|
330
|
+
pageLoaderKey(pageId, pageRoute)
|
|
331
|
+
)
|
|
332
|
+
}
|
|
333
|
+
)
|
|
334
|
+
}
|
|
335
|
+
) });
|
|
336
|
+
if (session.layoutType === "admin") {
|
|
337
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
338
|
+
LayoutComponent,
|
|
339
|
+
{
|
|
340
|
+
config: session.layoutConfig,
|
|
341
|
+
brand: session.brand,
|
|
342
|
+
registry: session.menuRegistry,
|
|
343
|
+
bridge: app.navigation,
|
|
344
|
+
route: route ?? void 0,
|
|
345
|
+
permissionChecker: app.permissionStore,
|
|
346
|
+
headerExtra: app.headerExtra,
|
|
347
|
+
children: outlet
|
|
348
|
+
}
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LayoutComponent, { brand: session.brand, children: outlet });
|
|
352
|
+
}
|
|
353
|
+
function pageLoaderKey(pageId, route) {
|
|
354
|
+
return `${pageId}|${JSON.stringify(route.params)}|${JSON.stringify(route.query)}`;
|
|
355
|
+
}
|
|
356
|
+
function NotFoundPage() {
|
|
357
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
358
|
+
ResultView,
|
|
359
|
+
{
|
|
360
|
+
className: "pactor-app-not-found",
|
|
361
|
+
title: "404",
|
|
362
|
+
subTitle: "\u9875\u9762\u4E0D\u5B58\u5728\u6216\u5C1A\u672A\u6CE8\u518C"
|
|
363
|
+
}
|
|
364
|
+
);
|
|
365
|
+
}
|
|
366
|
+
function ForbiddenPage() {
|
|
367
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
368
|
+
ResultView,
|
|
369
|
+
{
|
|
370
|
+
className: "pactor-app-forbidden",
|
|
371
|
+
title: "403",
|
|
372
|
+
subTitle: "\u6CA1\u6709\u8BBF\u95EE\u8BE5\u9875\u9762\u7684\u6743\u9650"
|
|
373
|
+
}
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// src/application.ts
|
|
378
|
+
var ReactRouterBinding = class {
|
|
379
|
+
constructor() {
|
|
380
|
+
this.location = { pathname: "/", search: "" };
|
|
381
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
382
|
+
}
|
|
383
|
+
/** 绑定真实桥接与初始 location(RouterBridgeSync 挂载时调用) */
|
|
384
|
+
bind(delegate, initial) {
|
|
385
|
+
this.delegate = delegate;
|
|
386
|
+
this.location = initial;
|
|
387
|
+
}
|
|
388
|
+
/** location 变化同步并通知订阅者 */
|
|
389
|
+
sync(location) {
|
|
390
|
+
this.location = location;
|
|
391
|
+
for (const listener of [...this.listeners]) {
|
|
392
|
+
listener(location);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
getLocation() {
|
|
396
|
+
return this.location;
|
|
397
|
+
}
|
|
398
|
+
push(to) {
|
|
399
|
+
if (this.delegate === void 0) {
|
|
400
|
+
console.warn(`[@pactor-app/app] \u8DEF\u7531\u5C1A\u672A\u6302\u8F7D\uFF0Cpush("${to}") \u5DF2\u5FFD\u7565`);
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
this.delegate.push(to);
|
|
404
|
+
}
|
|
405
|
+
replace(to) {
|
|
406
|
+
if (this.delegate === void 0) {
|
|
407
|
+
console.warn(`[@pactor-app/app] \u8DEF\u7531\u5C1A\u672A\u6302\u8F7D\uFF0Creplace("${to}") \u5DF2\u5FFD\u7565`);
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
this.delegate.replace(to);
|
|
411
|
+
}
|
|
412
|
+
subscribe(listener) {
|
|
413
|
+
this.listeners.add(listener);
|
|
414
|
+
return () => {
|
|
415
|
+
this.listeners.delete(listener);
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
};
|
|
419
|
+
function isRecord(value) {
|
|
420
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
421
|
+
}
|
|
422
|
+
function upsert(registry, name, item) {
|
|
423
|
+
if (registry.has(name)) {
|
|
424
|
+
registry.unregister(name);
|
|
425
|
+
}
|
|
426
|
+
registry.register(name, item);
|
|
427
|
+
}
|
|
428
|
+
function upsertAll(registry, entries) {
|
|
429
|
+
for (const [name, item] of Object.entries(entries ?? {})) {
|
|
430
|
+
upsert(registry, name, item);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
function createResourceHttpAdapter(authTokenProvider) {
|
|
434
|
+
const base = (0, import_resource.createFetchAdapter)();
|
|
435
|
+
if (authTokenProvider === void 0) {
|
|
436
|
+
return base;
|
|
437
|
+
}
|
|
438
|
+
return async (request) => {
|
|
439
|
+
const token = await authTokenProvider();
|
|
440
|
+
if (token === void 0 || token === "") {
|
|
441
|
+
return base(request);
|
|
442
|
+
}
|
|
443
|
+
return base({
|
|
444
|
+
...request,
|
|
445
|
+
headers: { ...request.headers, authorization: `Bearer ${token}` }
|
|
446
|
+
});
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
function createRuntimeHttpAdapter(authTokenProvider) {
|
|
450
|
+
const base = (0, import_runtime3.createFetchHttpAdapter)();
|
|
451
|
+
if (authTokenProvider === void 0) {
|
|
452
|
+
return base;
|
|
453
|
+
}
|
|
454
|
+
return {
|
|
455
|
+
async request(config) {
|
|
456
|
+
const token = await authTokenProvider();
|
|
457
|
+
if (token === void 0 || token === "") {
|
|
458
|
+
return base.request(config);
|
|
459
|
+
}
|
|
460
|
+
return base.request({
|
|
461
|
+
...config,
|
|
462
|
+
headers: { ...config.headers, authorization: `Bearer ${token}` }
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
var MENU_TYPES = /* @__PURE__ */ new Set(["group", "page", "link"]);
|
|
468
|
+
function sanitizeMenus(raw) {
|
|
469
|
+
if (!Array.isArray(raw)) {
|
|
470
|
+
return [];
|
|
471
|
+
}
|
|
472
|
+
const menus = [];
|
|
473
|
+
for (const item of raw) {
|
|
474
|
+
if (!isRecord(item) || typeof item["id"] !== "string") {
|
|
475
|
+
continue;
|
|
476
|
+
}
|
|
477
|
+
const menu = item;
|
|
478
|
+
menus.push({
|
|
479
|
+
...menu,
|
|
480
|
+
title: typeof item["title"] === "string" ? item["title"] : menu.id,
|
|
481
|
+
type: MENU_TYPES.has(menu.type) ? menu.type : "page",
|
|
482
|
+
children: item["children"] !== void 0 ? sanitizeMenus(item["children"]) : void 0
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
return menus;
|
|
486
|
+
}
|
|
487
|
+
var LAYOUT_MODES = ["top-side", "top-bottom", "side-full", "two-column"];
|
|
488
|
+
var LAYOUT_BREAKPOINTS = ["xs", "sm", "md", "lg", "xl", "xxl"];
|
|
489
|
+
function pickLayoutConfig(layout) {
|
|
490
|
+
const config = {};
|
|
491
|
+
for (const key of [
|
|
492
|
+
"header",
|
|
493
|
+
"sidebar",
|
|
494
|
+
"tabs",
|
|
495
|
+
"breadcrumb",
|
|
496
|
+
"footer",
|
|
497
|
+
"fixedHeader",
|
|
498
|
+
"fixedSider",
|
|
499
|
+
"collapsible",
|
|
500
|
+
"collapsed"
|
|
501
|
+
]) {
|
|
502
|
+
const value = layout?.[key];
|
|
503
|
+
if (typeof value === "boolean") {
|
|
504
|
+
config[key] = value;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
const mode = layout?.["mode"];
|
|
508
|
+
if (typeof mode === "string" && LAYOUT_MODES.includes(mode)) {
|
|
509
|
+
config.mode = mode;
|
|
510
|
+
}
|
|
511
|
+
const breakpoint = layout?.["breakpoint"];
|
|
512
|
+
if (typeof breakpoint === "string" && LAYOUT_BREAKPOINTS.includes(breakpoint)) {
|
|
513
|
+
config.breakpoint = breakpoint;
|
|
514
|
+
}
|
|
515
|
+
return config;
|
|
516
|
+
}
|
|
517
|
+
function createPactorApplication(options) {
|
|
518
|
+
if (typeof options.appId !== "string" || options.appId === "") {
|
|
519
|
+
throw new Error("[@pactor-app/app] createPactorApplication: appId \u5FC5\u586B");
|
|
520
|
+
}
|
|
521
|
+
const { appId } = options;
|
|
522
|
+
const routerOptions = options.router ?? {};
|
|
523
|
+
const overlayManager = new import_interaction.OverlayManager();
|
|
524
|
+
const uiBridge = (0, import_interaction.createUiBridge)();
|
|
525
|
+
const permissionStore = new import_permission.PermissionStore();
|
|
526
|
+
const layoutRegistry = (options.layoutRegistry ?? options.ui?.layoutRegistry)?.() ?? (0, import_layout2.createShadcnLayoutRegistry)();
|
|
527
|
+
const interactionKit = options.interactionKit ?? options.ui?.interactionKit ?? {
|
|
528
|
+
Provider: import_interaction.ShadcnInteractionProvider,
|
|
529
|
+
OverlayHost: import_interaction.ShadcnOverlayHost
|
|
530
|
+
};
|
|
531
|
+
const navigation = new ReactRouterBinding();
|
|
532
|
+
const loader = options.loader ?? new import_resource.HttpDslResourceLoader({
|
|
533
|
+
baseUrl: options.api?.baseURL,
|
|
534
|
+
adapter: createResourceHttpAdapter(options.authTokenProvider)
|
|
535
|
+
});
|
|
536
|
+
const httpAdapter = createRuntimeHttpAdapter(options.authTokenProvider);
|
|
537
|
+
const permissionAdapter = (0, import_permission.createPermissionAdapter)(permissionStore);
|
|
538
|
+
const routerAdapter = (0, import_router2.createRouterAdapter)(navigation);
|
|
539
|
+
const components = (options.componentRegistry ?? options.ui?.componentRegistry)?.() ?? (0, import_components.createShadcnComponentRegistry)();
|
|
540
|
+
upsertAll(components, options.components);
|
|
541
|
+
const actions = new import_core2.Registry("ActionRegistry");
|
|
542
|
+
(0, import_interaction.registerInteractionActions)(actions, overlayManager, uiBridge);
|
|
543
|
+
upsert(actions, "navigate", (action) => {
|
|
544
|
+
const to = action.params?.["to"];
|
|
545
|
+
if (typeof to !== "string" || to === "") {
|
|
546
|
+
return {
|
|
547
|
+
ok: false,
|
|
548
|
+
error: new Error("[@pactor-app/app] navigate \u52A8\u4F5C\u7F3A\u5C11 params.to\uFF08string\uFF09")
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
navigation.push(to);
|
|
552
|
+
return { ok: true };
|
|
553
|
+
});
|
|
554
|
+
upsertAll(actions, options.actions);
|
|
555
|
+
const services = new import_core2.Registry("ServiceRegistry");
|
|
556
|
+
upsertAll(services, options.services);
|
|
557
|
+
const capabilities = new import_core2.Registry("CapabilityRegistry");
|
|
558
|
+
upsertAll(capabilities, options.capabilities);
|
|
559
|
+
let session = null;
|
|
560
|
+
const handle = {
|
|
561
|
+
appId,
|
|
562
|
+
overlayManager,
|
|
563
|
+
uiBridge,
|
|
564
|
+
permissionStore,
|
|
565
|
+
layoutRegistry,
|
|
566
|
+
interactionKit,
|
|
567
|
+
routerOptions,
|
|
568
|
+
providers: options.providers,
|
|
569
|
+
headerExtra: options.headerExtra,
|
|
570
|
+
navigation,
|
|
571
|
+
async loadSession() {
|
|
572
|
+
const bootstrap = await loader.loadBootstrap();
|
|
573
|
+
permissionStore.setPermissions(
|
|
574
|
+
Array.isArray(bootstrap.permissions) ? bootstrap.permissions.filter(
|
|
575
|
+
(code) => typeof code === "string"
|
|
576
|
+
) : []
|
|
577
|
+
);
|
|
578
|
+
const menuRegistry = new import_router2.MenuRegistry(sanitizeMenus(bootstrap.menus));
|
|
579
|
+
const layout = isRecord(bootstrap.layout) ? bootstrap.layout : void 0;
|
|
580
|
+
const layoutType = options.layout ?? (typeof layout?.["type"] === "string" ? layout["type"] : void 0) ?? "admin";
|
|
581
|
+
const appRecord = {
|
|
582
|
+
id: appId,
|
|
583
|
+
...isRecord(bootstrap.app) ? bootstrap.app : {}
|
|
584
|
+
};
|
|
585
|
+
const brand = options.brand ?? {
|
|
586
|
+
title: typeof appRecord["name"] === "string" ? appRecord["name"] : appId,
|
|
587
|
+
logo: void 0
|
|
588
|
+
};
|
|
589
|
+
const browserLocale = typeof navigator !== "undefined" && typeof navigator.language === "string" ? navigator.language : "zh-CN";
|
|
590
|
+
const locale = options.locale ?? (typeof bootstrap.locale === "string" ? bootstrap.locale : void 0) ?? browserLocale;
|
|
591
|
+
const defaultLocale = options.defaultLocale ?? (typeof bootstrap.defaultLocale === "string" ? bootstrap.defaultLocale : void 0) ?? "zh-CN";
|
|
592
|
+
const messages = options.messages ?? (isRecord(bootstrap.messages) ? bootstrap.messages : void 0) ?? {};
|
|
593
|
+
const next = {
|
|
594
|
+
bootstrap,
|
|
595
|
+
menuRegistry,
|
|
596
|
+
layoutType,
|
|
597
|
+
layoutConfig: pickLayoutConfig(layout),
|
|
598
|
+
brand,
|
|
599
|
+
user: isRecord(bootstrap.user) ? bootstrap.user : {},
|
|
600
|
+
app: appRecord,
|
|
601
|
+
locale,
|
|
602
|
+
defaultLocale,
|
|
603
|
+
messages
|
|
604
|
+
};
|
|
605
|
+
session = next;
|
|
606
|
+
return next;
|
|
607
|
+
},
|
|
608
|
+
createPageRuntime(pageDsl, route) {
|
|
609
|
+
return (0, import_runtime3.createPageRuntime)(pageDsl, {
|
|
610
|
+
components,
|
|
611
|
+
actions,
|
|
612
|
+
services,
|
|
613
|
+
capabilities,
|
|
614
|
+
permission: permissionAdapter,
|
|
615
|
+
router: routerAdapter,
|
|
616
|
+
http: httpAdapter,
|
|
617
|
+
route: { params: route.params, query: route.query },
|
|
618
|
+
user: session?.user ?? {},
|
|
619
|
+
app: session?.app ?? { id: appId },
|
|
620
|
+
locale: session?.locale ?? "zh-CN",
|
|
621
|
+
defaultLocale: session?.defaultLocale ?? "zh-CN",
|
|
622
|
+
messages: session?.messages ?? {}
|
|
623
|
+
});
|
|
624
|
+
},
|
|
625
|
+
async resolvePage(pageId) {
|
|
626
|
+
const resource = await loader.loadPage(pageId);
|
|
627
|
+
return resource.schema;
|
|
628
|
+
}
|
|
629
|
+
};
|
|
630
|
+
let root = null;
|
|
631
|
+
return {
|
|
632
|
+
appId,
|
|
633
|
+
mount(selector) {
|
|
634
|
+
const target = document.querySelector(selector);
|
|
635
|
+
if (target === null) {
|
|
636
|
+
throw new Error(`[@pactor-app/app] mount \u76EE\u6807\u5143\u7D20\u4E0D\u5B58\u5728: ${selector}`);
|
|
637
|
+
}
|
|
638
|
+
if (root !== null) {
|
|
639
|
+
root.unmount();
|
|
640
|
+
root = null;
|
|
641
|
+
}
|
|
642
|
+
root = (0, import_client.createRoot)(target);
|
|
643
|
+
root.render((0, import_react5.createElement)(Application, { app: handle }));
|
|
644
|
+
},
|
|
645
|
+
unmount() {
|
|
646
|
+
if (root !== null) {
|
|
647
|
+
root.unmount();
|
|
648
|
+
root = null;
|
|
649
|
+
}
|
|
650
|
+
},
|
|
651
|
+
registerComponent(name, component) {
|
|
652
|
+
upsert(components, name, component);
|
|
653
|
+
},
|
|
654
|
+
registerAction(name, handler) {
|
|
655
|
+
upsert(actions, name, handler);
|
|
656
|
+
},
|
|
657
|
+
registerService(name, handler) {
|
|
658
|
+
upsert(services, name, handler);
|
|
659
|
+
},
|
|
660
|
+
registerCapability(name, capability) {
|
|
661
|
+
upsert(capabilities, name, capability);
|
|
662
|
+
},
|
|
663
|
+
setLocale(locale, messages) {
|
|
664
|
+
if (session === null) {
|
|
665
|
+
console.warn("[@pactor-app/app] setLocale \u5728 bootstrap \u5B8C\u6210\u524D\u8C03\u7528\u5DF2\u5FFD\u7565");
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
session = { ...session, locale, messages: messages ?? session.messages };
|
|
669
|
+
window.location.reload();
|
|
670
|
+
}
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
674
|
+
0 && (module.exports = {
|
|
675
|
+
Application,
|
|
676
|
+
DslPageLoader,
|
|
677
|
+
PageErrorBoundary,
|
|
678
|
+
ReactRouterBinding,
|
|
679
|
+
createPactorApplication
|
|
680
|
+
});
|