@finesoft/front 0.1.13 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app-MYBG3TGV.js +10 -0
- package/dist/app-MYBG3TGV.js.map +1 -0
- package/dist/browser.js +12 -10
- package/dist/chunk-2VETWTN5.js +88 -0
- package/dist/chunk-2VETWTN5.js.map +1 -0
- package/dist/chunk-FYP2ZYYV.js +25 -0
- package/dist/chunk-FYP2ZYYV.js.map +1 -0
- package/dist/{chunk-OVGQ4NUA.js → chunk-RVKDILGM.js} +2 -327
- package/dist/chunk-RVKDILGM.js.map +1 -0
- package/dist/chunk-T2AQHAYK.js +337 -0
- package/dist/chunk-T2AQHAYK.js.map +1 -0
- package/dist/chunk-Z4MHYAS3.js +108 -0
- package/dist/chunk-Z4MHYAS3.js.map +1 -0
- package/dist/index.cjs +1788 -839
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +202 -1
- package/dist/index.d.ts +202 -1
- package/dist/index.js +693 -180
- package/dist/index.js.map +1 -1
- package/dist/locale-YK3THSI6.js +7 -0
- package/dist/locale-YK3THSI6.js.map +1 -0
- package/dist/src-7D236CLJ.js +19 -0
- package/dist/src-7D236CLJ.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-OVGQ4NUA.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __esm = (fn, res) => function __init() {
|
|
9
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
10
|
+
};
|
|
8
11
|
var __export = (target, all) => {
|
|
9
12
|
for (var name in all)
|
|
10
13
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -27,75 +30,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
30
|
));
|
|
28
31
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
32
|
|
|
30
|
-
// src/index.ts
|
|
31
|
-
var index_exports = {};
|
|
32
|
-
__export(index_exports, {
|
|
33
|
-
ACTION_KINDS: () => ACTION_KINDS,
|
|
34
|
-
ActionDispatcher: () => ActionDispatcher,
|
|
35
|
-
BaseController: () => BaseController,
|
|
36
|
-
BaseLogger: () => BaseLogger,
|
|
37
|
-
CompositeLogger: () => CompositeLogger,
|
|
38
|
-
CompositeLoggerFactory: () => CompositeLoggerFactory,
|
|
39
|
-
ConsoleLogger: () => ConsoleLogger,
|
|
40
|
-
ConsoleLoggerFactory: () => ConsoleLoggerFactory,
|
|
41
|
-
Container: () => Container,
|
|
42
|
-
DEP_KEYS: () => DEP_KEYS,
|
|
43
|
-
Framework: () => Framework,
|
|
44
|
-
History: () => History,
|
|
45
|
-
HttpClient: () => HttpClient,
|
|
46
|
-
HttpError: () => HttpError,
|
|
47
|
-
IntentDispatcher: () => IntentDispatcher,
|
|
48
|
-
LruMap: () => LruMap,
|
|
49
|
-
PrefetchedIntents: () => PrefetchedIntents,
|
|
50
|
-
Router: () => Router,
|
|
51
|
-
SSR_PLACEHOLDERS: () => SSR_PLACEHOLDERS,
|
|
52
|
-
buildUrl: () => buildUrl,
|
|
53
|
-
createPrefetchedIntentsFromDom: () => createPrefetchedIntentsFromDom,
|
|
54
|
-
createSSRApp: () => createSSRApp,
|
|
55
|
-
createSSRRender: () => createSSRRender,
|
|
56
|
-
createServer: () => createServer,
|
|
57
|
-
defineRoutes: () => defineRoutes,
|
|
58
|
-
deserializeServerData: () => deserializeServerData,
|
|
59
|
-
detectRuntime: () => detectRuntime,
|
|
60
|
-
generateUuid: () => generateUuid,
|
|
61
|
-
getBaseUrl: () => getBaseUrl,
|
|
62
|
-
injectSSRContent: () => injectSSRContent,
|
|
63
|
-
isCompoundAction: () => isCompoundAction,
|
|
64
|
-
isExternalUrlAction: () => isExternalUrlAction,
|
|
65
|
-
isFlowAction: () => isFlowAction,
|
|
66
|
-
isNone: () => isNone,
|
|
67
|
-
isSome: () => isSome,
|
|
68
|
-
makeDependencies: () => makeDependencies,
|
|
69
|
-
makeExternalUrlAction: () => makeExternalUrlAction,
|
|
70
|
-
makeFlowAction: () => makeFlowAction,
|
|
71
|
-
mapEach: () => mapEach,
|
|
72
|
-
parseAcceptLanguage: () => parseAcceptLanguage,
|
|
73
|
-
pipe: () => pipe,
|
|
74
|
-
pipeAsync: () => pipeAsync,
|
|
75
|
-
registerActionHandlers: () => registerActionHandlers,
|
|
76
|
-
registerExternalUrlHandler: () => registerExternalUrlHandler,
|
|
77
|
-
registerFlowActionHandler: () => registerFlowActionHandler,
|
|
78
|
-
removeHost: () => removeHost,
|
|
79
|
-
removeQueryParams: () => removeQueryParams,
|
|
80
|
-
removeScheme: () => removeScheme,
|
|
81
|
-
resetFilterCache: () => resetFilterCache,
|
|
82
|
-
resolveRoot: () => resolveRoot,
|
|
83
|
-
serializeServerData: () => serializeServerData,
|
|
84
|
-
shouldLog: () => shouldLog,
|
|
85
|
-
ssrRender: () => ssrRender,
|
|
86
|
-
stableStringify: () => stableStringify,
|
|
87
|
-
startBrowserApp: () => startBrowserApp,
|
|
88
|
-
startServer: () => startServer,
|
|
89
|
-
tryScroll: () => tryScroll
|
|
90
|
-
});
|
|
91
|
-
module.exports = __toCommonJS(index_exports);
|
|
92
|
-
|
|
93
33
|
// ../core/src/actions/types.ts
|
|
94
|
-
var ACTION_KINDS = {
|
|
95
|
-
FLOW: "flow",
|
|
96
|
-
EXTERNAL_URL: "externalUrl",
|
|
97
|
-
COMPOUND: "compound"
|
|
98
|
-
};
|
|
99
34
|
function isFlowAction(action) {
|
|
100
35
|
return action.kind === ACTION_KINDS.FLOW;
|
|
101
36
|
}
|
|
@@ -111,119 +46,144 @@ function makeFlowAction(url, presentationContext) {
|
|
|
111
46
|
function makeExternalUrlAction(url) {
|
|
112
47
|
return { kind: ACTION_KINDS.EXTERNAL_URL, url };
|
|
113
48
|
}
|
|
49
|
+
var ACTION_KINDS;
|
|
50
|
+
var init_types = __esm({
|
|
51
|
+
"../core/src/actions/types.ts"() {
|
|
52
|
+
"use strict";
|
|
53
|
+
ACTION_KINDS = {
|
|
54
|
+
FLOW: "flow",
|
|
55
|
+
EXTERNAL_URL: "externalUrl",
|
|
56
|
+
COMPOUND: "compound"
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
});
|
|
114
60
|
|
|
115
61
|
// ../core/src/actions/dispatcher.ts
|
|
116
|
-
var ActionDispatcher
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
await this.perform(subAction);
|
|
62
|
+
var ActionDispatcher;
|
|
63
|
+
var init_dispatcher = __esm({
|
|
64
|
+
"../core/src/actions/dispatcher.ts"() {
|
|
65
|
+
"use strict";
|
|
66
|
+
init_types();
|
|
67
|
+
ActionDispatcher = class {
|
|
68
|
+
handlers = /* @__PURE__ */ new Map();
|
|
69
|
+
wiredActions = /* @__PURE__ */ new Set();
|
|
70
|
+
/** 注册指定 kind 的 handler(防止重复注册) */
|
|
71
|
+
onAction(kind, handler) {
|
|
72
|
+
if (this.wiredActions.has(kind)) {
|
|
73
|
+
console.warn(
|
|
74
|
+
`[ActionDispatcher] kind="${kind}" already registered, skipping`
|
|
75
|
+
);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
this.wiredActions.add(kind);
|
|
79
|
+
this.handlers.set(kind, handler);
|
|
135
80
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
81
|
+
/** 执行一个 Action(CompoundAction 递归展开) */
|
|
82
|
+
async perform(action) {
|
|
83
|
+
if (isCompoundAction(action)) {
|
|
84
|
+
for (const subAction of action.actions) {
|
|
85
|
+
await this.perform(subAction);
|
|
86
|
+
}
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const handler = this.handlers.get(action.kind);
|
|
90
|
+
if (!handler) {
|
|
91
|
+
console.warn(
|
|
92
|
+
`[ActionDispatcher] No handler for kind="${action.kind}"`
|
|
93
|
+
);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
await handler(action);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
146
99
|
}
|
|
147
|
-
};
|
|
100
|
+
});
|
|
148
101
|
|
|
149
102
|
// ../core/src/intents/dispatcher.ts
|
|
150
|
-
var IntentDispatcher
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
103
|
+
var IntentDispatcher;
|
|
104
|
+
var init_dispatcher2 = __esm({
|
|
105
|
+
"../core/src/intents/dispatcher.ts"() {
|
|
106
|
+
"use strict";
|
|
107
|
+
IntentDispatcher = class {
|
|
108
|
+
controllers = /* @__PURE__ */ new Map();
|
|
109
|
+
/** 注册一个 IntentController */
|
|
110
|
+
register(controller) {
|
|
111
|
+
this.controllers.set(controller.intentId, controller);
|
|
112
|
+
}
|
|
113
|
+
/** 分发 Intent 到对应 Controller */
|
|
114
|
+
async dispatch(intent, container) {
|
|
115
|
+
const controller = this.controllers.get(intent.id);
|
|
116
|
+
if (!controller) {
|
|
117
|
+
throw new Error(
|
|
118
|
+
`[IntentDispatcher] No controller for "${intent.id}". Registered: [${Array.from(this.controllers.keys()).join(", ")}]`
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
return controller.perform(intent, container);
|
|
122
|
+
}
|
|
123
|
+
/** 检查是否已注册某个 Intent */
|
|
124
|
+
has(intentId) {
|
|
125
|
+
return this.controllers.has(intentId);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
169
128
|
}
|
|
170
|
-
};
|
|
129
|
+
});
|
|
171
130
|
|
|
172
131
|
// ../core/src/dependencies/container.ts
|
|
173
|
-
var Container
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
if (!reg) {
|
|
184
|
-
throw new Error(`[Container] No registration for key: "${key}"`);
|
|
185
|
-
}
|
|
186
|
-
if (reg.singleton) {
|
|
187
|
-
if (reg.instance === void 0) {
|
|
188
|
-
reg.instance = reg.factory();
|
|
132
|
+
var Container;
|
|
133
|
+
var init_container = __esm({
|
|
134
|
+
"../core/src/dependencies/container.ts"() {
|
|
135
|
+
"use strict";
|
|
136
|
+
Container = class {
|
|
137
|
+
registrations = /* @__PURE__ */ new Map();
|
|
138
|
+
/** 注册依赖(默认单例) */
|
|
139
|
+
register(key, factory, singleton = true) {
|
|
140
|
+
this.registrations.set(key, { factory, singleton });
|
|
141
|
+
return this;
|
|
189
142
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
143
|
+
/** 解析依赖 */
|
|
144
|
+
resolve(key) {
|
|
145
|
+
const reg = this.registrations.get(key);
|
|
146
|
+
if (!reg) {
|
|
147
|
+
throw new Error(`[Container] No registration for key: "${key}"`);
|
|
148
|
+
}
|
|
149
|
+
if (reg.singleton) {
|
|
150
|
+
if (reg.instance === void 0) {
|
|
151
|
+
reg.instance = reg.factory();
|
|
152
|
+
}
|
|
153
|
+
return reg.instance;
|
|
154
|
+
}
|
|
155
|
+
return reg.factory();
|
|
156
|
+
}
|
|
157
|
+
/** 检查是否已注册 */
|
|
158
|
+
has(key) {
|
|
159
|
+
return this.registrations.has(key);
|
|
160
|
+
}
|
|
161
|
+
/** 销毁容器,清除所有缓存 */
|
|
162
|
+
dispose() {
|
|
163
|
+
for (const reg of this.registrations.values()) {
|
|
164
|
+
reg.instance = void 0;
|
|
165
|
+
}
|
|
166
|
+
this.registrations.clear();
|
|
167
|
+
}
|
|
168
|
+
};
|
|
204
169
|
}
|
|
205
|
-
};
|
|
170
|
+
});
|
|
206
171
|
|
|
207
172
|
// ../core/src/logger/base.ts
|
|
208
|
-
var BaseLogger
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
173
|
+
var BaseLogger;
|
|
174
|
+
var init_base = __esm({
|
|
175
|
+
"../core/src/logger/base.ts"() {
|
|
176
|
+
"use strict";
|
|
177
|
+
BaseLogger = class {
|
|
178
|
+
category;
|
|
179
|
+
constructor(category) {
|
|
180
|
+
this.category = category;
|
|
181
|
+
}
|
|
182
|
+
};
|
|
212
183
|
}
|
|
213
|
-
};
|
|
184
|
+
});
|
|
214
185
|
|
|
215
186
|
// ../core/src/logger/local-storage-filter.ts
|
|
216
|
-
var LEVEL_TO_NUM = {
|
|
217
|
-
"*": 4,
|
|
218
|
-
debug: 4,
|
|
219
|
-
info: 3,
|
|
220
|
-
warn: 2,
|
|
221
|
-
error: 1,
|
|
222
|
-
off: 0,
|
|
223
|
-
"": 0
|
|
224
|
-
};
|
|
225
|
-
var cachedRules;
|
|
226
|
-
var cachedRaw;
|
|
227
187
|
function parseRules() {
|
|
228
188
|
if (typeof globalThis.localStorage === "undefined") {
|
|
229
189
|
return {};
|
|
@@ -272,94 +232,62 @@ function resetFilterCache() {
|
|
|
272
232
|
cachedRules = void 0;
|
|
273
233
|
cachedRaw = void 0;
|
|
274
234
|
}
|
|
235
|
+
var LEVEL_TO_NUM, cachedRules, cachedRaw;
|
|
236
|
+
var init_local_storage_filter = __esm({
|
|
237
|
+
"../core/src/logger/local-storage-filter.ts"() {
|
|
238
|
+
"use strict";
|
|
239
|
+
LEVEL_TO_NUM = {
|
|
240
|
+
"*": 4,
|
|
241
|
+
debug: 4,
|
|
242
|
+
info: 3,
|
|
243
|
+
warn: 2,
|
|
244
|
+
error: 1,
|
|
245
|
+
off: 0,
|
|
246
|
+
"": 0
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
});
|
|
275
250
|
|
|
276
251
|
// ../core/src/logger/console.ts
|
|
277
|
-
var ConsoleLogger
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
252
|
+
var ConsoleLogger, ConsoleLoggerFactory;
|
|
253
|
+
var init_console = __esm({
|
|
254
|
+
"../core/src/logger/console.ts"() {
|
|
255
|
+
"use strict";
|
|
256
|
+
init_base();
|
|
257
|
+
init_local_storage_filter();
|
|
258
|
+
ConsoleLogger = class extends BaseLogger {
|
|
259
|
+
debug(...args) {
|
|
260
|
+
if (shouldLog(this.category, "debug")) {
|
|
261
|
+
console.debug(`[${this.category}]`, ...args);
|
|
262
|
+
}
|
|
263
|
+
return "";
|
|
264
|
+
}
|
|
265
|
+
info(...args) {
|
|
266
|
+
if (shouldLog(this.category, "info")) {
|
|
267
|
+
console.info(`[${this.category}]`, ...args);
|
|
268
|
+
}
|
|
269
|
+
return "";
|
|
270
|
+
}
|
|
271
|
+
warn(...args) {
|
|
272
|
+
if (shouldLog(this.category, "warn")) {
|
|
273
|
+
console.warn(`[${this.category}]`, ...args);
|
|
274
|
+
}
|
|
275
|
+
return "";
|
|
276
|
+
}
|
|
277
|
+
error(...args) {
|
|
278
|
+
console.error(`[${this.category}]`, ...args);
|
|
279
|
+
return "";
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
ConsoleLoggerFactory = class {
|
|
283
|
+
loggerFor(category) {
|
|
284
|
+
return new ConsoleLogger(category);
|
|
285
|
+
}
|
|
286
|
+
};
|
|
304
287
|
}
|
|
305
|
-
};
|
|
288
|
+
});
|
|
306
289
|
|
|
307
290
|
// ../core/src/dependencies/make-dependencies.ts
|
|
308
|
-
var DEP_KEYS = {
|
|
309
|
-
LOGGER: "logger",
|
|
310
|
-
LOGGER_FACTORY: "loggerFactory",
|
|
311
|
-
NET: "net",
|
|
312
|
-
LOCALE: "locale",
|
|
313
|
-
STORAGE: "storage",
|
|
314
|
-
FEATURE_FLAGS: "featureFlags",
|
|
315
|
-
METRICS: "metrics",
|
|
316
|
-
FETCH: "fetch"
|
|
317
|
-
};
|
|
318
|
-
var DefaultLocale = class {
|
|
319
|
-
language = "en";
|
|
320
|
-
storefront = "us";
|
|
321
|
-
setActiveLocale(language, storefront) {
|
|
322
|
-
this.language = language;
|
|
323
|
-
this.storefront = storefront;
|
|
324
|
-
}
|
|
325
|
-
};
|
|
326
|
-
var MemoryStorage = class {
|
|
327
|
-
store = /* @__PURE__ */ new Map();
|
|
328
|
-
get(key) {
|
|
329
|
-
return this.store.get(key);
|
|
330
|
-
}
|
|
331
|
-
set(key, value) {
|
|
332
|
-
this.store.set(key, value);
|
|
333
|
-
}
|
|
334
|
-
delete(key) {
|
|
335
|
-
this.store.delete(key);
|
|
336
|
-
}
|
|
337
|
-
};
|
|
338
|
-
var DefaultFeatureFlags = class {
|
|
339
|
-
flags;
|
|
340
|
-
constructor(flags = {}) {
|
|
341
|
-
this.flags = flags;
|
|
342
|
-
}
|
|
343
|
-
isEnabled(key) {
|
|
344
|
-
return this.flags[key] === true;
|
|
345
|
-
}
|
|
346
|
-
getString(key) {
|
|
347
|
-
const v = this.flags[key];
|
|
348
|
-
return typeof v === "string" ? v : void 0;
|
|
349
|
-
}
|
|
350
|
-
getNumber(key) {
|
|
351
|
-
const v = this.flags[key];
|
|
352
|
-
return typeof v === "number" ? v : void 0;
|
|
353
|
-
}
|
|
354
|
-
};
|
|
355
|
-
var ConsoleMetrics = class {
|
|
356
|
-
recordPageView(page, fields) {
|
|
357
|
-
console.info(`[Metrics:PageView] ${page}`, fields ?? "");
|
|
358
|
-
}
|
|
359
|
-
recordEvent(name, fields) {
|
|
360
|
-
console.info(`[Metrics:Event] ${name}`, fields ?? "");
|
|
361
|
-
}
|
|
362
|
-
};
|
|
363
291
|
function makeDependencies(container, options = {}) {
|
|
364
292
|
const {
|
|
365
293
|
fetch: fetchFn = globalThis.fetch?.bind(globalThis),
|
|
@@ -395,111 +323,186 @@ function makeDependencies(container, options = {}) {
|
|
|
395
323
|
);
|
|
396
324
|
container.register(DEP_KEYS.FETCH, () => fetchFn);
|
|
397
325
|
}
|
|
326
|
+
var DEP_KEYS, DefaultLocale, MemoryStorage, DefaultFeatureFlags, ConsoleMetrics;
|
|
327
|
+
var init_make_dependencies = __esm({
|
|
328
|
+
"../core/src/dependencies/make-dependencies.ts"() {
|
|
329
|
+
"use strict";
|
|
330
|
+
init_console();
|
|
331
|
+
DEP_KEYS = {
|
|
332
|
+
LOGGER: "logger",
|
|
333
|
+
LOGGER_FACTORY: "loggerFactory",
|
|
334
|
+
NET: "net",
|
|
335
|
+
LOCALE: "locale",
|
|
336
|
+
STORAGE: "storage",
|
|
337
|
+
FEATURE_FLAGS: "featureFlags",
|
|
338
|
+
METRICS: "metrics",
|
|
339
|
+
FETCH: "fetch"
|
|
340
|
+
};
|
|
341
|
+
DefaultLocale = class {
|
|
342
|
+
language = "en";
|
|
343
|
+
storefront = "us";
|
|
344
|
+
setActiveLocale(language, storefront) {
|
|
345
|
+
this.language = language;
|
|
346
|
+
this.storefront = storefront;
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
MemoryStorage = class {
|
|
350
|
+
store = /* @__PURE__ */ new Map();
|
|
351
|
+
get(key) {
|
|
352
|
+
return this.store.get(key);
|
|
353
|
+
}
|
|
354
|
+
set(key, value) {
|
|
355
|
+
this.store.set(key, value);
|
|
356
|
+
}
|
|
357
|
+
delete(key) {
|
|
358
|
+
this.store.delete(key);
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
DefaultFeatureFlags = class {
|
|
362
|
+
flags;
|
|
363
|
+
constructor(flags = {}) {
|
|
364
|
+
this.flags = flags;
|
|
365
|
+
}
|
|
366
|
+
isEnabled(key) {
|
|
367
|
+
return this.flags[key] === true;
|
|
368
|
+
}
|
|
369
|
+
getString(key) {
|
|
370
|
+
const v = this.flags[key];
|
|
371
|
+
return typeof v === "string" ? v : void 0;
|
|
372
|
+
}
|
|
373
|
+
getNumber(key) {
|
|
374
|
+
const v = this.flags[key];
|
|
375
|
+
return typeof v === "number" ? v : void 0;
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
ConsoleMetrics = class {
|
|
379
|
+
recordPageView(page, fields) {
|
|
380
|
+
console.info(`[Metrics:PageView] ${page}`, fields ?? "");
|
|
381
|
+
}
|
|
382
|
+
recordEvent(name, fields) {
|
|
383
|
+
console.info(`[Metrics:Event] ${name}`, fields ?? "");
|
|
384
|
+
}
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
});
|
|
398
388
|
|
|
399
389
|
// ../core/src/router/router.ts
|
|
400
|
-
var Router
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
const path = this.extractPath(urlOrPath);
|
|
423
|
-
const queryParams = this.extractQueryParams(urlOrPath);
|
|
424
|
-
for (const route of this.routes) {
|
|
425
|
-
const match = path.match(route.regex);
|
|
426
|
-
if (match) {
|
|
427
|
-
const params = {};
|
|
428
|
-
route.paramNames.forEach((name, index) => {
|
|
429
|
-
const value = match[index + 1];
|
|
430
|
-
if (value) params[name] = value;
|
|
390
|
+
var Router;
|
|
391
|
+
var init_router = __esm({
|
|
392
|
+
"../core/src/router/router.ts"() {
|
|
393
|
+
"use strict";
|
|
394
|
+
init_types();
|
|
395
|
+
Router = class {
|
|
396
|
+
routes = [];
|
|
397
|
+
/** 添加路由规则 */
|
|
398
|
+
add(pattern, intentId) {
|
|
399
|
+
const paramNames = [];
|
|
400
|
+
const regexStr = pattern.replace(
|
|
401
|
+
/\/:(\w+)(\?)?/g,
|
|
402
|
+
(_, name, optional) => {
|
|
403
|
+
paramNames.push(name);
|
|
404
|
+
return optional ? "(?:/([^/]+))?" : "/([^/]+)";
|
|
405
|
+
}
|
|
406
|
+
);
|
|
407
|
+
this.routes.push({
|
|
408
|
+
pattern,
|
|
409
|
+
intentId,
|
|
410
|
+
regex: new RegExp(`^${regexStr}/?$`),
|
|
411
|
+
paramNames
|
|
431
412
|
});
|
|
432
|
-
|
|
433
|
-
|
|
413
|
+
return this;
|
|
414
|
+
}
|
|
415
|
+
/** 解析 URL → RouteMatch */
|
|
416
|
+
resolve(urlOrPath) {
|
|
417
|
+
const path = this.extractPath(urlOrPath);
|
|
418
|
+
const queryParams = this.extractQueryParams(urlOrPath);
|
|
419
|
+
for (const route of this.routes) {
|
|
420
|
+
const match = path.match(route.regex);
|
|
421
|
+
if (match) {
|
|
422
|
+
const params = {};
|
|
423
|
+
route.paramNames.forEach((name, index) => {
|
|
424
|
+
const value = match[index + 1];
|
|
425
|
+
if (value) params[name] = value;
|
|
426
|
+
});
|
|
427
|
+
for (const [k, v] of Object.entries(queryParams)) {
|
|
428
|
+
if (!(k in params)) params[k] = v;
|
|
429
|
+
}
|
|
430
|
+
return {
|
|
431
|
+
intent: { id: route.intentId, params },
|
|
432
|
+
action: makeFlowAction(urlOrPath)
|
|
433
|
+
};
|
|
434
|
+
}
|
|
434
435
|
}
|
|
435
|
-
return
|
|
436
|
-
intent: { id: route.intentId, params },
|
|
437
|
-
action: makeFlowAction(urlOrPath)
|
|
438
|
-
};
|
|
436
|
+
return null;
|
|
439
437
|
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
}
|
|
438
|
+
/** 获取所有已注册的路由 */
|
|
439
|
+
getRoutes() {
|
|
440
|
+
return this.routes.map((r) => `${r.pattern} \u2192 ${r.intentId}`);
|
|
441
|
+
}
|
|
442
|
+
extractPath(url) {
|
|
443
|
+
try {
|
|
444
|
+
const parsed = new URL(url, "http://localhost");
|
|
445
|
+
return parsed.pathname;
|
|
446
|
+
} catch {
|
|
447
|
+
return url.split("?")[0].split("#")[0];
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
extractQueryParams(url) {
|
|
451
|
+
try {
|
|
452
|
+
const parsed = new URL(url, "http://localhost");
|
|
453
|
+
const params = {};
|
|
454
|
+
parsed.searchParams.forEach((v, k) => {
|
|
455
|
+
params[k] = v;
|
|
456
|
+
});
|
|
457
|
+
return params;
|
|
458
|
+
} catch {
|
|
459
|
+
return {};
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
};
|
|
466
463
|
}
|
|
467
|
-
};
|
|
464
|
+
});
|
|
468
465
|
|
|
469
466
|
// ../core/src/logger/composite.ts
|
|
470
|
-
var CompositeLoggerFactory
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
467
|
+
var CompositeLoggerFactory, CompositeLogger;
|
|
468
|
+
var init_composite = __esm({
|
|
469
|
+
"../core/src/logger/composite.ts"() {
|
|
470
|
+
"use strict";
|
|
471
|
+
CompositeLoggerFactory = class {
|
|
472
|
+
constructor(factories) {
|
|
473
|
+
this.factories = factories;
|
|
474
|
+
}
|
|
475
|
+
loggerFor(name) {
|
|
476
|
+
return new CompositeLogger(
|
|
477
|
+
this.factories.map((f) => f.loggerFor(name))
|
|
478
|
+
);
|
|
479
|
+
}
|
|
480
|
+
};
|
|
481
|
+
CompositeLogger = class {
|
|
482
|
+
constructor(loggers) {
|
|
483
|
+
this.loggers = loggers;
|
|
484
|
+
}
|
|
485
|
+
debug(...args) {
|
|
486
|
+
return this.callAll("debug", args);
|
|
487
|
+
}
|
|
488
|
+
info(...args) {
|
|
489
|
+
return this.callAll("info", args);
|
|
490
|
+
}
|
|
491
|
+
warn(...args) {
|
|
492
|
+
return this.callAll("warn", args);
|
|
493
|
+
}
|
|
494
|
+
error(...args) {
|
|
495
|
+
return this.callAll("error", args);
|
|
496
|
+
}
|
|
497
|
+
callAll(method, args) {
|
|
498
|
+
for (const logger of this.loggers) {
|
|
499
|
+
logger[method](...args);
|
|
500
|
+
}
|
|
501
|
+
return "";
|
|
502
|
+
}
|
|
503
|
+
};
|
|
501
504
|
}
|
|
502
|
-
};
|
|
505
|
+
});
|
|
503
506
|
|
|
504
507
|
// ../core/src/prefetched-intents/stable-stringify.ts
|
|
505
508
|
function stableStringify(obj) {
|
|
@@ -514,360 +517,789 @@ function stableStringify(obj) {
|
|
|
514
517
|
);
|
|
515
518
|
return "{" + parts.join(",") + "}";
|
|
516
519
|
}
|
|
520
|
+
var init_stable_stringify = __esm({
|
|
521
|
+
"../core/src/prefetched-intents/stable-stringify.ts"() {
|
|
522
|
+
"use strict";
|
|
523
|
+
}
|
|
524
|
+
});
|
|
517
525
|
|
|
518
526
|
// ../core/src/prefetched-intents/prefetched-intents.ts
|
|
519
|
-
var PrefetchedIntents
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
527
|
+
var PrefetchedIntents;
|
|
528
|
+
var init_prefetched_intents = __esm({
|
|
529
|
+
"../core/src/prefetched-intents/prefetched-intents.ts"() {
|
|
530
|
+
"use strict";
|
|
531
|
+
init_stable_stringify();
|
|
532
|
+
PrefetchedIntents = class _PrefetchedIntents {
|
|
533
|
+
intents;
|
|
534
|
+
constructor(intents) {
|
|
535
|
+
this.intents = intents;
|
|
536
|
+
}
|
|
537
|
+
/** 从 PrefetchedIntent 数组创建缓存实例 */
|
|
538
|
+
static fromArray(items) {
|
|
539
|
+
const map = /* @__PURE__ */ new Map();
|
|
540
|
+
for (const item of items) {
|
|
541
|
+
if (item.intent && item.data !== void 0) {
|
|
542
|
+
const key = stableStringify(item.intent);
|
|
543
|
+
map.set(key, item.data);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
return new _PrefetchedIntents(map);
|
|
547
|
+
}
|
|
548
|
+
/** 创建空缓存实例 */
|
|
549
|
+
static empty() {
|
|
550
|
+
return new _PrefetchedIntents(/* @__PURE__ */ new Map());
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* 获取缓存的 Intent 结果(一次性使用)。
|
|
554
|
+
* 命中后从缓存中删除。
|
|
555
|
+
*/
|
|
556
|
+
get(intent) {
|
|
557
|
+
const key = stableStringify(intent);
|
|
558
|
+
const data = this.intents.get(key);
|
|
559
|
+
if (data !== void 0) {
|
|
560
|
+
this.intents.delete(key);
|
|
561
|
+
return data;
|
|
562
|
+
}
|
|
563
|
+
return void 0;
|
|
564
|
+
}
|
|
565
|
+
/** 检查缓存中是否有某个 Intent 的数据 */
|
|
566
|
+
has(intent) {
|
|
567
|
+
return this.intents.has(stableStringify(intent));
|
|
568
|
+
}
|
|
569
|
+
/** 缓存中的条目数 */
|
|
570
|
+
get size() {
|
|
571
|
+
return this.intents.size;
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
// ../core/src/framework.ts
|
|
578
|
+
var Framework;
|
|
579
|
+
var init_framework = __esm({
|
|
580
|
+
"../core/src/framework.ts"() {
|
|
581
|
+
"use strict";
|
|
582
|
+
init_dispatcher();
|
|
583
|
+
init_container();
|
|
584
|
+
init_make_dependencies();
|
|
585
|
+
init_dispatcher2();
|
|
586
|
+
init_prefetched_intents();
|
|
587
|
+
init_router();
|
|
588
|
+
Framework = class _Framework {
|
|
589
|
+
container;
|
|
590
|
+
intentDispatcher;
|
|
591
|
+
actionDispatcher;
|
|
592
|
+
router;
|
|
593
|
+
prefetchedIntents;
|
|
594
|
+
constructor(container, prefetchedIntents) {
|
|
595
|
+
this.container = container;
|
|
596
|
+
this.intentDispatcher = new IntentDispatcher();
|
|
597
|
+
this.actionDispatcher = new ActionDispatcher();
|
|
598
|
+
this.router = new Router();
|
|
599
|
+
this.prefetchedIntents = prefetchedIntents;
|
|
600
|
+
}
|
|
601
|
+
/** 创建并初始化 Framework 实例 */
|
|
602
|
+
static create(config = {}) {
|
|
603
|
+
const container = new Container();
|
|
604
|
+
makeDependencies(container, config);
|
|
605
|
+
const fw = new _Framework(
|
|
606
|
+
container,
|
|
607
|
+
config.prefetchedIntents ?? PrefetchedIntents.empty()
|
|
608
|
+
);
|
|
609
|
+
config.setupRoutes?.(fw.router);
|
|
610
|
+
return fw;
|
|
611
|
+
}
|
|
612
|
+
/** 分发 Intent — 获取页面数据 */
|
|
613
|
+
async dispatch(intent) {
|
|
614
|
+
const logger = this.container.resolve(DEP_KEYS.LOGGER);
|
|
615
|
+
const cached = this.prefetchedIntents.get(intent);
|
|
616
|
+
if (cached !== void 0) {
|
|
617
|
+
logger.debug(
|
|
618
|
+
`[Framework] re-using prefetched intent response for: ${intent.id}`,
|
|
619
|
+
intent.params
|
|
620
|
+
);
|
|
621
|
+
return cached;
|
|
622
|
+
}
|
|
623
|
+
logger.debug(
|
|
624
|
+
`[Framework] dispatch intent: ${intent.id}`,
|
|
625
|
+
intent.params
|
|
626
|
+
);
|
|
627
|
+
return this.intentDispatcher.dispatch(intent, this.container);
|
|
628
|
+
}
|
|
629
|
+
/** 执行 Action — 处理用户交互 */
|
|
630
|
+
async perform(action) {
|
|
631
|
+
const logger = this.container.resolve(DEP_KEYS.LOGGER);
|
|
632
|
+
logger.debug(`[Framework] perform action: ${action.kind}`);
|
|
633
|
+
return this.actionDispatcher.perform(action);
|
|
634
|
+
}
|
|
635
|
+
/** 路由 URL — 将 URL 解析为 Intent + Action */
|
|
636
|
+
routeUrl(url) {
|
|
637
|
+
return this.router.resolve(url);
|
|
638
|
+
}
|
|
639
|
+
/** 记录页面访问事件 */
|
|
640
|
+
didEnterPage(page) {
|
|
641
|
+
const metrics = this.container.resolve(
|
|
642
|
+
DEP_KEYS.METRICS
|
|
643
|
+
);
|
|
644
|
+
metrics.recordPageView(page.pageType, {
|
|
645
|
+
pageId: page.id,
|
|
646
|
+
title: page.title
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
/** 注册 Action 处理器 */
|
|
650
|
+
onAction(kind, handler) {
|
|
651
|
+
this.actionDispatcher.onAction(kind, handler);
|
|
652
|
+
}
|
|
653
|
+
/** 注册 Intent Controller */
|
|
654
|
+
registerIntent(controller) {
|
|
655
|
+
this.intentDispatcher.register(controller);
|
|
656
|
+
}
|
|
657
|
+
/** 销毁 Framework 实例 */
|
|
658
|
+
dispose() {
|
|
659
|
+
this.container.dispose();
|
|
660
|
+
}
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
});
|
|
664
|
+
|
|
665
|
+
// ../core/src/http/client.ts
|
|
666
|
+
var HttpError, HttpClient;
|
|
667
|
+
var init_client = __esm({
|
|
668
|
+
"../core/src/http/client.ts"() {
|
|
669
|
+
"use strict";
|
|
670
|
+
HttpError = class extends Error {
|
|
671
|
+
constructor(status, statusText, body) {
|
|
672
|
+
super(`HTTP ${status}: ${statusText}`);
|
|
673
|
+
this.status = status;
|
|
674
|
+
this.statusText = statusText;
|
|
675
|
+
this.body = body;
|
|
676
|
+
this.name = "HttpError";
|
|
677
|
+
}
|
|
678
|
+
};
|
|
679
|
+
HttpClient = class {
|
|
680
|
+
baseUrl;
|
|
681
|
+
defaultHeaders;
|
|
682
|
+
fetchFn;
|
|
683
|
+
constructor(config) {
|
|
684
|
+
this.baseUrl = config.baseUrl;
|
|
685
|
+
this.defaultHeaders = config.defaultHeaders ?? {};
|
|
686
|
+
this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis);
|
|
687
|
+
}
|
|
688
|
+
/** GET 请求,返回解析后的 JSON */
|
|
689
|
+
async get(path, params) {
|
|
690
|
+
return this.request("GET", path, { params });
|
|
531
691
|
}
|
|
692
|
+
/** POST 请求,自动序列化 body 为 JSON */
|
|
693
|
+
async post(path, body, params) {
|
|
694
|
+
return this.request("POST", path, { body, params });
|
|
695
|
+
}
|
|
696
|
+
/** PUT 请求 */
|
|
697
|
+
async put(path, body, params) {
|
|
698
|
+
return this.request("PUT", path, { body, params });
|
|
699
|
+
}
|
|
700
|
+
/** DELETE 请求 */
|
|
701
|
+
async del(path, params) {
|
|
702
|
+
return this.request("DELETE", path, { params });
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* 底层请求方法 — 子类可覆写以自定义行为
|
|
706
|
+
*
|
|
707
|
+
* 自动处理:
|
|
708
|
+
* - URL 拼接 (baseUrl + path + params)
|
|
709
|
+
* - 默认 headers 合并
|
|
710
|
+
* - JSON body 序列化
|
|
711
|
+
* - 响应 JSON 解析
|
|
712
|
+
* - 非 2xx 状态码抛出 HttpError
|
|
713
|
+
*/
|
|
714
|
+
async request(method, path, options) {
|
|
715
|
+
const url = this.buildUrl(path, options?.params);
|
|
716
|
+
const headers = {
|
|
717
|
+
...this.defaultHeaders,
|
|
718
|
+
...options?.headers
|
|
719
|
+
};
|
|
720
|
+
const init = { method, headers };
|
|
721
|
+
if (options?.body !== void 0) {
|
|
722
|
+
headers["Content-Type"] = headers["Content-Type"] ?? "application/json";
|
|
723
|
+
init.body = JSON.stringify(options.body);
|
|
724
|
+
}
|
|
725
|
+
const response = await this.fetchFn(url, init);
|
|
726
|
+
if (!response.ok) {
|
|
727
|
+
const body = await response.text().catch(() => void 0);
|
|
728
|
+
throw new HttpError(response.status, response.statusText, body);
|
|
729
|
+
}
|
|
730
|
+
return response.json();
|
|
731
|
+
}
|
|
732
|
+
/** 构建完整 URL — 子类可覆写以自定义 URL 拼接逻辑 */
|
|
733
|
+
buildUrl(path, params) {
|
|
734
|
+
const base = this.baseUrl.endsWith("/") ? this.baseUrl.slice(0, -1) : this.baseUrl;
|
|
735
|
+
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
736
|
+
const url = new URL(`${base}${normalizedPath}`, "http://placeholder");
|
|
737
|
+
if (params) {
|
|
738
|
+
for (const [k, v] of Object.entries(params)) {
|
|
739
|
+
url.searchParams.set(k, v);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
if (this.baseUrl.startsWith("http")) {
|
|
743
|
+
return url.toString();
|
|
744
|
+
}
|
|
745
|
+
return `${url.pathname}${url.search}`;
|
|
746
|
+
}
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
});
|
|
750
|
+
|
|
751
|
+
// ../core/src/intents/base-controller.ts
|
|
752
|
+
var BaseController;
|
|
753
|
+
var init_base_controller = __esm({
|
|
754
|
+
"../core/src/intents/base-controller.ts"() {
|
|
755
|
+
"use strict";
|
|
756
|
+
BaseController = class {
|
|
757
|
+
/**
|
|
758
|
+
* 错误回退 — 子类可选覆写
|
|
759
|
+
*
|
|
760
|
+
* 当 execute() 抛出异常时调用。
|
|
761
|
+
* 默认行为: 重新抛出原始错误。
|
|
762
|
+
*
|
|
763
|
+
* @param params - Intent 参数
|
|
764
|
+
* @param error - execute() 抛出的错误
|
|
765
|
+
* @returns 回退数据
|
|
766
|
+
*/
|
|
767
|
+
fallback(params, error) {
|
|
768
|
+
throw error;
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* IntentController.perform() 实现
|
|
772
|
+
*
|
|
773
|
+
* 自动 try/catch → fallback 模式。
|
|
774
|
+
*/
|
|
775
|
+
async perform(intent, container) {
|
|
776
|
+
const params = intent.params ?? {};
|
|
777
|
+
try {
|
|
778
|
+
return await this.execute(params, container);
|
|
779
|
+
} catch (e) {
|
|
780
|
+
return this.fallback(
|
|
781
|
+
params,
|
|
782
|
+
e instanceof Error ? e : new Error(String(e))
|
|
783
|
+
);
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
});
|
|
789
|
+
|
|
790
|
+
// ../core/src/data/mapper.ts
|
|
791
|
+
function pipe(...mappers) {
|
|
792
|
+
return (input) => mappers.reduce((acc, mapper) => mapper(acc), input);
|
|
793
|
+
}
|
|
794
|
+
function pipeAsync(...mappers) {
|
|
795
|
+
return async (input) => {
|
|
796
|
+
let acc = input;
|
|
797
|
+
for (const mapper of mappers) {
|
|
798
|
+
acc = await mapper(acc);
|
|
532
799
|
}
|
|
533
|
-
return
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
800
|
+
return acc;
|
|
801
|
+
};
|
|
802
|
+
}
|
|
803
|
+
function mapEach(mapper) {
|
|
804
|
+
return (items) => items.map(mapper);
|
|
805
|
+
}
|
|
806
|
+
var init_mapper = __esm({
|
|
807
|
+
"../core/src/data/mapper.ts"() {
|
|
808
|
+
"use strict";
|
|
809
|
+
}
|
|
810
|
+
});
|
|
811
|
+
|
|
812
|
+
// ../core/src/bootstrap/define-routes.ts
|
|
813
|
+
function defineRoutes(framework, definitions) {
|
|
814
|
+
const registeredIntents = /* @__PURE__ */ new Set();
|
|
815
|
+
for (const def of definitions) {
|
|
816
|
+
if (def.controller && !registeredIntents.has(def.intentId)) {
|
|
817
|
+
framework.registerIntent(def.controller);
|
|
818
|
+
registeredIntents.add(def.intentId);
|
|
549
819
|
}
|
|
550
|
-
|
|
820
|
+
framework.router.add(def.path, def.intentId);
|
|
551
821
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
822
|
+
}
|
|
823
|
+
var init_define_routes = __esm({
|
|
824
|
+
"../core/src/bootstrap/define-routes.ts"() {
|
|
825
|
+
"use strict";
|
|
555
826
|
}
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
827
|
+
});
|
|
828
|
+
|
|
829
|
+
// ../core/src/utils/lru-map.ts
|
|
830
|
+
var LruMap;
|
|
831
|
+
var init_lru_map = __esm({
|
|
832
|
+
"../core/src/utils/lru-map.ts"() {
|
|
833
|
+
"use strict";
|
|
834
|
+
LruMap = class {
|
|
835
|
+
map = /* @__PURE__ */ new Map();
|
|
836
|
+
capacity;
|
|
837
|
+
constructor(capacity) {
|
|
838
|
+
this.capacity = capacity;
|
|
839
|
+
}
|
|
840
|
+
get(key) {
|
|
841
|
+
const value = this.map.get(key);
|
|
842
|
+
if (value !== void 0) {
|
|
843
|
+
this.map.delete(key);
|
|
844
|
+
this.map.set(key, value);
|
|
845
|
+
}
|
|
846
|
+
return value;
|
|
847
|
+
}
|
|
848
|
+
set(key, value) {
|
|
849
|
+
if (this.map.has(key)) {
|
|
850
|
+
this.map.delete(key);
|
|
851
|
+
} else if (this.map.size >= this.capacity) {
|
|
852
|
+
const oldest = this.map.keys().next().value;
|
|
853
|
+
if (oldest !== void 0) {
|
|
854
|
+
this.map.delete(oldest);
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
this.map.set(key, value);
|
|
858
|
+
}
|
|
859
|
+
has(key) {
|
|
860
|
+
return this.map.has(key);
|
|
861
|
+
}
|
|
862
|
+
delete(key) {
|
|
863
|
+
return this.map.delete(key);
|
|
864
|
+
}
|
|
865
|
+
get size() {
|
|
866
|
+
return this.map.size;
|
|
867
|
+
}
|
|
868
|
+
clear() {
|
|
869
|
+
this.map.clear();
|
|
870
|
+
}
|
|
871
|
+
};
|
|
559
872
|
}
|
|
560
|
-
};
|
|
873
|
+
});
|
|
561
874
|
|
|
562
|
-
// ../core/src/
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
875
|
+
// ../core/src/utils/optional.ts
|
|
876
|
+
function isSome(value) {
|
|
877
|
+
return value !== null && value !== void 0;
|
|
878
|
+
}
|
|
879
|
+
function isNone(value) {
|
|
880
|
+
return value === null || value === void 0;
|
|
881
|
+
}
|
|
882
|
+
var init_optional = __esm({
|
|
883
|
+
"../core/src/utils/optional.ts"() {
|
|
884
|
+
"use strict";
|
|
885
|
+
}
|
|
886
|
+
});
|
|
887
|
+
|
|
888
|
+
// ../core/src/utils/url.ts
|
|
889
|
+
function removeScheme(url) {
|
|
890
|
+
return url.replace(/^https?:\/\//, "");
|
|
891
|
+
}
|
|
892
|
+
function removeHost(url) {
|
|
893
|
+
try {
|
|
894
|
+
const parsed = new URL(url);
|
|
895
|
+
return parsed.pathname + parsed.search + parsed.hash;
|
|
896
|
+
} catch {
|
|
897
|
+
return url;
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
function removeQueryParams(url) {
|
|
901
|
+
return url.split("?")[0];
|
|
902
|
+
}
|
|
903
|
+
function getBaseUrl(url) {
|
|
904
|
+
return url.split("?")[0].split("#")[0];
|
|
905
|
+
}
|
|
906
|
+
function buildUrl(path, params) {
|
|
907
|
+
if (!params) return path;
|
|
908
|
+
const searchParams = new URLSearchParams();
|
|
909
|
+
for (const [key, value] of Object.entries(params)) {
|
|
910
|
+
if (value !== void 0) {
|
|
911
|
+
searchParams.set(key, value);
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
const qs = searchParams.toString();
|
|
915
|
+
return qs ? `${path}?${qs}` : path;
|
|
916
|
+
}
|
|
917
|
+
var init_url = __esm({
|
|
918
|
+
"../core/src/utils/url.ts"() {
|
|
919
|
+
"use strict";
|
|
920
|
+
}
|
|
921
|
+
});
|
|
922
|
+
|
|
923
|
+
// ../core/src/utils/uuid.ts
|
|
924
|
+
function generateUuid() {
|
|
925
|
+
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
926
|
+
return crypto.randomUUID();
|
|
927
|
+
}
|
|
928
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
929
|
+
const r = Math.random() * 16 | 0;
|
|
930
|
+
const v = c === "x" ? r : r & 3 | 8;
|
|
931
|
+
return v.toString(16);
|
|
932
|
+
});
|
|
933
|
+
}
|
|
934
|
+
var init_uuid = __esm({
|
|
935
|
+
"../core/src/utils/uuid.ts"() {
|
|
936
|
+
"use strict";
|
|
937
|
+
}
|
|
938
|
+
});
|
|
939
|
+
|
|
940
|
+
// ../core/src/index.ts
|
|
941
|
+
var init_src = __esm({
|
|
942
|
+
"../core/src/index.ts"() {
|
|
943
|
+
"use strict";
|
|
944
|
+
init_dispatcher();
|
|
945
|
+
init_types();
|
|
946
|
+
init_dispatcher2();
|
|
947
|
+
init_container();
|
|
948
|
+
init_make_dependencies();
|
|
949
|
+
init_router();
|
|
950
|
+
init_base();
|
|
951
|
+
init_composite();
|
|
952
|
+
init_console();
|
|
953
|
+
init_local_storage_filter();
|
|
954
|
+
init_framework();
|
|
955
|
+
init_prefetched_intents();
|
|
956
|
+
init_stable_stringify();
|
|
957
|
+
init_client();
|
|
958
|
+
init_base_controller();
|
|
959
|
+
init_mapper();
|
|
960
|
+
init_define_routes();
|
|
961
|
+
init_lru_map();
|
|
962
|
+
init_optional();
|
|
963
|
+
init_url();
|
|
964
|
+
init_uuid();
|
|
965
|
+
}
|
|
966
|
+
});
|
|
967
|
+
|
|
968
|
+
// ../ssr/src/render.ts
|
|
969
|
+
async function ssrRender(options) {
|
|
970
|
+
const { url, frameworkConfig, bootstrap, getErrorPage, renderApp } = options;
|
|
971
|
+
const framework = Framework.create(frameworkConfig);
|
|
972
|
+
bootstrap(framework);
|
|
973
|
+
const parsed = new URL(url, "http://localhost");
|
|
974
|
+
const fullPath = parsed.pathname + parsed.search;
|
|
975
|
+
const match = framework.routeUrl(fullPath);
|
|
976
|
+
let page;
|
|
977
|
+
let serverData = [];
|
|
978
|
+
if (match) {
|
|
979
|
+
try {
|
|
980
|
+
page = await framework.dispatch(match.intent);
|
|
981
|
+
serverData = [{ intent: match.intent, data: page }];
|
|
982
|
+
} catch {
|
|
983
|
+
page = getErrorPage(500, "Internal error");
|
|
984
|
+
}
|
|
985
|
+
} else {
|
|
986
|
+
page = getErrorPage(404, "Page not found");
|
|
987
|
+
}
|
|
988
|
+
const result = renderApp(page, framework);
|
|
989
|
+
framework.dispose();
|
|
990
|
+
return {
|
|
991
|
+
html: result.html,
|
|
992
|
+
head: result.head,
|
|
993
|
+
css: result.css,
|
|
994
|
+
serverData
|
|
995
|
+
};
|
|
996
|
+
}
|
|
997
|
+
var init_render = __esm({
|
|
998
|
+
"../ssr/src/render.ts"() {
|
|
999
|
+
"use strict";
|
|
1000
|
+
init_src();
|
|
1001
|
+
}
|
|
1002
|
+
});
|
|
1003
|
+
|
|
1004
|
+
// ../ssr/src/create-render.ts
|
|
1005
|
+
function createSSRRender(config) {
|
|
1006
|
+
const { bootstrap, getErrorPage, renderApp, frameworkConfig } = config;
|
|
1007
|
+
return (url, locale) => ssrRender({
|
|
1008
|
+
url,
|
|
1009
|
+
frameworkConfig: frameworkConfig ?? {},
|
|
1010
|
+
bootstrap,
|
|
1011
|
+
getErrorPage,
|
|
1012
|
+
renderApp: (page) => renderApp(page, locale)
|
|
1013
|
+
});
|
|
1014
|
+
}
|
|
1015
|
+
var init_create_render = __esm({
|
|
1016
|
+
"../ssr/src/create-render.ts"() {
|
|
1017
|
+
"use strict";
|
|
1018
|
+
init_render();
|
|
1019
|
+
}
|
|
1020
|
+
});
|
|
1021
|
+
|
|
1022
|
+
// ../ssr/src/inject.ts
|
|
1023
|
+
function injectSSRContent(options) {
|
|
1024
|
+
const { template, locale, head, css, html, serializedData } = options;
|
|
1025
|
+
const cssTag = css ? `<style>${css}</style>` : "";
|
|
1026
|
+
return template.replace(SSR_PLACEHOLDERS.LANG, locale).replace(SSR_PLACEHOLDERS.HEAD, `${head}
|
|
1027
|
+
${cssTag}`).replace(SSR_PLACEHOLDERS.BODY, html).replace(
|
|
1028
|
+
SSR_PLACEHOLDERS.DATA,
|
|
1029
|
+
`<script id="serialized-server-data" type="application/json">${serializedData}</script>`
|
|
1030
|
+
);
|
|
1031
|
+
}
|
|
1032
|
+
var SSR_PLACEHOLDERS;
|
|
1033
|
+
var init_inject = __esm({
|
|
1034
|
+
"../ssr/src/inject.ts"() {
|
|
1035
|
+
"use strict";
|
|
1036
|
+
SSR_PLACEHOLDERS = {
|
|
1037
|
+
LANG: "<!--ssr-lang-->",
|
|
1038
|
+
HEAD: "<!--ssr-head-->",
|
|
1039
|
+
BODY: "<!--ssr-body-->",
|
|
1040
|
+
DATA: "<!--ssr-data-->"
|
|
1041
|
+
};
|
|
1042
|
+
}
|
|
1043
|
+
});
|
|
1044
|
+
|
|
1045
|
+
// ../ssr/src/server-data.ts
|
|
1046
|
+
function serializeServerData(data) {
|
|
1047
|
+
const json = JSON.stringify(data);
|
|
1048
|
+
return json.replace(
|
|
1049
|
+
HTML_ESCAPE_PATTERN,
|
|
1050
|
+
(match) => HTML_REPLACEMENTS[match] ?? match
|
|
1051
|
+
);
|
|
1052
|
+
}
|
|
1053
|
+
var HTML_REPLACEMENTS, HTML_ESCAPE_PATTERN;
|
|
1054
|
+
var init_server_data = __esm({
|
|
1055
|
+
"../ssr/src/server-data.ts"() {
|
|
1056
|
+
"use strict";
|
|
1057
|
+
HTML_REPLACEMENTS = {
|
|
1058
|
+
"<": "\\u003C",
|
|
1059
|
+
">": "\\u003E",
|
|
1060
|
+
"/": "\\u002F",
|
|
1061
|
+
"\u2028": "\\u2028",
|
|
1062
|
+
"\u2029": "\\u2029"
|
|
1063
|
+
};
|
|
1064
|
+
HTML_ESCAPE_PATTERN = /[<>/\u2028\u2029]/g;
|
|
1065
|
+
}
|
|
1066
|
+
});
|
|
1067
|
+
|
|
1068
|
+
// ../ssr/src/index.ts
|
|
1069
|
+
var src_exports = {};
|
|
1070
|
+
__export(src_exports, {
|
|
1071
|
+
Framework: () => Framework,
|
|
1072
|
+
SSR_PLACEHOLDERS: () => SSR_PLACEHOLDERS,
|
|
1073
|
+
createSSRRender: () => createSSRRender,
|
|
1074
|
+
injectSSRContent: () => injectSSRContent,
|
|
1075
|
+
serializeServerData: () => serializeServerData,
|
|
1076
|
+
ssrRender: () => ssrRender
|
|
1077
|
+
});
|
|
1078
|
+
var init_src2 = __esm({
|
|
1079
|
+
"../ssr/src/index.ts"() {
|
|
1080
|
+
"use strict";
|
|
1081
|
+
init_create_render();
|
|
1082
|
+
init_inject();
|
|
1083
|
+
init_render();
|
|
1084
|
+
init_server_data();
|
|
1085
|
+
init_src();
|
|
1086
|
+
}
|
|
1087
|
+
});
|
|
1088
|
+
|
|
1089
|
+
// ../server/src/locale.ts
|
|
1090
|
+
var locale_exports = {};
|
|
1091
|
+
__export(locale_exports, {
|
|
1092
|
+
parseAcceptLanguage: () => parseAcceptLanguage
|
|
1093
|
+
});
|
|
1094
|
+
function parseAcceptLanguage(header, supported, fallback) {
|
|
1095
|
+
const effectiveSupported = supported ?? ["zh", "en"];
|
|
1096
|
+
const effectiveFallback = fallback ?? effectiveSupported[0] ?? "en";
|
|
1097
|
+
if (!header) return effectiveFallback;
|
|
1098
|
+
const langs = header.split(",").map((part) => {
|
|
1099
|
+
const [lang, q] = part.trim().split(";q=");
|
|
1100
|
+
return {
|
|
1101
|
+
lang: lang.trim().toLowerCase(),
|
|
1102
|
+
q: q ? parseFloat(q) : 1
|
|
1103
|
+
};
|
|
1104
|
+
}).sort((a, b) => b.q - a.q);
|
|
1105
|
+
for (const { lang } of langs) {
|
|
1106
|
+
const prefix = lang.split("-")[0];
|
|
1107
|
+
if (effectiveSupported.includes(prefix)) {
|
|
1108
|
+
return prefix;
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
return effectiveFallback;
|
|
1112
|
+
}
|
|
1113
|
+
var init_locale = __esm({
|
|
1114
|
+
"../server/src/locale.ts"() {
|
|
1115
|
+
"use strict";
|
|
1116
|
+
}
|
|
1117
|
+
});
|
|
1118
|
+
|
|
1119
|
+
// ../server/src/app.ts
|
|
1120
|
+
var app_exports = {};
|
|
1121
|
+
__export(app_exports, {
|
|
1122
|
+
createSSRApp: () => createSSRApp
|
|
1123
|
+
});
|
|
1124
|
+
function createSSRApp(options) {
|
|
1125
|
+
const {
|
|
1126
|
+
root,
|
|
1127
|
+
vite,
|
|
1128
|
+
isProduction,
|
|
1129
|
+
ssrEntryPath = "/src/ssr.ts",
|
|
1130
|
+
ssrProductionModule,
|
|
1131
|
+
supportedLocales,
|
|
1132
|
+
defaultLocale
|
|
1133
|
+
} = options;
|
|
1134
|
+
const app = new import_hono.Hono();
|
|
1135
|
+
async function readTemplate(url) {
|
|
1136
|
+
if (!isProduction && vite) {
|
|
1137
|
+
const { readFileSync: readFileSync2 } = await import(
|
|
1138
|
+
/* @vite-ignore */
|
|
1139
|
+
"fs"
|
|
1140
|
+
);
|
|
1141
|
+
const { resolve: resolve2 } = await import(
|
|
1142
|
+
/* @vite-ignore */
|
|
1143
|
+
"path"
|
|
1144
|
+
);
|
|
1145
|
+
const raw = readFileSync2(resolve2(root, "index.html"), "utf-8");
|
|
1146
|
+
return vite.transformIndexHtml(url, raw);
|
|
1147
|
+
}
|
|
1148
|
+
const isDeno = typeof globalThis.Deno !== "undefined";
|
|
1149
|
+
if (isDeno) {
|
|
1150
|
+
return globalThis.Deno.readTextFileSync(
|
|
1151
|
+
new URL("../dist/client/index.html", import_meta.url)
|
|
595
1152
|
);
|
|
596
|
-
return cached;
|
|
597
1153
|
}
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
1154
|
+
const { readFileSync } = await import(
|
|
1155
|
+
/* @vite-ignore */
|
|
1156
|
+
"fs"
|
|
601
1157
|
);
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
async perform(action) {
|
|
606
|
-
const logger = this.container.resolve(DEP_KEYS.LOGGER);
|
|
607
|
-
logger.debug(`[Framework] perform action: ${action.kind}`);
|
|
608
|
-
return this.actionDispatcher.perform(action);
|
|
609
|
-
}
|
|
610
|
-
/** 路由 URL — 将 URL 解析为 Intent + Action */
|
|
611
|
-
routeUrl(url) {
|
|
612
|
-
return this.router.resolve(url);
|
|
613
|
-
}
|
|
614
|
-
/** 记录页面访问事件 */
|
|
615
|
-
didEnterPage(page) {
|
|
616
|
-
const metrics = this.container.resolve(
|
|
617
|
-
DEP_KEYS.METRICS
|
|
1158
|
+
const { resolve } = await import(
|
|
1159
|
+
/* @vite-ignore */
|
|
1160
|
+
"path"
|
|
618
1161
|
);
|
|
619
|
-
|
|
620
|
-
pageId: page.id,
|
|
621
|
-
title: page.title
|
|
622
|
-
});
|
|
623
|
-
}
|
|
624
|
-
/** 注册 Action 处理器 */
|
|
625
|
-
onAction(kind, handler) {
|
|
626
|
-
this.actionDispatcher.onAction(kind, handler);
|
|
627
|
-
}
|
|
628
|
-
/** 注册 Intent Controller */
|
|
629
|
-
registerIntent(controller) {
|
|
630
|
-
this.intentDispatcher.register(controller);
|
|
631
|
-
}
|
|
632
|
-
/** 销毁 Framework 实例 */
|
|
633
|
-
dispose() {
|
|
634
|
-
this.container.dispose();
|
|
635
|
-
}
|
|
636
|
-
};
|
|
637
|
-
|
|
638
|
-
// ../core/src/http/client.ts
|
|
639
|
-
var HttpError = class extends Error {
|
|
640
|
-
constructor(status, statusText, body) {
|
|
641
|
-
super(`HTTP ${status}: ${statusText}`);
|
|
642
|
-
this.status = status;
|
|
643
|
-
this.statusText = statusText;
|
|
644
|
-
this.body = body;
|
|
645
|
-
this.name = "HttpError";
|
|
646
|
-
}
|
|
647
|
-
};
|
|
648
|
-
var HttpClient = class {
|
|
649
|
-
baseUrl;
|
|
650
|
-
defaultHeaders;
|
|
651
|
-
fetchFn;
|
|
652
|
-
constructor(config) {
|
|
653
|
-
this.baseUrl = config.baseUrl;
|
|
654
|
-
this.defaultHeaders = config.defaultHeaders ?? {};
|
|
655
|
-
this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis);
|
|
656
|
-
}
|
|
657
|
-
/** GET 请求,返回解析后的 JSON */
|
|
658
|
-
async get(path, params) {
|
|
659
|
-
return this.request("GET", path, { params });
|
|
660
|
-
}
|
|
661
|
-
/** POST 请求,自动序列化 body 为 JSON */
|
|
662
|
-
async post(path, body, params) {
|
|
663
|
-
return this.request("POST", path, { body, params });
|
|
664
|
-
}
|
|
665
|
-
/** PUT 请求 */
|
|
666
|
-
async put(path, body, params) {
|
|
667
|
-
return this.request("PUT", path, { body, params });
|
|
668
|
-
}
|
|
669
|
-
/** DELETE 请求 */
|
|
670
|
-
async del(path, params) {
|
|
671
|
-
return this.request("DELETE", path, { params });
|
|
672
|
-
}
|
|
673
|
-
/**
|
|
674
|
-
* 底层请求方法 — 子类可覆写以自定义行为
|
|
675
|
-
*
|
|
676
|
-
* 自动处理:
|
|
677
|
-
* - URL 拼接 (baseUrl + path + params)
|
|
678
|
-
* - 默认 headers 合并
|
|
679
|
-
* - JSON body 序列化
|
|
680
|
-
* - 响应 JSON 解析
|
|
681
|
-
* - 非 2xx 状态码抛出 HttpError
|
|
682
|
-
*/
|
|
683
|
-
async request(method, path, options) {
|
|
684
|
-
const url = this.buildUrl(path, options?.params);
|
|
685
|
-
const headers = {
|
|
686
|
-
...this.defaultHeaders,
|
|
687
|
-
...options?.headers
|
|
688
|
-
};
|
|
689
|
-
const init = { method, headers };
|
|
690
|
-
if (options?.body !== void 0) {
|
|
691
|
-
headers["Content-Type"] = headers["Content-Type"] ?? "application/json";
|
|
692
|
-
init.body = JSON.stringify(options.body);
|
|
693
|
-
}
|
|
694
|
-
const response = await this.fetchFn(url, init);
|
|
695
|
-
if (!response.ok) {
|
|
696
|
-
const body = await response.text().catch(() => void 0);
|
|
697
|
-
throw new HttpError(response.status, response.statusText, body);
|
|
698
|
-
}
|
|
699
|
-
return response.json();
|
|
1162
|
+
return readFileSync(resolve(root, "dist/client/index.html"), "utf-8");
|
|
700
1163
|
}
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
705
|
-
const url = new URL(`${base}${normalizedPath}`, "http://placeholder");
|
|
706
|
-
if (params) {
|
|
707
|
-
for (const [k, v] of Object.entries(params)) {
|
|
708
|
-
url.searchParams.set(k, v);
|
|
709
|
-
}
|
|
1164
|
+
async function loadSSRModule() {
|
|
1165
|
+
if (!isProduction && vite) {
|
|
1166
|
+
return await vite.ssrLoadModule(ssrEntryPath);
|
|
710
1167
|
}
|
|
711
|
-
if (
|
|
712
|
-
return
|
|
1168
|
+
if (ssrProductionModule) {
|
|
1169
|
+
return import(ssrProductionModule);
|
|
713
1170
|
}
|
|
714
|
-
|
|
1171
|
+
const { resolve } = await import(
|
|
1172
|
+
/* @vite-ignore */
|
|
1173
|
+
"path"
|
|
1174
|
+
);
|
|
1175
|
+
const { pathToFileURL } = await import(
|
|
1176
|
+
/* @vite-ignore */
|
|
1177
|
+
"url"
|
|
1178
|
+
);
|
|
1179
|
+
const absPath = pathToFileURL(resolve(root, "dist/server/ssr.js")).href;
|
|
1180
|
+
return import(absPath);
|
|
715
1181
|
}
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
// ../core/src/intents/base-controller.ts
|
|
719
|
-
var BaseController = class {
|
|
720
|
-
/**
|
|
721
|
-
* 错误回退 — 子类可选覆写
|
|
722
|
-
*
|
|
723
|
-
* 当 execute() 抛出异常时调用。
|
|
724
|
-
* 默认行为: 重新抛出原始错误。
|
|
725
|
-
*
|
|
726
|
-
* @param params - Intent 参数
|
|
727
|
-
* @param error - execute() 抛出的错误
|
|
728
|
-
* @returns 回退数据
|
|
729
|
-
*/
|
|
730
|
-
fallback(params, error) {
|
|
731
|
-
throw error;
|
|
732
|
-
}
|
|
733
|
-
/**
|
|
734
|
-
* IntentController.perform() 实现
|
|
735
|
-
*
|
|
736
|
-
* 自动 try/catch → fallback 模式。
|
|
737
|
-
*/
|
|
738
|
-
async perform(intent, container) {
|
|
739
|
-
const params = intent.params ?? {};
|
|
1182
|
+
app.get("*", async (c) => {
|
|
1183
|
+
const url = c.req.path + (c.req.url.includes("?") ? "?" + c.req.url.split("?")[1] : "");
|
|
740
1184
|
try {
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
1185
|
+
const template = await readTemplate(url);
|
|
1186
|
+
const { render, serializeServerData: serializeServerData2 } = await loadSSRModule();
|
|
1187
|
+
const locale = parseAcceptLanguage(
|
|
1188
|
+
c.req.header("accept-language"),
|
|
1189
|
+
supportedLocales,
|
|
1190
|
+
defaultLocale
|
|
746
1191
|
);
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
}
|
|
767
|
-
|
|
768
|
-
// ../core/src/bootstrap/define-routes.ts
|
|
769
|
-
function defineRoutes(framework, definitions) {
|
|
770
|
-
const registeredIntents = /* @__PURE__ */ new Set();
|
|
771
|
-
for (const def of definitions) {
|
|
772
|
-
if (def.controller && !registeredIntents.has(def.intentId)) {
|
|
773
|
-
framework.registerIntent(def.controller);
|
|
774
|
-
registeredIntents.add(def.intentId);
|
|
775
|
-
}
|
|
776
|
-
framework.router.add(def.path, def.intentId);
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
// ../core/src/utils/lru-map.ts
|
|
781
|
-
var LruMap = class {
|
|
782
|
-
map = /* @__PURE__ */ new Map();
|
|
783
|
-
capacity;
|
|
784
|
-
constructor(capacity) {
|
|
785
|
-
this.capacity = capacity;
|
|
786
|
-
}
|
|
787
|
-
get(key) {
|
|
788
|
-
const value = this.map.get(key);
|
|
789
|
-
if (value !== void 0) {
|
|
790
|
-
this.map.delete(key);
|
|
791
|
-
this.map.set(key, value);
|
|
792
|
-
}
|
|
793
|
-
return value;
|
|
794
|
-
}
|
|
795
|
-
set(key, value) {
|
|
796
|
-
if (this.map.has(key)) {
|
|
797
|
-
this.map.delete(key);
|
|
798
|
-
} else if (this.map.size >= this.capacity) {
|
|
799
|
-
const oldest = this.map.keys().next().value;
|
|
800
|
-
if (oldest !== void 0) {
|
|
801
|
-
this.map.delete(oldest);
|
|
1192
|
+
const {
|
|
1193
|
+
html: appHtml,
|
|
1194
|
+
head,
|
|
1195
|
+
css,
|
|
1196
|
+
serverData
|
|
1197
|
+
} = await render(url, locale);
|
|
1198
|
+
const serializedData = serializeServerData2(serverData);
|
|
1199
|
+
const finalHtml = injectSSRContent({
|
|
1200
|
+
template,
|
|
1201
|
+
locale,
|
|
1202
|
+
head,
|
|
1203
|
+
css,
|
|
1204
|
+
html: appHtml,
|
|
1205
|
+
serializedData
|
|
1206
|
+
});
|
|
1207
|
+
return c.html(finalHtml);
|
|
1208
|
+
} catch (e) {
|
|
1209
|
+
if (!isProduction && vite) {
|
|
1210
|
+
vite.ssrFixStacktrace(e);
|
|
802
1211
|
}
|
|
1212
|
+
console.error("[SSR Error]", e);
|
|
1213
|
+
return c.text("Internal Server Error", 500);
|
|
803
1214
|
}
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
has(key) {
|
|
807
|
-
return this.map.has(key);
|
|
808
|
-
}
|
|
809
|
-
delete(key) {
|
|
810
|
-
return this.map.delete(key);
|
|
811
|
-
}
|
|
812
|
-
get size() {
|
|
813
|
-
return this.map.size;
|
|
814
|
-
}
|
|
815
|
-
clear() {
|
|
816
|
-
this.map.clear();
|
|
817
|
-
}
|
|
818
|
-
};
|
|
819
|
-
|
|
820
|
-
// ../core/src/utils/optional.ts
|
|
821
|
-
function isSome(value) {
|
|
822
|
-
return value !== null && value !== void 0;
|
|
823
|
-
}
|
|
824
|
-
function isNone(value) {
|
|
825
|
-
return value === null || value === void 0;
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
// ../core/src/utils/url.ts
|
|
829
|
-
function removeScheme(url) {
|
|
830
|
-
return url.replace(/^https?:\/\//, "");
|
|
831
|
-
}
|
|
832
|
-
function removeHost(url) {
|
|
833
|
-
try {
|
|
834
|
-
const parsed = new URL(url);
|
|
835
|
-
return parsed.pathname + parsed.search + parsed.hash;
|
|
836
|
-
} catch {
|
|
837
|
-
return url;
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
function removeQueryParams(url) {
|
|
841
|
-
return url.split("?")[0];
|
|
842
|
-
}
|
|
843
|
-
function getBaseUrl(url) {
|
|
844
|
-
return url.split("?")[0].split("#")[0];
|
|
1215
|
+
});
|
|
1216
|
+
return app;
|
|
845
1217
|
}
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
1218
|
+
var import_hono, import_meta;
|
|
1219
|
+
var init_app = __esm({
|
|
1220
|
+
"../server/src/app.ts"() {
|
|
1221
|
+
"use strict";
|
|
1222
|
+
init_src2();
|
|
1223
|
+
import_hono = require("hono");
|
|
1224
|
+
init_locale();
|
|
1225
|
+
import_meta = {};
|
|
853
1226
|
}
|
|
854
|
-
|
|
855
|
-
return qs ? `${path}?${qs}` : path;
|
|
856
|
-
}
|
|
1227
|
+
});
|
|
857
1228
|
|
|
858
|
-
//
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
1229
|
+
// src/index.ts
|
|
1230
|
+
var index_exports = {};
|
|
1231
|
+
__export(index_exports, {
|
|
1232
|
+
ACTION_KINDS: () => ACTION_KINDS,
|
|
1233
|
+
ActionDispatcher: () => ActionDispatcher,
|
|
1234
|
+
BaseController: () => BaseController,
|
|
1235
|
+
BaseLogger: () => BaseLogger,
|
|
1236
|
+
CompositeLogger: () => CompositeLogger,
|
|
1237
|
+
CompositeLoggerFactory: () => CompositeLoggerFactory,
|
|
1238
|
+
ConsoleLogger: () => ConsoleLogger,
|
|
1239
|
+
ConsoleLoggerFactory: () => ConsoleLoggerFactory,
|
|
1240
|
+
Container: () => Container,
|
|
1241
|
+
DEP_KEYS: () => DEP_KEYS,
|
|
1242
|
+
Framework: () => Framework,
|
|
1243
|
+
History: () => History,
|
|
1244
|
+
HttpClient: () => HttpClient,
|
|
1245
|
+
HttpError: () => HttpError,
|
|
1246
|
+
IntentDispatcher: () => IntentDispatcher,
|
|
1247
|
+
LruMap: () => LruMap,
|
|
1248
|
+
PrefetchedIntents: () => PrefetchedIntents,
|
|
1249
|
+
Router: () => Router,
|
|
1250
|
+
SSR_PLACEHOLDERS: () => SSR_PLACEHOLDERS,
|
|
1251
|
+
autoAdapter: () => autoAdapter,
|
|
1252
|
+
buildUrl: () => buildUrl,
|
|
1253
|
+
cloudflareAdapter: () => cloudflareAdapter,
|
|
1254
|
+
createPrefetchedIntentsFromDom: () => createPrefetchedIntentsFromDom,
|
|
1255
|
+
createSSRApp: () => createSSRApp,
|
|
1256
|
+
createSSRRender: () => createSSRRender,
|
|
1257
|
+
createServer: () => createServer,
|
|
1258
|
+
defineRoutes: () => defineRoutes,
|
|
1259
|
+
deserializeServerData: () => deserializeServerData,
|
|
1260
|
+
detectRuntime: () => detectRuntime,
|
|
1261
|
+
finesoftFrontViteConfig: () => finesoftFrontViteConfig,
|
|
1262
|
+
generateUuid: () => generateUuid,
|
|
1263
|
+
getBaseUrl: () => getBaseUrl,
|
|
1264
|
+
injectSSRContent: () => injectSSRContent,
|
|
1265
|
+
isCompoundAction: () => isCompoundAction,
|
|
1266
|
+
isExternalUrlAction: () => isExternalUrlAction,
|
|
1267
|
+
isFlowAction: () => isFlowAction,
|
|
1268
|
+
isNone: () => isNone,
|
|
1269
|
+
isSome: () => isSome,
|
|
1270
|
+
makeDependencies: () => makeDependencies,
|
|
1271
|
+
makeExternalUrlAction: () => makeExternalUrlAction,
|
|
1272
|
+
makeFlowAction: () => makeFlowAction,
|
|
1273
|
+
mapEach: () => mapEach,
|
|
1274
|
+
netlifyAdapter: () => netlifyAdapter,
|
|
1275
|
+
nodeAdapter: () => nodeAdapter,
|
|
1276
|
+
parseAcceptLanguage: () => parseAcceptLanguage,
|
|
1277
|
+
pipe: () => pipe,
|
|
1278
|
+
pipeAsync: () => pipeAsync,
|
|
1279
|
+
registerActionHandlers: () => registerActionHandlers,
|
|
1280
|
+
registerExternalUrlHandler: () => registerExternalUrlHandler,
|
|
1281
|
+
registerFlowActionHandler: () => registerFlowActionHandler,
|
|
1282
|
+
removeHost: () => removeHost,
|
|
1283
|
+
removeQueryParams: () => removeQueryParams,
|
|
1284
|
+
removeScheme: () => removeScheme,
|
|
1285
|
+
resetFilterCache: () => resetFilterCache,
|
|
1286
|
+
resolveAdapter: () => resolveAdapter,
|
|
1287
|
+
resolveRoot: () => resolveRoot,
|
|
1288
|
+
serializeServerData: () => serializeServerData,
|
|
1289
|
+
shouldLog: () => shouldLog,
|
|
1290
|
+
ssrRender: () => ssrRender,
|
|
1291
|
+
stableStringify: () => stableStringify,
|
|
1292
|
+
startBrowserApp: () => startBrowserApp,
|
|
1293
|
+
startServer: () => startServer,
|
|
1294
|
+
staticAdapter: () => staticAdapter,
|
|
1295
|
+
tryScroll: () => tryScroll,
|
|
1296
|
+
vercelAdapter: () => vercelAdapter
|
|
1297
|
+
});
|
|
1298
|
+
module.exports = __toCommonJS(index_exports);
|
|
1299
|
+
init_src();
|
|
869
1300
|
|
|
870
1301
|
// ../browser/src/action-handlers/external-url-action.ts
|
|
1302
|
+
init_src();
|
|
871
1303
|
function registerExternalUrlHandler(deps) {
|
|
872
1304
|
const { framework, log } = deps;
|
|
873
1305
|
framework.onAction(
|
|
@@ -879,6 +1311,12 @@ function registerExternalUrlHandler(deps) {
|
|
|
879
1311
|
);
|
|
880
1312
|
}
|
|
881
1313
|
|
|
1314
|
+
// ../browser/src/action-handlers/flow-action.ts
|
|
1315
|
+
init_src();
|
|
1316
|
+
|
|
1317
|
+
// ../browser/src/utils/history.ts
|
|
1318
|
+
init_src();
|
|
1319
|
+
|
|
882
1320
|
// ../browser/src/utils/try-scroll.ts
|
|
883
1321
|
var MAX_TRIES = 100;
|
|
884
1322
|
var FUDGE = 16;
|
|
@@ -1126,7 +1564,11 @@ function registerActionHandlers(deps) {
|
|
|
1126
1564
|
registerExternalUrlHandler({ framework, log });
|
|
1127
1565
|
}
|
|
1128
1566
|
|
|
1567
|
+
// ../browser/src/start-app.ts
|
|
1568
|
+
init_src();
|
|
1569
|
+
|
|
1129
1570
|
// ../browser/src/server-data.ts
|
|
1571
|
+
init_src();
|
|
1130
1572
|
var SERVER_DATA_ID = "serialized-server-data";
|
|
1131
1573
|
function deserializeServerData() {
|
|
1132
1574
|
const script = document.getElementById(SERVER_DATA_ID);
|
|
@@ -1184,205 +1626,459 @@ async function startBrowserApp(config) {
|
|
|
1184
1626
|
}
|
|
1185
1627
|
}
|
|
1186
1628
|
|
|
1187
|
-
// ../
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1629
|
+
// ../browser/src/index.ts
|
|
1630
|
+
init_src();
|
|
1631
|
+
|
|
1632
|
+
// src/index.ts
|
|
1633
|
+
init_src2();
|
|
1634
|
+
|
|
1635
|
+
// ../server/src/adapters/shared.ts
|
|
1636
|
+
var BUILD_TOOL_EXTERNALS = [
|
|
1637
|
+
"vite",
|
|
1638
|
+
"esbuild",
|
|
1639
|
+
"rollup",
|
|
1640
|
+
"fsevents",
|
|
1641
|
+
"lightningcss"
|
|
1642
|
+
];
|
|
1643
|
+
function generateSSREntry(ctx, opts) {
|
|
1644
|
+
const setupImport = ctx.setupPath ? `import _setupDefault from "./${ctx.setupPath}";` : ``;
|
|
1645
|
+
const setupCall = ctx.setupPath ? `if (typeof _setupDefault === "function") await _setupDefault(app);` : ``;
|
|
1646
|
+
const locales = JSON.stringify(ctx.locales);
|
|
1647
|
+
const defaultLocale = JSON.stringify(ctx.defaultLocale);
|
|
1648
|
+
return `
|
|
1649
|
+
import { Hono } from "hono";
|
|
1650
|
+
${opts.platformImport}
|
|
1651
|
+
import { render, serializeServerData } from "./${ctx.ssrEntry}";
|
|
1652
|
+
${setupImport}
|
|
1653
|
+
|
|
1654
|
+
const TEMPLATE = ${JSON.stringify(ctx.templateHtml)};
|
|
1655
|
+
const LOCALES = ${locales};
|
|
1656
|
+
const DEFAULT_LOCALE = ${defaultLocale};
|
|
1657
|
+
|
|
1658
|
+
function parseAcceptLanguage(header) {
|
|
1659
|
+
if (!header) return DEFAULT_LOCALE;
|
|
1660
|
+
const langs = header.split(",").map(p => {
|
|
1661
|
+
const [l, q] = p.trim().split(";q=");
|
|
1662
|
+
return { l: l.trim().toLowerCase(), q: q ? +q : 1 };
|
|
1663
|
+
}).sort((a, b) => b.q - a.q);
|
|
1664
|
+
for (const { l } of langs) {
|
|
1665
|
+
const prefix = l.split("-")[0];
|
|
1666
|
+
if (LOCALES.includes(prefix)) return prefix;
|
|
1206
1667
|
}
|
|
1207
|
-
|
|
1208
|
-
framework.dispose();
|
|
1209
|
-
return {
|
|
1210
|
-
html: result.html,
|
|
1211
|
-
head: result.head,
|
|
1212
|
-
css: result.css,
|
|
1213
|
-
serverData
|
|
1214
|
-
};
|
|
1668
|
+
return DEFAULT_LOCALE;
|
|
1215
1669
|
}
|
|
1216
1670
|
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
bootstrap,
|
|
1224
|
-
getErrorPage,
|
|
1225
|
-
renderApp: (page) => renderApp(page, locale)
|
|
1226
|
-
});
|
|
1671
|
+
function injectSSR(t, locale, head, css, html, data) {
|
|
1672
|
+
return t
|
|
1673
|
+
.replace("<!--ssr-lang-->", locale)
|
|
1674
|
+
.replace("<!--ssr-head-->", head + "\\n<style>" + css + "</style>")
|
|
1675
|
+
.replace("<!--ssr-body-->", html)
|
|
1676
|
+
.replace("<!--ssr-data-->", '<script id="serialized-server-data" type="application/json">' + data + "</script>");
|
|
1227
1677
|
}
|
|
1228
1678
|
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1679
|
+
const app = new Hono();
|
|
1680
|
+
${setupCall}
|
|
1681
|
+
|
|
1682
|
+
app.get("*", async (c) => {
|
|
1683
|
+
const url = c.req.path + (c.req.url.includes("?") ? "?" + c.req.url.split("?")[1] : "");
|
|
1684
|
+
try {
|
|
1685
|
+
const locale = parseAcceptLanguage(c.req.header("accept-language"));
|
|
1686
|
+
const { html: appHtml, head, css, serverData } = await render(url, locale);
|
|
1687
|
+
const serializedData = serializeServerData(serverData);
|
|
1688
|
+
return c.html(injectSSR(TEMPLATE, locale, head, css, appHtml, serializedData));
|
|
1689
|
+
} catch (e) {
|
|
1690
|
+
console.error("[SSR Error]", e);
|
|
1691
|
+
return c.text("Internal Server Error", 500);
|
|
1692
|
+
}
|
|
1693
|
+
});
|
|
1694
|
+
|
|
1695
|
+
${opts.platformExport}
|
|
1696
|
+
`;
|
|
1697
|
+
}
|
|
1698
|
+
async function buildBundle(ctx, opts) {
|
|
1699
|
+
await ctx.vite.build({
|
|
1700
|
+
root: ctx.root,
|
|
1701
|
+
build: {
|
|
1702
|
+
ssr: opts.entry,
|
|
1703
|
+
outDir: opts.outDir,
|
|
1704
|
+
emptyOutDir: true,
|
|
1705
|
+
target: opts.target ?? "node18",
|
|
1706
|
+
rollupOptions: {
|
|
1707
|
+
output: { entryFileNames: opts.fileName ?? "index.mjs" }
|
|
1708
|
+
}
|
|
1709
|
+
},
|
|
1710
|
+
ssr: {
|
|
1711
|
+
noExternal: opts.noExternal !== false,
|
|
1712
|
+
external: opts.external ?? BUILD_TOOL_EXTERNALS
|
|
1713
|
+
},
|
|
1714
|
+
resolve: ctx.resolvedResolve,
|
|
1715
|
+
css: ctx.resolvedCss
|
|
1716
|
+
});
|
|
1717
|
+
}
|
|
1718
|
+
function copyStaticAssets(ctx, destDir, opts) {
|
|
1719
|
+
const { fs, path } = ctx;
|
|
1720
|
+
fs.cpSync(path.resolve(ctx.root, "dist/client"), destDir, {
|
|
1721
|
+
recursive: true
|
|
1722
|
+
});
|
|
1723
|
+
if (opts?.excludeHtml !== false) {
|
|
1724
|
+
fs.rmSync(path.join(destDir, "index.html"), { force: true });
|
|
1725
|
+
}
|
|
1244
1726
|
}
|
|
1245
1727
|
|
|
1246
|
-
// ../
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
};
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1728
|
+
// ../server/src/adapters/cloudflare.ts
|
|
1729
|
+
function cloudflareAdapter() {
|
|
1730
|
+
return {
|
|
1731
|
+
name: "cloudflare",
|
|
1732
|
+
async build(ctx) {
|
|
1733
|
+
const { fs, path, root } = ctx;
|
|
1734
|
+
const outputDir = path.resolve(root, "dist/cloudflare");
|
|
1735
|
+
fs.rmSync(outputDir, { recursive: true, force: true });
|
|
1736
|
+
const entrySource = generateSSREntry(ctx, {
|
|
1737
|
+
platformImport: ``,
|
|
1738
|
+
platformExport: `export default app;`
|
|
1739
|
+
});
|
|
1740
|
+
const tempEntry = path.resolve(root, ".cf-entry.tmp.mjs");
|
|
1741
|
+
fs.writeFileSync(tempEntry, entrySource);
|
|
1742
|
+
try {
|
|
1743
|
+
await buildBundle(ctx, {
|
|
1744
|
+
entry: ".cf-entry.tmp.mjs",
|
|
1745
|
+
outDir: outputDir,
|
|
1746
|
+
target: "es2022",
|
|
1747
|
+
fileName: "_worker.js"
|
|
1748
|
+
// 使用默认 external(vite/esbuild/rollup/fsevents/lightningcss)
|
|
1749
|
+
// 这些构建工具运行时不需要,且 fsevents 是 macOS .node 原生二进制无法打包
|
|
1750
|
+
});
|
|
1751
|
+
copyStaticAssets(ctx, path.resolve(outputDir, "assets"));
|
|
1752
|
+
} finally {
|
|
1753
|
+
fs.rmSync(tempEntry, { force: true });
|
|
1754
|
+
}
|
|
1755
|
+
console.log(" Cloudflare output \u2192 dist/cloudflare/\n");
|
|
1756
|
+
}
|
|
1757
|
+
};
|
|
1261
1758
|
}
|
|
1262
1759
|
|
|
1263
|
-
// ../server/src/
|
|
1264
|
-
|
|
1760
|
+
// ../server/src/adapters/netlify.ts
|
|
1761
|
+
function netlifyAdapter() {
|
|
1762
|
+
return {
|
|
1763
|
+
name: "netlify",
|
|
1764
|
+
async build(ctx) {
|
|
1765
|
+
const { fs, path, root } = ctx;
|
|
1766
|
+
const funcDir = path.resolve(
|
|
1767
|
+
root,
|
|
1768
|
+
".netlify/functions-internal/ssr"
|
|
1769
|
+
);
|
|
1770
|
+
fs.rmSync(path.resolve(root, ".netlify"), {
|
|
1771
|
+
recursive: true,
|
|
1772
|
+
force: true
|
|
1773
|
+
});
|
|
1774
|
+
const entrySource = generateSSREntry(ctx, {
|
|
1775
|
+
platformImport: `import { handle } from "hono/netlify";`,
|
|
1776
|
+
platformExport: `export default handle(app);`
|
|
1777
|
+
});
|
|
1778
|
+
const tempEntry = path.resolve(root, ".netlify-entry.tmp.mjs");
|
|
1779
|
+
fs.writeFileSync(tempEntry, entrySource);
|
|
1780
|
+
try {
|
|
1781
|
+
await buildBundle(ctx, {
|
|
1782
|
+
entry: ".netlify-entry.tmp.mjs",
|
|
1783
|
+
outDir: funcDir,
|
|
1784
|
+
target: "node18"
|
|
1785
|
+
});
|
|
1786
|
+
} finally {
|
|
1787
|
+
fs.rmSync(tempEntry, { force: true });
|
|
1788
|
+
}
|
|
1789
|
+
const redirects = `/* /.netlify/functions/ssr 200
|
|
1790
|
+
`;
|
|
1791
|
+
fs.writeFileSync(
|
|
1792
|
+
path.resolve(root, "dist/client/_redirects"),
|
|
1793
|
+
redirects
|
|
1794
|
+
);
|
|
1795
|
+
console.log(
|
|
1796
|
+
" Netlify output \u2192 .netlify/functions-internal/ssr/\n Publish dir: dist/client/\n"
|
|
1797
|
+
);
|
|
1798
|
+
}
|
|
1799
|
+
};
|
|
1800
|
+
}
|
|
1265
1801
|
|
|
1266
|
-
// ../server/src/
|
|
1267
|
-
function
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1802
|
+
// ../server/src/adapters/node.ts
|
|
1803
|
+
function nodeAdapter() {
|
|
1804
|
+
return {
|
|
1805
|
+
name: "node",
|
|
1806
|
+
async build(ctx) {
|
|
1807
|
+
const { fs, path, root } = ctx;
|
|
1808
|
+
const entrySource = generateSSREntry(ctx, {
|
|
1809
|
+
platformImport: `import { serve } from "@hono/node-server";`,
|
|
1810
|
+
platformExport: `
|
|
1811
|
+
const port = +(process.env.PORT || 3000);
|
|
1812
|
+
serve({ fetch: app.fetch, port }, (info) => {
|
|
1813
|
+
console.log(\`Server running at http://localhost:\${info.port}\`);
|
|
1814
|
+
});
|
|
1815
|
+
`
|
|
1816
|
+
});
|
|
1817
|
+
const tempEntry = path.resolve(root, ".node-entry.tmp.mjs");
|
|
1818
|
+
fs.writeFileSync(tempEntry, entrySource);
|
|
1819
|
+
try {
|
|
1820
|
+
await buildBundle(ctx, {
|
|
1821
|
+
entry: ".node-entry.tmp.mjs",
|
|
1822
|
+
outDir: path.resolve(root, "dist/server"),
|
|
1823
|
+
target: "node18"
|
|
1824
|
+
});
|
|
1825
|
+
} finally {
|
|
1826
|
+
fs.rmSync(tempEntry, { force: true });
|
|
1827
|
+
}
|
|
1828
|
+
console.log(
|
|
1829
|
+
" Node output \u2192 dist/server/index.mjs\n Run: node dist/server/index.mjs\n"
|
|
1830
|
+
);
|
|
1282
1831
|
}
|
|
1283
|
-
}
|
|
1284
|
-
return effectiveFallback;
|
|
1832
|
+
};
|
|
1285
1833
|
}
|
|
1286
1834
|
|
|
1287
|
-
// ../server/src/
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
defaultLocale
|
|
1298
|
-
} = options;
|
|
1299
|
-
const app = new import_hono.Hono();
|
|
1300
|
-
async function readTemplate(url) {
|
|
1301
|
-
if (!isProduction && vite) {
|
|
1302
|
-
const { readFileSync: readFileSync2 } = await import(
|
|
1835
|
+
// ../server/src/adapters/static.ts
|
|
1836
|
+
function staticAdapter(opts = {}) {
|
|
1837
|
+
return {
|
|
1838
|
+
name: "static",
|
|
1839
|
+
async build(ctx) {
|
|
1840
|
+
const { fs, path, root, vite } = ctx;
|
|
1841
|
+
const outputDir = path.resolve(root, "dist/static");
|
|
1842
|
+
fs.rmSync(outputDir, { recursive: true, force: true });
|
|
1843
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
1844
|
+
const { pathToFileURL } = await import(
|
|
1303
1845
|
/* @vite-ignore */
|
|
1304
|
-
"
|
|
1846
|
+
"url"
|
|
1305
1847
|
);
|
|
1306
|
-
const
|
|
1848
|
+
const ssrPath = pathToFileURL(
|
|
1849
|
+
path.resolve(root, "dist/server/ssr.js")
|
|
1850
|
+
).href;
|
|
1851
|
+
const ssrModule = await import(
|
|
1307
1852
|
/* @vite-ignore */
|
|
1308
|
-
|
|
1853
|
+
ssrPath
|
|
1309
1854
|
);
|
|
1310
|
-
const
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1855
|
+
const routePaths = await extractRoutes(ctx, opts);
|
|
1856
|
+
const allUrls = [];
|
|
1857
|
+
for (const routePath of routePaths) {
|
|
1858
|
+
for (const locale of ctx.locales) {
|
|
1859
|
+
const url = locale === ctx.defaultLocale ? routePath : `/${locale}${routePath === "/" ? "" : routePath}`;
|
|
1860
|
+
allUrls.push(url);
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1863
|
+
console.log(
|
|
1864
|
+
` Pre-rendering ${allUrls.length} pages (${routePaths.length} routes \xD7 ${ctx.locales.length} locales)...
|
|
1865
|
+
`
|
|
1317
1866
|
);
|
|
1867
|
+
for (const url of allUrls) {
|
|
1868
|
+
try {
|
|
1869
|
+
const locale = inferLocale(
|
|
1870
|
+
url,
|
|
1871
|
+
ctx.locales,
|
|
1872
|
+
ctx.defaultLocale
|
|
1873
|
+
);
|
|
1874
|
+
const {
|
|
1875
|
+
html: appHtml,
|
|
1876
|
+
head,
|
|
1877
|
+
css,
|
|
1878
|
+
serverData
|
|
1879
|
+
} = await ssrModule.render(url, locale);
|
|
1880
|
+
const serializedData = ssrModule.serializeServerData(serverData);
|
|
1881
|
+
const finalHtml = injectSSRForStatic(
|
|
1882
|
+
ctx.templateHtml,
|
|
1883
|
+
locale,
|
|
1884
|
+
head,
|
|
1885
|
+
css,
|
|
1886
|
+
appHtml,
|
|
1887
|
+
serializedData
|
|
1888
|
+
);
|
|
1889
|
+
const filePath = url === "/" ? path.join(outputDir, "index.html") : path.join(outputDir, url, "index.html");
|
|
1890
|
+
fs.mkdirSync(path.resolve(filePath, ".."), {
|
|
1891
|
+
recursive: true
|
|
1892
|
+
});
|
|
1893
|
+
fs.writeFileSync(filePath, finalHtml);
|
|
1894
|
+
} catch (e) {
|
|
1895
|
+
console.warn(` [static] Failed to render ${url}:`, e);
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1898
|
+
ctx.copyStaticAssets(outputDir, { excludeHtml: true });
|
|
1899
|
+
console.log(` Static output \u2192 dist/static/
|
|
1900
|
+
`);
|
|
1318
1901
|
}
|
|
1319
|
-
|
|
1902
|
+
};
|
|
1903
|
+
}
|
|
1904
|
+
async function extractRoutes(ctx, opts) {
|
|
1905
|
+
const routesFile = opts.routesExport ?? "src/lib/bootstrap.ts";
|
|
1906
|
+
const paths = [];
|
|
1907
|
+
try {
|
|
1908
|
+
const { pathToFileURL } = await import(
|
|
1320
1909
|
/* @vite-ignore */
|
|
1321
|
-
"
|
|
1910
|
+
"url"
|
|
1322
1911
|
);
|
|
1323
|
-
|
|
1912
|
+
await ctx.vite.build({
|
|
1913
|
+
root: ctx.root,
|
|
1914
|
+
build: {
|
|
1915
|
+
ssr: routesFile,
|
|
1916
|
+
outDir: ctx.path.resolve(ctx.root, "dist/server"),
|
|
1917
|
+
emptyOutDir: false,
|
|
1918
|
+
rollupOptions: {
|
|
1919
|
+
output: { entryFileNames: "_routes.mjs" }
|
|
1920
|
+
}
|
|
1921
|
+
},
|
|
1922
|
+
resolve: ctx.resolvedResolve
|
|
1923
|
+
});
|
|
1924
|
+
const routesPath = pathToFileURL(
|
|
1925
|
+
ctx.path.resolve(ctx.root, "dist/server/_routes.mjs")
|
|
1926
|
+
).href;
|
|
1927
|
+
const routesMod = await import(
|
|
1324
1928
|
/* @vite-ignore */
|
|
1325
|
-
|
|
1929
|
+
routesPath
|
|
1326
1930
|
);
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
return import(ssrProductionModule);
|
|
1931
|
+
const routes = routesMod.routes ?? routesMod.default;
|
|
1932
|
+
if (Array.isArray(routes)) {
|
|
1933
|
+
for (const r of routes) {
|
|
1934
|
+
if (r.path && !r.path.includes(":")) {
|
|
1935
|
+
paths.push(r.path);
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1335
1938
|
}
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1939
|
+
ctx.fs.rmSync(ctx.path.resolve(ctx.root, "dist/server/_routes.mjs"), {
|
|
1940
|
+
force: true
|
|
1941
|
+
});
|
|
1942
|
+
} catch (e) {
|
|
1943
|
+
console.warn(
|
|
1944
|
+
` [static] Could not load routes from "${routesFile}". Using "/" only.`,
|
|
1945
|
+
e
|
|
1343
1946
|
);
|
|
1344
|
-
|
|
1345
|
-
return import(absPath);
|
|
1947
|
+
if (paths.length === 0) paths.push("/");
|
|
1346
1948
|
}
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1949
|
+
if (opts.dynamicRoutes) {
|
|
1950
|
+
for (const r of opts.dynamicRoutes) {
|
|
1951
|
+
if (!paths.includes(r)) paths.push(r);
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
if (paths.length === 0) paths.push("/");
|
|
1955
|
+
return paths;
|
|
1956
|
+
}
|
|
1957
|
+
function inferLocale(url, locales, defaultLocale) {
|
|
1958
|
+
const segments = url.split("/").filter(Boolean);
|
|
1959
|
+
if (segments.length > 0 && locales.includes(segments[0])) {
|
|
1960
|
+
return segments[0];
|
|
1961
|
+
}
|
|
1962
|
+
return defaultLocale;
|
|
1963
|
+
}
|
|
1964
|
+
function injectSSRForStatic(template, locale, head, css, html, serializedData) {
|
|
1965
|
+
return template.replace("<!--ssr-lang-->", locale).replace("<!--ssr-head-->", head + "\n<style>" + css + "</style>").replace("<!--ssr-body-->", html).replace(
|
|
1966
|
+
"<!--ssr-data-->",
|
|
1967
|
+
'<script id="serialized-server-data" type="application/json">' + serializedData + "</script>"
|
|
1968
|
+
);
|
|
1969
|
+
}
|
|
1970
|
+
|
|
1971
|
+
// ../server/src/adapters/vercel.ts
|
|
1972
|
+
function vercelAdapter() {
|
|
1973
|
+
return {
|
|
1974
|
+
name: "vercel",
|
|
1975
|
+
async build(ctx) {
|
|
1976
|
+
const { fs, path, root } = ctx;
|
|
1977
|
+
const outputDir = path.resolve(root, ".vercel/output");
|
|
1978
|
+
fs.rmSync(outputDir, { recursive: true, force: true });
|
|
1979
|
+
const entrySource = generateSSREntry(ctx, {
|
|
1980
|
+
platformImport: `import { handle } from "hono/vercel";`,
|
|
1981
|
+
platformExport: `export default handle(app);`
|
|
1371
1982
|
});
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1983
|
+
const tempEntry = path.resolve(root, ".vercel-entry.tmp.mjs");
|
|
1984
|
+
fs.writeFileSync(tempEntry, entrySource);
|
|
1985
|
+
try {
|
|
1986
|
+
const funcDir = path.resolve(
|
|
1987
|
+
root,
|
|
1988
|
+
".vercel/output/functions/ssr.func"
|
|
1989
|
+
);
|
|
1990
|
+
await buildBundle(ctx, {
|
|
1991
|
+
entry: ".vercel-entry.tmp.mjs",
|
|
1992
|
+
outDir: funcDir,
|
|
1993
|
+
target: "node18"
|
|
1994
|
+
});
|
|
1995
|
+
fs.writeFileSync(
|
|
1996
|
+
path.resolve(funcDir, ".vc-config.json"),
|
|
1997
|
+
JSON.stringify(
|
|
1998
|
+
{
|
|
1999
|
+
runtime: "nodejs20.x",
|
|
2000
|
+
handler: "index.mjs",
|
|
2001
|
+
launcherType: "Nodejs"
|
|
2002
|
+
},
|
|
2003
|
+
null,
|
|
2004
|
+
2
|
|
2005
|
+
)
|
|
2006
|
+
);
|
|
2007
|
+
copyStaticAssets(
|
|
2008
|
+
ctx,
|
|
2009
|
+
path.resolve(root, ".vercel/output/static")
|
|
2010
|
+
);
|
|
2011
|
+
fs.writeFileSync(
|
|
2012
|
+
path.resolve(root, ".vercel/output/config.json"),
|
|
2013
|
+
JSON.stringify(
|
|
2014
|
+
{
|
|
2015
|
+
version: 3,
|
|
2016
|
+
routes: [
|
|
2017
|
+
{ handle: "filesystem" },
|
|
2018
|
+
{ src: "/(.*)", dest: "/ssr" }
|
|
2019
|
+
]
|
|
2020
|
+
},
|
|
2021
|
+
null,
|
|
2022
|
+
2
|
|
2023
|
+
)
|
|
2024
|
+
);
|
|
2025
|
+
} finally {
|
|
2026
|
+
fs.rmSync(tempEntry, { force: true });
|
|
1376
2027
|
}
|
|
1377
|
-
console.
|
|
1378
|
-
return c.text("Internal Server Error", 500);
|
|
2028
|
+
console.log(" Vercel output \u2192 .vercel/output/\n");
|
|
1379
2029
|
}
|
|
1380
|
-
}
|
|
1381
|
-
|
|
2030
|
+
};
|
|
2031
|
+
}
|
|
2032
|
+
|
|
2033
|
+
// ../server/src/adapters/resolve.ts
|
|
2034
|
+
function resolveAdapter(value) {
|
|
2035
|
+
if (typeof value !== "string") return value;
|
|
2036
|
+
switch (value) {
|
|
2037
|
+
case "vercel":
|
|
2038
|
+
return vercelAdapter();
|
|
2039
|
+
case "cloudflare":
|
|
2040
|
+
return cloudflareAdapter();
|
|
2041
|
+
case "netlify":
|
|
2042
|
+
return netlifyAdapter();
|
|
2043
|
+
case "node":
|
|
2044
|
+
return nodeAdapter();
|
|
2045
|
+
case "static":
|
|
2046
|
+
return staticAdapter();
|
|
2047
|
+
case "auto":
|
|
2048
|
+
return autoAdapter();
|
|
2049
|
+
default:
|
|
2050
|
+
throw new Error(
|
|
2051
|
+
`[finesoft] Unknown adapter: "${value}". Available: vercel, cloudflare, netlify, node, static, auto`
|
|
2052
|
+
);
|
|
2053
|
+
}
|
|
2054
|
+
}
|
|
2055
|
+
|
|
2056
|
+
// ../server/src/adapters/auto.ts
|
|
2057
|
+
function autoAdapter() {
|
|
2058
|
+
return {
|
|
2059
|
+
name: "auto",
|
|
2060
|
+
async build(ctx) {
|
|
2061
|
+
const detected = detectPlatform();
|
|
2062
|
+
console.log(` [auto] Detected platform: ${detected}
|
|
2063
|
+
`);
|
|
2064
|
+
const adapter = resolveAdapter(detected);
|
|
2065
|
+
return adapter.build(ctx);
|
|
2066
|
+
}
|
|
2067
|
+
};
|
|
1382
2068
|
}
|
|
2069
|
+
function detectPlatform() {
|
|
2070
|
+
if (process.env.VERCEL) return "vercel";
|
|
2071
|
+
if (process.env.CF_PAGES) return "cloudflare";
|
|
2072
|
+
if (process.env.NETLIFY) return "netlify";
|
|
2073
|
+
return "node";
|
|
2074
|
+
}
|
|
2075
|
+
|
|
2076
|
+
// ../server/src/index.ts
|
|
2077
|
+
init_app();
|
|
1383
2078
|
|
|
1384
2079
|
// ../server/src/create-server.ts
|
|
1385
2080
|
var import_hono3 = require("hono");
|
|
2081
|
+
init_app();
|
|
1386
2082
|
|
|
1387
2083
|
// ../server/src/runtime.ts
|
|
1388
2084
|
function detectRuntime() {
|
|
@@ -1590,6 +2286,251 @@ async function createServer(config = {}) {
|
|
|
1590
2286
|
});
|
|
1591
2287
|
return { app, vite, runtime };
|
|
1592
2288
|
}
|
|
2289
|
+
|
|
2290
|
+
// ../server/src/index.ts
|
|
2291
|
+
init_locale();
|
|
2292
|
+
|
|
2293
|
+
// ../server/src/vite-plugin.ts
|
|
2294
|
+
function resolveSetupFn(mod) {
|
|
2295
|
+
if (typeof mod.default === "function") return mod.default;
|
|
2296
|
+
if (typeof mod.setup === "function") return mod.setup;
|
|
2297
|
+
const first = Object.values(mod).find((v) => typeof v === "function");
|
|
2298
|
+
return first ?? null;
|
|
2299
|
+
}
|
|
2300
|
+
function finesoftFrontViteConfig(options = {}) {
|
|
2301
|
+
const ssrEntry = options.ssr?.entry ?? "src/ssr.ts";
|
|
2302
|
+
let root = process.cwd();
|
|
2303
|
+
let resolvedCommand;
|
|
2304
|
+
let resolvedResolve;
|
|
2305
|
+
let resolvedCss;
|
|
2306
|
+
return {
|
|
2307
|
+
name: "finesoft-front",
|
|
2308
|
+
config(userConfig, env) {
|
|
2309
|
+
const overrides = {
|
|
2310
|
+
appType: "custom"
|
|
2311
|
+
};
|
|
2312
|
+
if (env.command === "build" && !process.env.__FINESOFT_SUB_BUILD__) {
|
|
2313
|
+
overrides.build = {
|
|
2314
|
+
outDir: userConfig.build?.outDir ?? "dist/client"
|
|
2315
|
+
};
|
|
2316
|
+
}
|
|
2317
|
+
return overrides;
|
|
2318
|
+
},
|
|
2319
|
+
configResolved(config) {
|
|
2320
|
+
resolvedCommand = config.command;
|
|
2321
|
+
resolvedResolve = config.resolve;
|
|
2322
|
+
resolvedCss = config.css;
|
|
2323
|
+
root = config.root;
|
|
2324
|
+
},
|
|
2325
|
+
// ─── Dev ───────────────────────────────────────────────
|
|
2326
|
+
configureServer(server) {
|
|
2327
|
+
return async () => {
|
|
2328
|
+
const { Hono: HonoClass } = await import(
|
|
2329
|
+
/* @vite-ignore */
|
|
2330
|
+
"hono"
|
|
2331
|
+
);
|
|
2332
|
+
const { createSSRApp: createSSRApp2 } = await Promise.resolve().then(() => (init_app(), app_exports));
|
|
2333
|
+
const { getRequestListener } = await import(
|
|
2334
|
+
/* @vite-ignore */
|
|
2335
|
+
"@hono/node-server"
|
|
2336
|
+
);
|
|
2337
|
+
const app = new HonoClass();
|
|
2338
|
+
if (typeof options.setup === "function") {
|
|
2339
|
+
await options.setup(app);
|
|
2340
|
+
} else if (typeof options.setup === "string") {
|
|
2341
|
+
const mod = await server.ssrLoadModule("/" + options.setup);
|
|
2342
|
+
const fn = resolveSetupFn(mod);
|
|
2343
|
+
if (fn) await fn(app);
|
|
2344
|
+
}
|
|
2345
|
+
const ssrApp = createSSRApp2({
|
|
2346
|
+
root,
|
|
2347
|
+
vite: server,
|
|
2348
|
+
isProduction: false,
|
|
2349
|
+
ssrEntryPath: "/" + ssrEntry,
|
|
2350
|
+
supportedLocales: options.locales,
|
|
2351
|
+
defaultLocale: options.defaultLocale
|
|
2352
|
+
});
|
|
2353
|
+
app.route("/", ssrApp);
|
|
2354
|
+
const listener = getRequestListener(app.fetch);
|
|
2355
|
+
server.middlewares.use((req, res) => {
|
|
2356
|
+
listener(req, res);
|
|
2357
|
+
});
|
|
2358
|
+
};
|
|
2359
|
+
},
|
|
2360
|
+
// ─── Preview ───────────────────────────────────────────
|
|
2361
|
+
configurePreviewServer(server) {
|
|
2362
|
+
return async () => {
|
|
2363
|
+
const { readFileSync } = await import(
|
|
2364
|
+
/* @vite-ignore */
|
|
2365
|
+
"fs"
|
|
2366
|
+
);
|
|
2367
|
+
const { resolve } = await import(
|
|
2368
|
+
/* @vite-ignore */
|
|
2369
|
+
"path"
|
|
2370
|
+
);
|
|
2371
|
+
const { pathToFileURL } = await import(
|
|
2372
|
+
/* @vite-ignore */
|
|
2373
|
+
"url"
|
|
2374
|
+
);
|
|
2375
|
+
const { Hono: HonoClass } = await import(
|
|
2376
|
+
/* @vite-ignore */
|
|
2377
|
+
"hono"
|
|
2378
|
+
);
|
|
2379
|
+
const { injectSSRContent: injectSSRContent2 } = await Promise.resolve().then(() => (init_src2(), src_exports));
|
|
2380
|
+
const { parseAcceptLanguage: parseAcceptLanguage2 } = await Promise.resolve().then(() => (init_locale(), locale_exports));
|
|
2381
|
+
const { getRequestListener } = await import(
|
|
2382
|
+
/* @vite-ignore */
|
|
2383
|
+
"@hono/node-server"
|
|
2384
|
+
);
|
|
2385
|
+
const app = new HonoClass();
|
|
2386
|
+
if (typeof options.setup === "function") {
|
|
2387
|
+
await options.setup(app);
|
|
2388
|
+
} else if (typeof options.setup === "string") {
|
|
2389
|
+
try {
|
|
2390
|
+
const setupPath = pathToFileURL(
|
|
2391
|
+
resolve(root, "dist/server/setup.mjs")
|
|
2392
|
+
).href;
|
|
2393
|
+
const mod = await import(
|
|
2394
|
+
/* @vite-ignore */
|
|
2395
|
+
setupPath
|
|
2396
|
+
);
|
|
2397
|
+
const fn = resolveSetupFn(
|
|
2398
|
+
mod
|
|
2399
|
+
);
|
|
2400
|
+
if (fn) await fn(app);
|
|
2401
|
+
} catch {
|
|
2402
|
+
console.warn(
|
|
2403
|
+
"[finesoft] Could not load setup module for preview. API routes disabled."
|
|
2404
|
+
);
|
|
2405
|
+
}
|
|
2406
|
+
}
|
|
2407
|
+
const templatePath = resolve(root, "dist/client/index.html");
|
|
2408
|
+
const template = readFileSync(templatePath, "utf-8");
|
|
2409
|
+
const ssrPath = pathToFileURL(
|
|
2410
|
+
resolve(root, "dist/server/ssr.js")
|
|
2411
|
+
).href;
|
|
2412
|
+
const ssrModule = await import(
|
|
2413
|
+
/* @vite-ignore */
|
|
2414
|
+
ssrPath
|
|
2415
|
+
);
|
|
2416
|
+
app.get("*", async (c) => {
|
|
2417
|
+
const url = c.req.path + (c.req.url.includes("?") ? "?" + c.req.url.split("?")[1] : "");
|
|
2418
|
+
try {
|
|
2419
|
+
const locale = parseAcceptLanguage2(
|
|
2420
|
+
c.req.header("accept-language"),
|
|
2421
|
+
options.locales,
|
|
2422
|
+
options.defaultLocale
|
|
2423
|
+
);
|
|
2424
|
+
const {
|
|
2425
|
+
html: appHtml,
|
|
2426
|
+
head,
|
|
2427
|
+
css,
|
|
2428
|
+
serverData
|
|
2429
|
+
} = await ssrModule.render(url, locale);
|
|
2430
|
+
const serializedData = ssrModule.serializeServerData(serverData);
|
|
2431
|
+
const finalHtml = injectSSRContent2({
|
|
2432
|
+
template,
|
|
2433
|
+
locale,
|
|
2434
|
+
head,
|
|
2435
|
+
css,
|
|
2436
|
+
html: appHtml,
|
|
2437
|
+
serializedData
|
|
2438
|
+
});
|
|
2439
|
+
return c.html(finalHtml);
|
|
2440
|
+
} catch (e) {
|
|
2441
|
+
console.error("[SSR Preview Error]", e);
|
|
2442
|
+
return c.text("Internal Server Error", 500);
|
|
2443
|
+
}
|
|
2444
|
+
});
|
|
2445
|
+
const listener = getRequestListener(app.fetch);
|
|
2446
|
+
server.middlewares.use((req, res) => {
|
|
2447
|
+
listener(req, res);
|
|
2448
|
+
});
|
|
2449
|
+
};
|
|
2450
|
+
},
|
|
2451
|
+
// ─── Build ─────────────────────────────────────────────
|
|
2452
|
+
async closeBundle() {
|
|
2453
|
+
if (process.env.__FINESOFT_SUB_BUILD__) return;
|
|
2454
|
+
if (resolvedCommand !== "build") return;
|
|
2455
|
+
process.env.__FINESOFT_SUB_BUILD__ = "1";
|
|
2456
|
+
try {
|
|
2457
|
+
const vite = await import(
|
|
2458
|
+
/* @vite-ignore */
|
|
2459
|
+
"vite"
|
|
2460
|
+
);
|
|
2461
|
+
const fs = await import(
|
|
2462
|
+
/* @vite-ignore */
|
|
2463
|
+
"fs"
|
|
2464
|
+
);
|
|
2465
|
+
const path = await import(
|
|
2466
|
+
/* @vite-ignore */
|
|
2467
|
+
"path"
|
|
2468
|
+
);
|
|
2469
|
+
console.log("\n Building SSR bundle...\n");
|
|
2470
|
+
await vite.build({
|
|
2471
|
+
root,
|
|
2472
|
+
build: {
|
|
2473
|
+
ssr: ssrEntry,
|
|
2474
|
+
outDir: "dist/server"
|
|
2475
|
+
},
|
|
2476
|
+
resolve: resolvedResolve,
|
|
2477
|
+
css: resolvedCss
|
|
2478
|
+
});
|
|
2479
|
+
if (typeof options.setup === "string") {
|
|
2480
|
+
console.log(" Building setup module...\n");
|
|
2481
|
+
await vite.build({
|
|
2482
|
+
root,
|
|
2483
|
+
build: {
|
|
2484
|
+
ssr: options.setup,
|
|
2485
|
+
outDir: "dist/server",
|
|
2486
|
+
emptyOutDir: false,
|
|
2487
|
+
rollupOptions: {
|
|
2488
|
+
output: { entryFileNames: "setup.mjs" }
|
|
2489
|
+
}
|
|
2490
|
+
},
|
|
2491
|
+
resolve: resolvedResolve
|
|
2492
|
+
});
|
|
2493
|
+
}
|
|
2494
|
+
if (options.adapter) {
|
|
2495
|
+
const adapter = resolveAdapter(options.adapter);
|
|
2496
|
+
const locales = options.locales ?? ["zh", "en"];
|
|
2497
|
+
const defaultLocale = options.defaultLocale ?? locales[0] ?? "en";
|
|
2498
|
+
const templateHtml = fs.readFileSync(
|
|
2499
|
+
path.resolve(root, "dist/client/index.html"),
|
|
2500
|
+
"utf-8"
|
|
2501
|
+
);
|
|
2502
|
+
const ctx = {
|
|
2503
|
+
root,
|
|
2504
|
+
ssrEntry,
|
|
2505
|
+
setupPath: typeof options.setup === "string" ? options.setup : void 0,
|
|
2506
|
+
locales,
|
|
2507
|
+
defaultLocale,
|
|
2508
|
+
templateHtml,
|
|
2509
|
+
resolvedResolve,
|
|
2510
|
+
resolvedCss,
|
|
2511
|
+
vite,
|
|
2512
|
+
fs,
|
|
2513
|
+
path,
|
|
2514
|
+
generateSSREntry(opts) {
|
|
2515
|
+
return generateSSREntry(ctx, opts);
|
|
2516
|
+
},
|
|
2517
|
+
buildBundle(opts) {
|
|
2518
|
+
return buildBundle(ctx, opts);
|
|
2519
|
+
},
|
|
2520
|
+
copyStaticAssets(destDir, opts) {
|
|
2521
|
+
return copyStaticAssets(ctx, destDir, opts);
|
|
2522
|
+
}
|
|
2523
|
+
};
|
|
2524
|
+
console.log(` Running adapter: ${adapter.name}...
|
|
2525
|
+
`);
|
|
2526
|
+
await adapter.build(ctx);
|
|
2527
|
+
}
|
|
2528
|
+
} finally {
|
|
2529
|
+
delete process.env.__FINESOFT_SUB_BUILD__;
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2532
|
+
};
|
|
2533
|
+
}
|
|
1593
2534
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1594
2535
|
0 && (module.exports = {
|
|
1595
2536
|
ACTION_KINDS,
|
|
@@ -1611,7 +2552,9 @@ async function createServer(config = {}) {
|
|
|
1611
2552
|
PrefetchedIntents,
|
|
1612
2553
|
Router,
|
|
1613
2554
|
SSR_PLACEHOLDERS,
|
|
2555
|
+
autoAdapter,
|
|
1614
2556
|
buildUrl,
|
|
2557
|
+
cloudflareAdapter,
|
|
1615
2558
|
createPrefetchedIntentsFromDom,
|
|
1616
2559
|
createSSRApp,
|
|
1617
2560
|
createSSRRender,
|
|
@@ -1619,6 +2562,7 @@ async function createServer(config = {}) {
|
|
|
1619
2562
|
defineRoutes,
|
|
1620
2563
|
deserializeServerData,
|
|
1621
2564
|
detectRuntime,
|
|
2565
|
+
finesoftFrontViteConfig,
|
|
1622
2566
|
generateUuid,
|
|
1623
2567
|
getBaseUrl,
|
|
1624
2568
|
injectSSRContent,
|
|
@@ -1631,6 +2575,8 @@ async function createServer(config = {}) {
|
|
|
1631
2575
|
makeExternalUrlAction,
|
|
1632
2576
|
makeFlowAction,
|
|
1633
2577
|
mapEach,
|
|
2578
|
+
netlifyAdapter,
|
|
2579
|
+
nodeAdapter,
|
|
1634
2580
|
parseAcceptLanguage,
|
|
1635
2581
|
pipe,
|
|
1636
2582
|
pipeAsync,
|
|
@@ -1641,6 +2587,7 @@ async function createServer(config = {}) {
|
|
|
1641
2587
|
removeQueryParams,
|
|
1642
2588
|
removeScheme,
|
|
1643
2589
|
resetFilterCache,
|
|
2590
|
+
resolveAdapter,
|
|
1644
2591
|
resolveRoot,
|
|
1645
2592
|
serializeServerData,
|
|
1646
2593
|
shouldLog,
|
|
@@ -1648,6 +2595,8 @@ async function createServer(config = {}) {
|
|
|
1648
2595
|
stableStringify,
|
|
1649
2596
|
startBrowserApp,
|
|
1650
2597
|
startServer,
|
|
1651
|
-
|
|
2598
|
+
staticAdapter,
|
|
2599
|
+
tryScroll,
|
|
2600
|
+
vercelAdapter
|
|
1652
2601
|
});
|
|
1653
2602
|
//# sourceMappingURL=index.cjs.map
|