@pactor-app/module-pack 0.0.0-stage → 1.56.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 +103 -2
- package/dist/index.cjs +1568 -0
- package/dist/index.d.cts +550 -0
- package/dist/index.d.ts +550 -0
- package/dist/index.js +1507 -0
- package/package.json +55 -3
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1568 @@
|
|
|
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
|
+
CLIENT_EXTERNALS: () => CLIENT_EXTERNALS,
|
|
24
|
+
CLIENT_STYLES_ENTRY: () => CLIENT_STYLES_ENTRY,
|
|
25
|
+
CONFIG_DEFAULTS: () => CONFIG_DEFAULTS,
|
|
26
|
+
CONFIG_FILE: () => CONFIG_FILE,
|
|
27
|
+
ConfigError: () => ConfigError,
|
|
28
|
+
DEFAULT_TARGET: () => DEFAULT_TARGET,
|
|
29
|
+
INCLUDE_KEY: () => INCLUDE_KEY,
|
|
30
|
+
IncludeError: () => IncludeError,
|
|
31
|
+
MODULE_ID_PREFIX: () => MODULE_ID_PREFIX,
|
|
32
|
+
ModuleBuildError: () => ModuleBuildError,
|
|
33
|
+
ProfileError: () => ProfileError,
|
|
34
|
+
SERVER_BUNDLE_FILE: () => SERVER_BUNDLE_FILE,
|
|
35
|
+
SERVER_ENTRY: () => SERVER_ENTRY,
|
|
36
|
+
SERVER_EXTERNALS: () => SERVER_EXTERNALS,
|
|
37
|
+
ServerBundleError: () => ServerBundleError,
|
|
38
|
+
buildModule: () => buildModule,
|
|
39
|
+
bumpPackageVersion: () => bumpPackageVersion,
|
|
40
|
+
bumpVersion: () => bumpVersion,
|
|
41
|
+
bundleClient: () => bundleClient,
|
|
42
|
+
bundleServer: () => bundleServer,
|
|
43
|
+
collectModuleSource: () => collectModuleSource,
|
|
44
|
+
compileTailwind: () => compileTailwind,
|
|
45
|
+
deriveApiPrefix: () => deriveApiPrefix,
|
|
46
|
+
deriveModuleId: () => deriveModuleId,
|
|
47
|
+
discoverActions: () => discoverActions,
|
|
48
|
+
discoverComponents: () => discoverComponents,
|
|
49
|
+
emitDsl: () => emitDsl,
|
|
50
|
+
emitModule: () => emitModule,
|
|
51
|
+
expandIncludes: () => expandIncludes,
|
|
52
|
+
getProfile: () => getProfile,
|
|
53
|
+
initModule: () => initModule,
|
|
54
|
+
innospotsWebShellV1: () => innospotsWebShellV1,
|
|
55
|
+
innospotsWebShellV2: () => innospotsWebShellV2,
|
|
56
|
+
innospotsWebShellV3: () => innospotsWebShellV3,
|
|
57
|
+
listProfiles: () => listProfiles,
|
|
58
|
+
loadModuleConfig: () => loadModuleConfig,
|
|
59
|
+
loadYamlExpanded: () => loadYamlExpanded,
|
|
60
|
+
matchPathPattern: () => matchPathPattern,
|
|
61
|
+
parseJsonc: () => parseJsonc,
|
|
62
|
+
parseYamlFile: () => parseYamlFile,
|
|
63
|
+
readProjectVersion: () => readProjectVersion,
|
|
64
|
+
renderClientEntry: () => renderClientEntry,
|
|
65
|
+
renderModuleStyles: () => renderModuleStyles,
|
|
66
|
+
renderServerEntry: () => renderServerEntry,
|
|
67
|
+
resolvePactorVersionRange: () => resolvePactorVersionRange,
|
|
68
|
+
rewriteDslUrls: () => rewriteDslUrls,
|
|
69
|
+
rewriteNavigationTo: () => rewriteNavigationTo,
|
|
70
|
+
transformSitemap: () => transformSitemap,
|
|
71
|
+
tsconfigAliases: () => tsconfigAliases,
|
|
72
|
+
validateModule: () => validateModule,
|
|
73
|
+
writeManifest: () => writeManifest
|
|
74
|
+
});
|
|
75
|
+
module.exports = __toCommonJS(index_exports);
|
|
76
|
+
|
|
77
|
+
// src/build.ts
|
|
78
|
+
var import_node_fs10 = require("fs");
|
|
79
|
+
var import_node_path10 = require("path");
|
|
80
|
+
|
|
81
|
+
// src/bundle-client.ts
|
|
82
|
+
var import_node_fs = require("fs");
|
|
83
|
+
var import_node_path = require("path");
|
|
84
|
+
var import_esbuild = require("esbuild");
|
|
85
|
+
var CLIENT_EXTERNALS = [
|
|
86
|
+
"react",
|
|
87
|
+
"react-dom",
|
|
88
|
+
"react-dom/client",
|
|
89
|
+
"next",
|
|
90
|
+
"next/*",
|
|
91
|
+
"pactor-app",
|
|
92
|
+
"pactor-app/*",
|
|
93
|
+
"@pactor-app/*"
|
|
94
|
+
];
|
|
95
|
+
function bundleClient(options) {
|
|
96
|
+
const entry = (0, import_node_path.join)(options.projectDir, options.clientEntry);
|
|
97
|
+
if (!(0, import_node_fs.existsSync)(entry)) {
|
|
98
|
+
return {
|
|
99
|
+
bundled: false,
|
|
100
|
+
css: false,
|
|
101
|
+
message: `client \u5165\u53E3\u4E0D\u5B58\u5728: ${options.clientEntry}\uFF08\u6309\u7EAF DSL \u6A21\u5757\u5904\u7406\uFF0C\u8DF3\u8FC7 client \u6253\u5305\uFF09`
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
(0, import_node_fs.mkdirSync)(options.outDir, { recursive: true });
|
|
105
|
+
(0, import_esbuild.buildSync)({
|
|
106
|
+
entryPoints: [entry],
|
|
107
|
+
bundle: true,
|
|
108
|
+
format: "esm",
|
|
109
|
+
platform: "browser",
|
|
110
|
+
outdir: options.outDir,
|
|
111
|
+
entryNames: "index",
|
|
112
|
+
sourcemap: true,
|
|
113
|
+
alias: tsconfigAliases(options.projectDir),
|
|
114
|
+
external: [...CLIENT_EXTERNALS],
|
|
115
|
+
logLevel: "silent"
|
|
116
|
+
});
|
|
117
|
+
return {
|
|
118
|
+
bundled: true,
|
|
119
|
+
css: (0, import_node_fs.existsSync)((0, import_node_path.join)(options.outDir, "index.css"))
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function tsconfigAliases(projectDir) {
|
|
123
|
+
const file = (0, import_node_path.join)(projectDir, "tsconfig.json");
|
|
124
|
+
if (!(0, import_node_fs.existsSync)(file)) return {};
|
|
125
|
+
const compilerOptions = readTsconfig(file);
|
|
126
|
+
const paths = compilerOptions.paths ?? {};
|
|
127
|
+
const baseUrl = compilerOptions.baseUrl ?? ".";
|
|
128
|
+
const alias = {};
|
|
129
|
+
for (const [key, targets] of Object.entries(paths)) {
|
|
130
|
+
const target = targets[0];
|
|
131
|
+
if (typeof target !== "string") continue;
|
|
132
|
+
const name = key.endsWith("/*") ? key.slice(0, -2) : key;
|
|
133
|
+
const rel = target.endsWith("/*") ? target.slice(0, -2) : target;
|
|
134
|
+
alias[name] = (0, import_node_path.resolve)((0, import_node_path.dirname)(file), baseUrl, rel);
|
|
135
|
+
}
|
|
136
|
+
return alias;
|
|
137
|
+
}
|
|
138
|
+
function readTsconfig(file, seen = /* @__PURE__ */ new Set()) {
|
|
139
|
+
if (seen.has(file) || !(0, import_node_fs.existsSync)(file)) return {};
|
|
140
|
+
seen.add(file);
|
|
141
|
+
let raw;
|
|
142
|
+
try {
|
|
143
|
+
raw = parseJsonc((0, import_node_fs.readFileSync)(file, "utf8"));
|
|
144
|
+
} catch {
|
|
145
|
+
return {};
|
|
146
|
+
}
|
|
147
|
+
let base2 = {};
|
|
148
|
+
if (typeof raw.extends === "string" && raw.extends.startsWith(".")) {
|
|
149
|
+
base2 = readTsconfig((0, import_node_path.resolve)((0, import_node_path.dirname)(file), raw.extends), seen);
|
|
150
|
+
}
|
|
151
|
+
const own = raw.compilerOptions ?? {};
|
|
152
|
+
return {
|
|
153
|
+
baseUrl: own.baseUrl ?? base2.baseUrl,
|
|
154
|
+
paths: { ...base2.paths ?? {}, ...own.paths ?? {} }
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
function parseJsonc(text) {
|
|
158
|
+
let out = "";
|
|
159
|
+
let inString = false;
|
|
160
|
+
let i = 0;
|
|
161
|
+
while (i < text.length) {
|
|
162
|
+
const c = text[i];
|
|
163
|
+
if (inString) {
|
|
164
|
+
out += c;
|
|
165
|
+
if (c === "\\") {
|
|
166
|
+
out += text[i + 1] ?? "";
|
|
167
|
+
i += 2;
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
if (c === '"') inString = false;
|
|
171
|
+
i += 1;
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
if (c === '"') {
|
|
175
|
+
inString = true;
|
|
176
|
+
out += c;
|
|
177
|
+
i += 1;
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
if (c === "/" && text[i + 1] === "/") {
|
|
181
|
+
while (i < text.length && text[i] !== "\n") i += 1;
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
if (c === "/" && text[i + 1] === "*") {
|
|
185
|
+
i += 2;
|
|
186
|
+
while (i < text.length && !(text[i] === "*" && text[i + 1] === "/")) i += 1;
|
|
187
|
+
i += 2;
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
out += c;
|
|
191
|
+
i += 1;
|
|
192
|
+
}
|
|
193
|
+
return JSON.parse(out.replace(/,(\s*[}\]])/g, "$1"));
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// src/bundle-server.ts
|
|
197
|
+
var import_node_fs2 = require("fs");
|
|
198
|
+
var import_node_path2 = require("path");
|
|
199
|
+
var import_esbuild2 = require("esbuild");
|
|
200
|
+
var SERVER_EXTERNALS = [
|
|
201
|
+
"react",
|
|
202
|
+
"react-dom",
|
|
203
|
+
"react-dom/*",
|
|
204
|
+
"next",
|
|
205
|
+
"next/*",
|
|
206
|
+
"pactor-app",
|
|
207
|
+
"pactor-app/*",
|
|
208
|
+
"@pactor-app/*"
|
|
209
|
+
];
|
|
210
|
+
var SERVER_BUNDLE_FILE = "index.mjs";
|
|
211
|
+
var ServerBundleError = class extends Error {
|
|
212
|
+
};
|
|
213
|
+
function bundleServer(options) {
|
|
214
|
+
const projectRoot = (0, import_node_path2.resolve)(options.projectDir);
|
|
215
|
+
const entry = (0, import_node_path2.resolve)(projectRoot, options.serverEntry);
|
|
216
|
+
if (!entry.startsWith(`${projectRoot}${import_node_path2.sep}`)) {
|
|
217
|
+
throw new ServerBundleError(
|
|
218
|
+
`server \u5165\u53E3\u5FC5\u987B\u4F4D\u4E8E\u5DE5\u7A0B\u6839\u5185: ${options.serverEntry}`
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
if (!(0, import_node_fs2.existsSync)(entry)) {
|
|
222
|
+
throw new ServerBundleError(`server \u5165\u53E3\u4E0D\u5B58\u5728: ${options.serverEntry}`);
|
|
223
|
+
}
|
|
224
|
+
(0, import_node_fs2.mkdirSync)(options.outDir, { recursive: true });
|
|
225
|
+
(0, import_esbuild2.buildSync)({
|
|
226
|
+
entryPoints: [entry],
|
|
227
|
+
bundle: true,
|
|
228
|
+
format: "esm",
|
|
229
|
+
platform: "node",
|
|
230
|
+
target: "node20",
|
|
231
|
+
outdir: options.outDir,
|
|
232
|
+
entryNames: "index",
|
|
233
|
+
outExtension: { ".js": ".mjs" },
|
|
234
|
+
sourcemap: true,
|
|
235
|
+
alias: tsconfigAliases(projectRoot),
|
|
236
|
+
external: [...SERVER_EXTERNALS],
|
|
237
|
+
logLevel: "silent"
|
|
238
|
+
});
|
|
239
|
+
if (!(0, import_node_fs2.existsSync)((0, import_node_path2.join)(options.outDir, SERVER_BUNDLE_FILE))) {
|
|
240
|
+
throw new ServerBundleError(
|
|
241
|
+
`server \u6253\u5305\u672A\u4EA7\u51FA ${SERVER_BUNDLE_FILE}\uFF08\u8BF7\u68C0\u67E5 serverEntry \u4E0E esbuild \u914D\u7F6E\uFF09`
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
return { bundled: true, entry: SERVER_BUNDLE_FILE };
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// src/collect.ts
|
|
248
|
+
var import_node_fs3 = require("fs");
|
|
249
|
+
var import_node_path3 = require("path");
|
|
250
|
+
function collectModuleSource(yamlRoot) {
|
|
251
|
+
const pages = /* @__PURE__ */ new Map();
|
|
252
|
+
const layouts = [];
|
|
253
|
+
const fragments = [];
|
|
254
|
+
const warnings = [];
|
|
255
|
+
const walk = (dir) => {
|
|
256
|
+
for (const entry of (0, import_node_fs3.readdirSync)(dir, { withFileTypes: true })) {
|
|
257
|
+
const full = (0, import_node_path3.join)(dir, entry.name);
|
|
258
|
+
if (entry.isDirectory()) {
|
|
259
|
+
walk(full);
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
if (!entry.name.endsWith(".yaml") || entry.name === "sitemap.yaml") {
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
const rel = (0, import_node_path3.relative)(yamlRoot, full);
|
|
266
|
+
if (entry.name.endsWith(".layout.yaml")) {
|
|
267
|
+
layouts.push(rel);
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
if (entry.name.endsWith(".fragment.yaml")) {
|
|
271
|
+
fragments.push(rel);
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
let id = entry.name.slice(0, -".yaml".length);
|
|
275
|
+
if (id.endsWith(".page")) {
|
|
276
|
+
id = id.slice(0, -".page".length);
|
|
277
|
+
}
|
|
278
|
+
if (pages.has(id)) {
|
|
279
|
+
warnings.push(`\u9875\u9762 id \u91CD\u590D: ${id}\uFF08${rel} \u8986\u76D6 ${pages.get(id)}\uFF09`);
|
|
280
|
+
}
|
|
281
|
+
pages.set(id, rel);
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
walk(yamlRoot);
|
|
285
|
+
layouts.sort();
|
|
286
|
+
fragments.sort();
|
|
287
|
+
return { yamlRoot, pages, layouts, fragments, warnings };
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// src/compile-styles.ts
|
|
291
|
+
var import_node_child_process = require("child_process");
|
|
292
|
+
var import_node_fs4 = require("fs");
|
|
293
|
+
var import_node_os = require("os");
|
|
294
|
+
var import_node_path4 = require("path");
|
|
295
|
+
function compileTailwind(options) {
|
|
296
|
+
const warnings = [];
|
|
297
|
+
if (!options.tailwind.enabled) {
|
|
298
|
+
return { compiled: false, warnings };
|
|
299
|
+
}
|
|
300
|
+
const work = (0, import_node_fs4.mkdtempSync)((0, import_node_path4.join)((0, import_node_os.tmpdir)(), "pactor-tailwind-"));
|
|
301
|
+
try {
|
|
302
|
+
let input;
|
|
303
|
+
if (options.tailwind.input !== void 0) {
|
|
304
|
+
input = (0, import_node_path4.join)(options.projectDir, options.tailwind.input);
|
|
305
|
+
if (!(0, import_node_fs4.existsSync)(input)) {
|
|
306
|
+
warnings.push(`tailwind.input \u4E0D\u5B58\u5728: ${options.tailwind.input}\uFF0C\u8DF3\u8FC7\u9884\u7F16\u8BD1`);
|
|
307
|
+
return { compiled: false, warnings };
|
|
308
|
+
}
|
|
309
|
+
} else {
|
|
310
|
+
const scan = (options.tailwind.scan ?? options.scanDirs).map(
|
|
311
|
+
(dir) => `@source "${dir.replace(/\\/g, "/")}";`
|
|
312
|
+
);
|
|
313
|
+
input = (0, import_node_path4.join)(work, "input.css");
|
|
314
|
+
(0, import_node_fs4.writeFileSync)(input, `@import "tailwindcss";
|
|
315
|
+
${scan.join("\n")}
|
|
316
|
+
`, "utf8");
|
|
317
|
+
}
|
|
318
|
+
const out = (0, import_node_path4.join)(work, "tailwind.css");
|
|
319
|
+
(0, import_node_child_process.execFileSync)(
|
|
320
|
+
"npx",
|
|
321
|
+
["--no-install", "tailwindcss", "--input", input, "--output", out],
|
|
322
|
+
{ cwd: options.projectDir, stdio: "pipe" }
|
|
323
|
+
);
|
|
324
|
+
if ((0, import_node_fs4.existsSync)(out)) {
|
|
325
|
+
const css = (0, import_node_fs4.readFileSync)(out, "utf8");
|
|
326
|
+
if (css.trim().length > 0) {
|
|
327
|
+
(0, import_node_fs4.mkdirSync)((0, import_node_path4.dirname)(options.cssFile), { recursive: true });
|
|
328
|
+
(0, import_node_fs4.appendFileSync)(
|
|
329
|
+
options.cssFile,
|
|
330
|
+
`
|
|
331
|
+
/* tailwind utilities\uFF08pactor module build \u9884\u7F16\u8BD1\uFF09 */
|
|
332
|
+
${css}`,
|
|
333
|
+
"utf8"
|
|
334
|
+
);
|
|
335
|
+
return { compiled: true, warnings };
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
warnings.push("tailwind \u9884\u7F16\u8BD1\u4EA7\u7269\u4E3A\u7A7A\uFF0C\u5DF2\u8DF3\u8FC7");
|
|
339
|
+
return { compiled: false, warnings };
|
|
340
|
+
} catch (error) {
|
|
341
|
+
const firstLine = error.message.split("\n")[0] ?? "\u672A\u77E5\u9519\u8BEF";
|
|
342
|
+
warnings.push(`tailwind \u4E0D\u53EF\u7528\u6216\u7F16\u8BD1\u5931\u8D25\uFF0C\u5DF2\u964D\u7EA7\u8DF3\u8FC7\u9884\u7F16\u8BD1\uFF08${firstLine}\uFF09`);
|
|
343
|
+
return { compiled: false, warnings };
|
|
344
|
+
} finally {
|
|
345
|
+
(0, import_node_fs4.rmSync)(work, { recursive: true, force: true });
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// src/config.ts
|
|
350
|
+
var import_node_fs5 = require("fs");
|
|
351
|
+
var import_node_path5 = require("path");
|
|
352
|
+
|
|
353
|
+
// src/profiles/innospots-web-shell.ts
|
|
354
|
+
var base = {
|
|
355
|
+
name: "innospots-web-shell",
|
|
356
|
+
inlineStringLayouts: true,
|
|
357
|
+
stripMenuPaths: true,
|
|
358
|
+
rewriteNavigation: { basePath: true, excludeApiUrls: true },
|
|
359
|
+
rewriteAssetUrls: (id, version) => `/modules/${id}/${version}/`,
|
|
360
|
+
forbidRootBasePath: true,
|
|
361
|
+
moduleServerApi: false
|
|
362
|
+
};
|
|
363
|
+
var innospotsWebShellV1 = {
|
|
364
|
+
...base,
|
|
365
|
+
version: 1,
|
|
366
|
+
forceInlinePages: true
|
|
367
|
+
};
|
|
368
|
+
var innospotsWebShellV2 = {
|
|
369
|
+
...base,
|
|
370
|
+
version: 2,
|
|
371
|
+
forceInlinePages: false
|
|
372
|
+
};
|
|
373
|
+
var innospotsWebShellV3 = {
|
|
374
|
+
...base,
|
|
375
|
+
version: 3,
|
|
376
|
+
forceInlinePages: false,
|
|
377
|
+
moduleServerApi: true
|
|
378
|
+
};
|
|
379
|
+
|
|
380
|
+
// src/profiles/index.ts
|
|
381
|
+
var ProfileError = class extends Error {
|
|
382
|
+
};
|
|
383
|
+
var registry = /* @__PURE__ */ new Map([
|
|
384
|
+
[`${innospotsWebShellV1.name}@${innospotsWebShellV1.version}`, innospotsWebShellV1],
|
|
385
|
+
[`${innospotsWebShellV2.name}@${innospotsWebShellV2.version}`, innospotsWebShellV2],
|
|
386
|
+
[`${innospotsWebShellV3.name}@${innospotsWebShellV3.version}`, innospotsWebShellV3]
|
|
387
|
+
]);
|
|
388
|
+
var DEFAULT_TARGET = `${innospotsWebShellV3.name}@${innospotsWebShellV3.version}`;
|
|
389
|
+
function listProfiles() {
|
|
390
|
+
return [...registry.keys()];
|
|
391
|
+
}
|
|
392
|
+
function getProfile(id) {
|
|
393
|
+
const profile = registry.get(id);
|
|
394
|
+
if (!profile) {
|
|
395
|
+
throw new ProfileError(`\u672A\u77E5 target profile: ${id}\uFF08\u53EF\u7528: ${listProfiles().join(", ")}\uFF09`);
|
|
396
|
+
}
|
|
397
|
+
return profile;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// src/config.ts
|
|
401
|
+
var ConfigError = class extends Error {
|
|
402
|
+
};
|
|
403
|
+
var CONFIG_FILE = "pactor.module.json";
|
|
404
|
+
var CONFIG_DEFAULTS = {
|
|
405
|
+
yamlRoot: "src/server/yaml",
|
|
406
|
+
clientEntry: "module/client.ts",
|
|
407
|
+
publicDir: "public",
|
|
408
|
+
target: DEFAULT_TARGET,
|
|
409
|
+
outDir: "dist-module"
|
|
410
|
+
};
|
|
411
|
+
function loadModuleConfig(projectDir, configPath) {
|
|
412
|
+
const file = configPath ? (0, import_node_path5.resolve)(projectDir, configPath) : (0, import_node_path5.join)(projectDir, CONFIG_FILE);
|
|
413
|
+
if (!(0, import_node_fs5.existsSync)(file)) {
|
|
414
|
+
throw new ConfigError(`\u7F3A\u5C11\u914D\u7F6E\u6587\u4EF6: ${file}\uFF08\u53EF\u5148\u6267\u884C pactor module init \u751F\u6210\uFF09`);
|
|
415
|
+
}
|
|
416
|
+
let raw;
|
|
417
|
+
try {
|
|
418
|
+
raw = JSON.parse((0, import_node_fs5.readFileSync)(file, "utf8"));
|
|
419
|
+
} catch (error) {
|
|
420
|
+
throw new ConfigError(`\u914D\u7F6E\u89E3\u6790\u5931\u8D25: ${file}: ${error.message}`);
|
|
421
|
+
}
|
|
422
|
+
if (!isRecord(raw)) {
|
|
423
|
+
throw new ConfigError(`${file}: \u914D\u7F6E\u5FC5\u987B\u662F JSON \u5BF9\u8C61`);
|
|
424
|
+
}
|
|
425
|
+
const id = readString(raw, "id", file);
|
|
426
|
+
if (!id) {
|
|
427
|
+
throw new ConfigError(`${file}: \u7F3A\u5C11\u5FC5\u586B\u5B57\u6BB5 id\uFF08\u6A21\u5757 id\uFF0C\u8FDB\u5165 globalPageId \u524D\u7F00\uFF09`);
|
|
428
|
+
}
|
|
429
|
+
const name = readString(raw, "name", file) ?? id;
|
|
430
|
+
let basePath = readString(raw, "basePath", file) ?? `/${id}`;
|
|
431
|
+
if (!basePath.startsWith("/")) basePath = `/${basePath}`;
|
|
432
|
+
if (basePath.length > 1 && basePath.endsWith("/")) basePath = basePath.slice(0, -1);
|
|
433
|
+
const actions = raw.actions === void 0 ? [] : readStringArray(raw.actions, "actions", file);
|
|
434
|
+
if (raw.demo !== void 0) {
|
|
435
|
+
throw new ConfigError(
|
|
436
|
+
`${file}: demo.public \u5DF2\u79FB\u9664\uFF0C\u8BF7\u6539\u7528 "access": { "default": "public" }\uFF08\u7F3A\u7701\u586B\u5145\u8BED\u4E49\uFF0C\u4E0D\u8986\u76D6\u663E\u5F0F permission\uFF09`
|
|
437
|
+
);
|
|
438
|
+
}
|
|
439
|
+
const access = isRecord(raw.access) ? raw.access : {};
|
|
440
|
+
const accessDefault = readString(access, "default", file, "access") ?? "authenticated";
|
|
441
|
+
if (accessDefault !== "public" && accessDefault !== "authenticated") {
|
|
442
|
+
throw new ConfigError(`${file}: access.default \u53EA\u652F\u6301 "public" | "authenticated"`);
|
|
443
|
+
}
|
|
444
|
+
const tailwind = isRecord(raw.tailwind) ? raw.tailwind : {};
|
|
445
|
+
const rewrite = isRecord(raw.rewrite) ? raw.rewrite : {};
|
|
446
|
+
const serverEntry = readString(raw, "serverEntry", file);
|
|
447
|
+
const apiPrefixes = raw.apiPrefixes === void 0 ? void 0 : readStringArray(raw.apiPrefixes, "apiPrefixes", file);
|
|
448
|
+
validateServerConfig({ id, serverEntry, apiPrefixes, file });
|
|
449
|
+
return {
|
|
450
|
+
id,
|
|
451
|
+
name,
|
|
452
|
+
basePath,
|
|
453
|
+
yamlRoot: readString(raw, "yamlRoot", file) ?? CONFIG_DEFAULTS.yamlRoot,
|
|
454
|
+
clientEntry: readString(raw, "clientEntry", file) ?? CONFIG_DEFAULTS.clientEntry,
|
|
455
|
+
...serverEntry !== void 0 ? { serverEntry, apiPrefixes } : {},
|
|
456
|
+
actions,
|
|
457
|
+
publicDir: readString(raw, "publicDir", file) ?? CONFIG_DEFAULTS.publicDir,
|
|
458
|
+
target: readString(raw, "target", file) ?? CONFIG_DEFAULTS.target,
|
|
459
|
+
access: { default: accessDefault },
|
|
460
|
+
tailwind: {
|
|
461
|
+
enabled: readBoolean(tailwind, "enabled", file, "tailwind") ?? false,
|
|
462
|
+
input: readString(tailwind, "input", file, "tailwind"),
|
|
463
|
+
scan: tailwind.scan === void 0 ? void 0 : readStringArray(tailwind.scan, "tailwind.scan", file)
|
|
464
|
+
},
|
|
465
|
+
rewrite: {
|
|
466
|
+
absoluteApiToRelative: readBoolean(rewrite, "absoluteApiToRelative", file, "rewrite") ?? true
|
|
467
|
+
},
|
|
468
|
+
outDir: readString(raw, "outDir", file) ?? CONFIG_DEFAULTS.outDir
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
function isRecord(value) {
|
|
472
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
473
|
+
}
|
|
474
|
+
function readString(record, key, file, parent) {
|
|
475
|
+
const value = record[key];
|
|
476
|
+
if (value === void 0) return void 0;
|
|
477
|
+
const label = parent ? `${parent}.${key}` : key;
|
|
478
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
479
|
+
throw new ConfigError(`${file}: ${label} \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32`);
|
|
480
|
+
}
|
|
481
|
+
return value;
|
|
482
|
+
}
|
|
483
|
+
function readBoolean(record, key, file, parent) {
|
|
484
|
+
const value = record[key];
|
|
485
|
+
if (value === void 0) return void 0;
|
|
486
|
+
if (typeof value !== "boolean") {
|
|
487
|
+
throw new ConfigError(`${file}: ${parent}.${key} \u5FC5\u987B\u662F\u5E03\u5C14\u503C`);
|
|
488
|
+
}
|
|
489
|
+
return value;
|
|
490
|
+
}
|
|
491
|
+
function readStringArray(value, label, file) {
|
|
492
|
+
if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) {
|
|
493
|
+
throw new ConfigError(`${file}: ${label} \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6570\u7EC4`);
|
|
494
|
+
}
|
|
495
|
+
return value;
|
|
496
|
+
}
|
|
497
|
+
var URL_SAFE_MODULE_ID_RE = /^[A-Za-z0-9._~-]+$/;
|
|
498
|
+
var API_PREFIX_RE = /^\/api\/[A-Za-z0-9._~-]+(?:\/[A-Za-z0-9._~-]+)*$/;
|
|
499
|
+
var RESERVED_API_PREFIXES = ["/api/modules", "/api/runtime"];
|
|
500
|
+
function validateServerConfig(input) {
|
|
501
|
+
const { id, serverEntry, apiPrefixes, file } = input;
|
|
502
|
+
if (serverEntry === void 0 && apiPrefixes === void 0) return;
|
|
503
|
+
if (serverEntry === void 0 || apiPrefixes === void 0) {
|
|
504
|
+
throw new ConfigError(`${file}: serverEntry \u4E0E apiPrefixes \u5FC5\u987B\u540C\u65F6\u914D\u7F6E\uFF08\u7F3A\u4E00\u4E0D\u53EF\uFF09`);
|
|
505
|
+
}
|
|
506
|
+
if (apiPrefixes.length === 0) {
|
|
507
|
+
throw new ConfigError(`${file}: \u914D\u7F6E serverEntry \u65F6 apiPrefixes \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4`);
|
|
508
|
+
}
|
|
509
|
+
if (!URL_SAFE_MODULE_ID_RE.test(id)) {
|
|
510
|
+
throw new ConfigError(
|
|
511
|
+
`${file}: \u542F\u7528 serverEntry \u65F6 id \u53EA\u80FD\u5305\u542B\u5B57\u6BCD\u3001\u6570\u5B57\u3001. _ ~ -\uFF08\u5F53\u524D: ${JSON.stringify(id)}\uFF09`
|
|
512
|
+
);
|
|
513
|
+
}
|
|
514
|
+
for (const prefix of apiPrefixes) {
|
|
515
|
+
if (!API_PREFIX_RE.test(prefix)) {
|
|
516
|
+
throw new ConfigError(
|
|
517
|
+
`${file}: apiPrefixes \u542B\u975E\u6CD5\u524D\u7F00 ${JSON.stringify(prefix)}\uFF08\u8981\u6C42\u5F62\u5982 /api/risk-analysis\uFF0C\u4E0D\u80FD\u542B query / hash / \u5C3E\u659C\u6760 / \u901A\u914D / :param\uFF09`
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
const reserved = RESERVED_API_PREFIXES.find(
|
|
521
|
+
(item) => prefix === item || prefix.startsWith(`${item}/`)
|
|
522
|
+
);
|
|
523
|
+
if (reserved) {
|
|
524
|
+
throw new ConfigError(
|
|
525
|
+
`${file}: apiPrefixes \u4E0D\u80FD\u4F7F\u7528\u4FDD\u7559\u524D\u7F00 ${reserved}\uFF08Shell \u81EA\u5E26\u8DEF\u7531\uFF09: ${prefix}`
|
|
526
|
+
);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
for (let i = 0; i < apiPrefixes.length; i += 1) {
|
|
530
|
+
for (let j = i + 1; j < apiPrefixes.length; j += 1) {
|
|
531
|
+
const a = apiPrefixes[i];
|
|
532
|
+
const b = apiPrefixes[j];
|
|
533
|
+
if (a === b) {
|
|
534
|
+
throw new ConfigError(`${file}: apiPrefixes \u5B58\u5728\u91CD\u590D\u524D\u7F00: ${a}`);
|
|
535
|
+
}
|
|
536
|
+
if (a.startsWith(`${b}/`) || b.startsWith(`${a}/`)) {
|
|
537
|
+
throw new ConfigError(
|
|
538
|
+
`${file}: apiPrefixes \u524D\u7F00\u4E92\u76F8\u5305\u542B\uFF08\u540C\u4E00\u6A21\u5757\u5185\u65E0\u6CD5\u786E\u5B9A\u5F52\u5C5E\uFF09: ${a} / ${b}`
|
|
539
|
+
);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
// src/emit-manifest.ts
|
|
546
|
+
var import_node_crypto = require("crypto");
|
|
547
|
+
var import_node_fs6 = require("fs");
|
|
548
|
+
var import_node_module = require("module");
|
|
549
|
+
var import_node_path6 = require("path");
|
|
550
|
+
var import_yaml = require("yaml");
|
|
551
|
+
function emitModule(input) {
|
|
552
|
+
const dslResult = emitDsl(input);
|
|
553
|
+
const manifest = writeManifest(input);
|
|
554
|
+
return { ...dslResult, manifest };
|
|
555
|
+
}
|
|
556
|
+
function emitDsl(input) {
|
|
557
|
+
const { config, projectDir, outDir, site, pages } = input;
|
|
558
|
+
const dslDir = (0, import_node_path6.join)(outDir, "dsl");
|
|
559
|
+
(0, import_node_fs6.mkdirSync)(dslDir, { recursive: true });
|
|
560
|
+
(0, import_node_fs6.writeFileSync)((0, import_node_path6.join)(dslDir, "sitemap.yaml"), (0, import_yaml.stringify)(site, { lineWidth: 0 }), "utf8");
|
|
561
|
+
for (const [id, dsl] of pages) {
|
|
562
|
+
(0, import_node_fs6.writeFileSync)((0, import_node_path6.join)(dslDir, `${id}.yaml`), (0, import_yaml.stringify)(dsl, { lineWidth: 0 }), "utf8");
|
|
563
|
+
}
|
|
564
|
+
const publicDir = (0, import_node_path6.join)(projectDir, config.publicDir);
|
|
565
|
+
const assetsDir = (0, import_node_path6.join)(outDir, "assets");
|
|
566
|
+
if ((0, import_node_fs6.existsSync)(publicDir)) {
|
|
567
|
+
(0, import_node_fs6.cpSync)(publicDir, assetsDir, { recursive: true });
|
|
568
|
+
} else {
|
|
569
|
+
(0, import_node_fs6.mkdirSync)(assetsDir, { recursive: true });
|
|
570
|
+
}
|
|
571
|
+
const assets = hashAssets(assetsDir, assetsDir);
|
|
572
|
+
(0, import_node_fs6.writeFileSync)(
|
|
573
|
+
(0, import_node_path6.join)(outDir, "module-assets.json"),
|
|
574
|
+
`${JSON.stringify({ module: config.id, assets }, null, 2)}
|
|
575
|
+
`,
|
|
576
|
+
"utf8"
|
|
577
|
+
);
|
|
578
|
+
return { assetCount: assets.length };
|
|
579
|
+
}
|
|
580
|
+
function writeManifest(input) {
|
|
581
|
+
const { config, projectDir, outDir } = input;
|
|
582
|
+
const version = readProjectVersion(projectDir);
|
|
583
|
+
const manifest = {
|
|
584
|
+
schemaVersion: "1",
|
|
585
|
+
id: config.id,
|
|
586
|
+
name: config.name,
|
|
587
|
+
version,
|
|
588
|
+
pactorVersionRange: resolvePactorVersionRange(projectDir, input.warnings),
|
|
589
|
+
basePath: config.basePath,
|
|
590
|
+
sitemap: "dsl/sitemap.yaml",
|
|
591
|
+
dslRoot: "dsl",
|
|
592
|
+
assetsRoot: "assets",
|
|
593
|
+
...input.clientEntry ? { clientEntry: input.clientEntry } : {},
|
|
594
|
+
...input.styles ? { styles: input.styles } : {},
|
|
595
|
+
...input.serverEntry ? { serverEntry: input.serverEntry } : {},
|
|
596
|
+
...input.apiPrefixes && input.apiPrefixes.length > 0 ? { apiPrefixes: input.apiPrefixes } : {}
|
|
597
|
+
};
|
|
598
|
+
(0, import_node_fs6.writeFileSync)(
|
|
599
|
+
(0, import_node_path6.join)(outDir, "manifest.json"),
|
|
600
|
+
`${JSON.stringify(manifest, null, 2)}
|
|
601
|
+
`,
|
|
602
|
+
"utf8"
|
|
603
|
+
);
|
|
604
|
+
return manifest;
|
|
605
|
+
}
|
|
606
|
+
function readProjectVersion(projectDir) {
|
|
607
|
+
const pkgFile = (0, import_node_path6.join)(projectDir, "package.json");
|
|
608
|
+
if (!(0, import_node_fs6.existsSync)(pkgFile)) return "0.0.0";
|
|
609
|
+
try {
|
|
610
|
+
const pkg = JSON.parse((0, import_node_fs6.readFileSync)(pkgFile, "utf8"));
|
|
611
|
+
return typeof pkg.version === "string" && pkg.version.length > 0 ? pkg.version : "0.0.0";
|
|
612
|
+
} catch {
|
|
613
|
+
return "0.0.0";
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
function resolvePactorVersionRange(projectDir, warnings) {
|
|
617
|
+
try {
|
|
618
|
+
const require2 = (0, import_node_module.createRequire)((0, import_node_path6.join)(projectDir, "package.json"));
|
|
619
|
+
for (const name of ["pactor-app/package.json", "@pactor-app/app/package.json"]) {
|
|
620
|
+
try {
|
|
621
|
+
const pkgFile = require2.resolve(name);
|
|
622
|
+
const pkg2 = JSON.parse((0, import_node_fs6.readFileSync)(pkgFile, "utf8"));
|
|
623
|
+
if (typeof pkg2.version === "string" && pkg2.version.length > 0) {
|
|
624
|
+
return `^${pkg2.version}`;
|
|
625
|
+
}
|
|
626
|
+
} catch {
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
const pkg = JSON.parse((0, import_node_fs6.readFileSync)((0, import_node_path6.join)(projectDir, "package.json"), "utf8"));
|
|
630
|
+
for (const section of ["dependencies", "peerDependencies", "devDependencies"]) {
|
|
631
|
+
const range = pkg[section]?.["pactor-app"];
|
|
632
|
+
if (typeof range === "string" && range.length > 0) {
|
|
633
|
+
return range;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
} catch {
|
|
637
|
+
}
|
|
638
|
+
warnings.push("\u672A\u80FD\u63A8\u5BFC\u76EE\u6807\u5DE5\u7A0B\u7684 pactor-app \u7248\u672C\uFF0CpactorVersionRange \u56DE\u9000\u4E3A ^1.54.0");
|
|
639
|
+
return "^1.54.0";
|
|
640
|
+
}
|
|
641
|
+
function hashAssets(dir, root) {
|
|
642
|
+
const entries = [];
|
|
643
|
+
if (!(0, import_node_fs6.existsSync)(dir)) return entries;
|
|
644
|
+
for (const entry of (0, import_node_fs6.readdirSync)(dir, { withFileTypes: true }).sort(
|
|
645
|
+
(a, b) => a.name.localeCompare(b.name)
|
|
646
|
+
)) {
|
|
647
|
+
const full = (0, import_node_path6.join)(dir, entry.name);
|
|
648
|
+
if (entry.isDirectory()) {
|
|
649
|
+
entries.push(...hashAssets(full, root));
|
|
650
|
+
continue;
|
|
651
|
+
}
|
|
652
|
+
if (!entry.isFile()) continue;
|
|
653
|
+
const content = (0, import_node_fs6.readFileSync)(full);
|
|
654
|
+
entries.push({
|
|
655
|
+
path: full.slice(root.length + 1).split("\\").join("/"),
|
|
656
|
+
sha256: (0, import_node_crypto.createHash)("sha256").update(content).digest("hex"),
|
|
657
|
+
size: (0, import_node_fs6.statSync)(full).size
|
|
658
|
+
});
|
|
659
|
+
}
|
|
660
|
+
return entries;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// src/expand-include.ts
|
|
664
|
+
var import_node_fs7 = require("fs");
|
|
665
|
+
var import_node_path7 = require("path");
|
|
666
|
+
var import_yaml2 = require("yaml");
|
|
667
|
+
var INCLUDE_KEY = "$include";
|
|
668
|
+
var IncludeError = class extends Error {
|
|
669
|
+
};
|
|
670
|
+
function parseYamlFile(file) {
|
|
671
|
+
const doc = (0, import_yaml2.parseDocument)((0, import_node_fs7.readFileSync)(file, "utf8"));
|
|
672
|
+
if (doc.errors.length > 0) {
|
|
673
|
+
throw new IncludeError(
|
|
674
|
+
`${file}: ${doc.errors.map((error) => error.message).join("; ")}`
|
|
675
|
+
);
|
|
676
|
+
}
|
|
677
|
+
return doc.toJS();
|
|
678
|
+
}
|
|
679
|
+
function loadYamlExpanded(yamlRoot, relPath, stack = []) {
|
|
680
|
+
if (stack.includes(relPath)) {
|
|
681
|
+
throw new IncludeError(`\u5FAA\u73AF\u5F15\u7528: ${[...stack, relPath].join(" -> ")}`);
|
|
682
|
+
}
|
|
683
|
+
const value = parseYamlFile((0, import_node_path7.join)(yamlRoot, relPath));
|
|
684
|
+
return expandIncludes(value, { yamlRoot, current: relPath, stack: [...stack, relPath] });
|
|
685
|
+
}
|
|
686
|
+
function expandIncludes(value, ctx) {
|
|
687
|
+
if (Array.isArray(value)) {
|
|
688
|
+
return value.map((item) => expandIncludes(item, ctx));
|
|
689
|
+
}
|
|
690
|
+
if (value === null || typeof value !== "object") {
|
|
691
|
+
return value;
|
|
692
|
+
}
|
|
693
|
+
const record = value;
|
|
694
|
+
if (INCLUDE_KEY in record) {
|
|
695
|
+
if (Object.keys(record).length > 1) {
|
|
696
|
+
throw new IncludeError(`${ctx.current}: $include \u4E0D\u80FD\u4E0E\u5176\u4ED6\u5B57\u6BB5\u5E76\u5217`);
|
|
697
|
+
}
|
|
698
|
+
const target = record[INCLUDE_KEY];
|
|
699
|
+
if (typeof target !== "string") {
|
|
700
|
+
throw new IncludeError(`${ctx.current}: $include \u5FC5\u987B\u662F\u5B57\u7B26\u4E32`);
|
|
701
|
+
}
|
|
702
|
+
return loadYamlExpanded(ctx.yamlRoot, target, ctx.stack);
|
|
703
|
+
}
|
|
704
|
+
return Object.fromEntries(
|
|
705
|
+
Object.entries(record).map(([key, item]) => [key, expandIncludes(item, ctx)])
|
|
706
|
+
);
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
// src/rewrite-urls.ts
|
|
710
|
+
var import_node_fs8 = require("fs");
|
|
711
|
+
var import_node_path8 = require("path");
|
|
712
|
+
var NAVIGATION_ACTIONS = /* @__PURE__ */ new Set(["navigate", "app.reload"]);
|
|
713
|
+
var ABSOLUTE_API_RE = /^https?:\/\/[^/]+(\/api\/.+)$/;
|
|
714
|
+
function rewriteDslUrls(value, ctx) {
|
|
715
|
+
const warnings = [];
|
|
716
|
+
const walk = (node) => {
|
|
717
|
+
if (typeof node === "string") {
|
|
718
|
+
return rewriteString(node, ctx, warnings);
|
|
719
|
+
}
|
|
720
|
+
if (Array.isArray(node)) {
|
|
721
|
+
return node.map((item) => walk(item));
|
|
722
|
+
}
|
|
723
|
+
if (node === null || typeof node !== "object") {
|
|
724
|
+
return node;
|
|
725
|
+
}
|
|
726
|
+
const record = node;
|
|
727
|
+
const next = {};
|
|
728
|
+
for (const [key, item] of Object.entries(record)) {
|
|
729
|
+
next[key] = walk(item);
|
|
730
|
+
}
|
|
731
|
+
if (ctx.rewriteNavigation && isNavigationAction(record)) {
|
|
732
|
+
const params = next.params;
|
|
733
|
+
if (isRecord2(params) && typeof params.to === "string") {
|
|
734
|
+
const rewritten = rewriteNavigationTo(params.to, ctx);
|
|
735
|
+
if (rewritten !== void 0) {
|
|
736
|
+
params.to = rewritten;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
return next;
|
|
741
|
+
};
|
|
742
|
+
return { value: walk(value), warnings };
|
|
743
|
+
}
|
|
744
|
+
function isNavigationAction(record) {
|
|
745
|
+
return typeof record.action === "string" && NAVIGATION_ACTIONS.has(record.action);
|
|
746
|
+
}
|
|
747
|
+
function rewriteNavigationTo(to, ctx) {
|
|
748
|
+
if (!to.startsWith("/") || to.startsWith("//")) return void 0;
|
|
749
|
+
if (to.startsWith("/api/")) return void 0;
|
|
750
|
+
if (to === ctx.basePath || to.startsWith(`${ctx.basePath}/`)) return void 0;
|
|
751
|
+
const hit = [ctx.loginPath, ...ctx.pagePaths].some(
|
|
752
|
+
(pattern) => pattern.length > 0 && matchPathPattern(pattern, to)
|
|
753
|
+
);
|
|
754
|
+
if (!hit) return void 0;
|
|
755
|
+
return `${ctx.basePath}${to}`;
|
|
756
|
+
}
|
|
757
|
+
function matchPathPattern(pattern, value) {
|
|
758
|
+
const patternSegs = pattern.split("?")[0].split("/").filter(Boolean);
|
|
759
|
+
const valueSegs = value.split("?")[0].split("/").filter(Boolean);
|
|
760
|
+
if (patternSegs.length !== valueSegs.length) return false;
|
|
761
|
+
return patternSegs.every((seg, index) => seg.startsWith(":") || seg === valueSegs[index]);
|
|
762
|
+
}
|
|
763
|
+
function rewriteString(value, ctx, warnings) {
|
|
764
|
+
const absoluteApi = ABSOLUTE_API_RE.exec(value);
|
|
765
|
+
if (absoluteApi) {
|
|
766
|
+
const relative3 = absoluteApi[1];
|
|
767
|
+
const namespaced2 = ctx.absoluteApiToRelative ? namespaceModuleApi(relative3, ctx) : void 0;
|
|
768
|
+
const action = ctx.absoluteApiToRelative ? namespaced2 !== void 0 ? "\uFF08\u5DF2\u91CD\u5199\u4E3A\u6A21\u5757 API \u76F8\u5BF9\u8DEF\u5F84\uFF09" : "\uFF08\u5DF2\u91CD\u5199\u4E3A\u76F8\u5BF9\u8DEF\u5F84\uFF0C\u9700\u5E95\u5EA7 BFF/\u4EE3\u7406\u627F\u63A5\uFF09" : "\uFF08absoluteApiToRelative=false\uFF0C\u4FDD\u6301\u7EDD\u5BF9\u5730\u5740\uFF0C\u4E0D\u4F1A\u8D70\u6A21\u5757 API \u8DEF\u7531\uFF09";
|
|
769
|
+
warnings.push(`\u7EDD\u5BF9 API \u5730\u5740: ${value}${action}`);
|
|
770
|
+
return ctx.absoluteApiToRelative ? namespaced2 ?? relative3 : value;
|
|
771
|
+
}
|
|
772
|
+
const namespaced = namespaceModuleApi(value, ctx);
|
|
773
|
+
if (namespaced !== void 0) return namespaced;
|
|
774
|
+
if (!ctx.rewriteAssets) return value;
|
|
775
|
+
if (!value.startsWith("/") || value.startsWith("//")) return value;
|
|
776
|
+
if (value.startsWith("/api/")) return value;
|
|
777
|
+
if (value === ctx.basePath || value.startsWith(`${ctx.basePath}/`)) return value;
|
|
778
|
+
const isPagePath = [ctx.loginPath, ...ctx.pagePaths].some(
|
|
779
|
+
(pattern) => pattern.length > 0 && matchPathPattern(pattern, value)
|
|
780
|
+
);
|
|
781
|
+
if (isPagePath) return value;
|
|
782
|
+
if (!isPublicFile(ctx.publicDir, value)) return value;
|
|
783
|
+
return `${ctx.assetPrefix}${value}`;
|
|
784
|
+
}
|
|
785
|
+
function namespaceModuleApi(value, ctx) {
|
|
786
|
+
const { moduleId, apiPrefixes } = ctx;
|
|
787
|
+
if (!moduleId || !apiPrefixes || apiPrefixes.length === 0) return void 0;
|
|
788
|
+
const pathOnly = value.split(/[?#]/, 1)[0];
|
|
789
|
+
const hit = [...apiPrefixes].sort((a, b) => b.length - a.length).some((prefix) => pathOnly === prefix || pathOnly.startsWith(`${prefix}/`));
|
|
790
|
+
if (!hit) return void 0;
|
|
791
|
+
return `/api/modules/${encodeURIComponent(moduleId)}${value.slice("/api".length)}`;
|
|
792
|
+
}
|
|
793
|
+
function isPublicFile(publicDir, urlPath) {
|
|
794
|
+
const file = (0, import_node_path8.join)(publicDir, urlPath);
|
|
795
|
+
try {
|
|
796
|
+
return (0, import_node_fs8.existsSync)(file) && (0, import_node_fs8.statSync)(file).isFile();
|
|
797
|
+
} catch {
|
|
798
|
+
return false;
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
function isRecord2(value) {
|
|
802
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
// src/transform-sitemap.ts
|
|
806
|
+
function transformSitemap(site, options) {
|
|
807
|
+
const { profile, accessDefault, loadLayout } = options;
|
|
808
|
+
const fillPublic = accessDefault === "public";
|
|
809
|
+
const next = { ...site };
|
|
810
|
+
const rawLayouts = isRecord3(site.layouts) ? site.layouts : {};
|
|
811
|
+
const layouts = {};
|
|
812
|
+
for (const [name, def] of Object.entries(rawLayouts)) {
|
|
813
|
+
layouts[name] = typeof def === "string" && profile.inlineStringLayouts ? loadLayout(def) : def;
|
|
814
|
+
}
|
|
815
|
+
next.layouts = layouts;
|
|
816
|
+
const rawPages = Array.isArray(site.pages) ? site.pages : [];
|
|
817
|
+
next.pages = rawPages.map((page) => {
|
|
818
|
+
const nextPage = { ...page };
|
|
819
|
+
if (profile.forceInlinePages) {
|
|
820
|
+
delete nextPage.lazy;
|
|
821
|
+
}
|
|
822
|
+
if (fillPublic && isAccessUndeclared(nextPage)) {
|
|
823
|
+
nextPage.public = true;
|
|
824
|
+
}
|
|
825
|
+
return nextPage;
|
|
826
|
+
});
|
|
827
|
+
const rawMenus = Array.isArray(site.menus) ? site.menus : [];
|
|
828
|
+
const transformMenu = (menu) => {
|
|
829
|
+
const nextMenu = { ...menu };
|
|
830
|
+
if (profile.stripMenuPaths) {
|
|
831
|
+
delete nextMenu.path;
|
|
832
|
+
}
|
|
833
|
+
if (fillPublic && isAccessUndeclared(nextMenu)) {
|
|
834
|
+
nextMenu.public = true;
|
|
835
|
+
}
|
|
836
|
+
if (Array.isArray(nextMenu.children)) {
|
|
837
|
+
nextMenu.children = nextMenu.children.map(
|
|
838
|
+
(child) => isRecord3(child) ? transformMenu(child) : child
|
|
839
|
+
);
|
|
840
|
+
}
|
|
841
|
+
return nextMenu;
|
|
842
|
+
};
|
|
843
|
+
next.menus = rawMenus.map((menu) => isRecord3(menu) ? transformMenu(menu) : menu);
|
|
844
|
+
return {
|
|
845
|
+
site: next,
|
|
846
|
+
layoutCount: Object.keys(layouts).length,
|
|
847
|
+
pageCount: rawPages.length,
|
|
848
|
+
menuCount: rawMenus.length
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
function isRecord3(value) {
|
|
852
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
853
|
+
}
|
|
854
|
+
function isAccessUndeclared(entry) {
|
|
855
|
+
return entry.public === void 0 && entry.permission === void 0;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
// src/validate.ts
|
|
859
|
+
var import_node_fs9 = require("fs");
|
|
860
|
+
var import_node_path9 = require("path");
|
|
861
|
+
var import_yaml3 = require("yaml");
|
|
862
|
+
var REQUIRED_MANIFEST_FIELDS = [
|
|
863
|
+
"schemaVersion",
|
|
864
|
+
"id",
|
|
865
|
+
"name",
|
|
866
|
+
"version",
|
|
867
|
+
"pactorVersionRange",
|
|
868
|
+
"basePath",
|
|
869
|
+
"sitemap",
|
|
870
|
+
"dslRoot",
|
|
871
|
+
"assetsRoot"
|
|
872
|
+
];
|
|
873
|
+
function validateModule(options = {}) {
|
|
874
|
+
const projectDir = (0, import_node_path9.resolve)(options.dir ?? process.cwd());
|
|
875
|
+
const errors = [];
|
|
876
|
+
const warnings = [];
|
|
877
|
+
let config;
|
|
878
|
+
if (options.moduleDir === void 0) {
|
|
879
|
+
try {
|
|
880
|
+
config = loadModuleConfig(projectDir, options.config);
|
|
881
|
+
} catch (error) {
|
|
882
|
+
errors.push(error.message);
|
|
883
|
+
return { ok: false, errors, warnings };
|
|
884
|
+
}
|
|
885
|
+
} else {
|
|
886
|
+
try {
|
|
887
|
+
config = loadModuleConfig(projectDir, options.config);
|
|
888
|
+
} catch {
|
|
889
|
+
config = void 0;
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
const moduleDir = options.moduleDir ?? (0, import_node_path9.join)(projectDir, config?.outDir ?? CONFIG_DEFAULTS.outDir);
|
|
893
|
+
const manifestFile = (0, import_node_path9.join)(moduleDir, "manifest.json");
|
|
894
|
+
if (!(0, import_node_fs9.existsSync)(manifestFile)) {
|
|
895
|
+
errors.push(`\u4EA7\u7269\u4E0D\u5B58\u5728: ${manifestFile}\uFF08\u5148\u6267\u884C pactor module build\uFF09`);
|
|
896
|
+
return { ok: false, errors, warnings };
|
|
897
|
+
}
|
|
898
|
+
let manifest;
|
|
899
|
+
try {
|
|
900
|
+
manifest = JSON.parse((0, import_node_fs9.readFileSync)(manifestFile, "utf8"));
|
|
901
|
+
} catch (error) {
|
|
902
|
+
errors.push(`manifest.json \u89E3\u6790\u5931\u8D25: ${error.message}`);
|
|
903
|
+
return { ok: false, errors, warnings };
|
|
904
|
+
}
|
|
905
|
+
for (const field of REQUIRED_MANIFEST_FIELDS) {
|
|
906
|
+
if (!(field in manifest)) {
|
|
907
|
+
errors.push(`manifest \u7F3A\u5C11\u5B57\u6BB5: ${field}`);
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
if (manifest.schemaVersion !== "1") {
|
|
911
|
+
errors.push(`manifest.schemaVersion \u5FC5\u987B\u4E3A "1"\uFF08\u5F53\u524D: ${JSON.stringify(manifest.schemaVersion)}\uFF09`);
|
|
912
|
+
}
|
|
913
|
+
const dslRoot = typeof manifest.dslRoot === "string" ? manifest.dslRoot : "dsl";
|
|
914
|
+
const sitemapRel = typeof manifest.sitemap === "string" ? manifest.sitemap : "dsl/sitemap.yaml";
|
|
915
|
+
const sitemapFile = (0, import_node_path9.join)(moduleDir, sitemapRel);
|
|
916
|
+
if (!(0, import_node_fs9.existsSync)(sitemapFile)) {
|
|
917
|
+
errors.push(`sitemap \u4E0D\u5B58\u5728: ${sitemapRel}`);
|
|
918
|
+
} else {
|
|
919
|
+
const doc = (0, import_yaml3.parseDocument)((0, import_node_fs9.readFileSync)(sitemapFile, "utf8"));
|
|
920
|
+
if (doc.errors.length > 0) {
|
|
921
|
+
errors.push(`sitemap YAML \u89E3\u6790\u5931\u8D25: ${doc.errors.map((e) => e.message).join("; ")}`);
|
|
922
|
+
} else {
|
|
923
|
+
const site = doc.toJS();
|
|
924
|
+
const pages = Array.isArray(site.pages) ? site.pages : [];
|
|
925
|
+
for (const page of pages) {
|
|
926
|
+
const id = page.id;
|
|
927
|
+
if (typeof id !== "string") {
|
|
928
|
+
errors.push("sitemap.pages \u5B58\u5728\u7F3A\u5C11 id \u7684\u9875\u9762\u9879");
|
|
929
|
+
continue;
|
|
930
|
+
}
|
|
931
|
+
if (findPageDslFile((0, import_node_path9.join)(moduleDir, dslRoot), id) === null) {
|
|
932
|
+
errors.push(`\u9875\u9762 ${id} \u7F3A\u5C11 DSL \u6587\u4EF6\uFF08${dslRoot}/ \u4E0B\u672A\u627E\u5230 ${id}.yaml\uFF09`);
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
const layouts = site.layouts;
|
|
936
|
+
if (layouts !== null && typeof layouts === "object" && !Array.isArray(layouts)) {
|
|
937
|
+
for (const [name, def] of Object.entries(layouts)) {
|
|
938
|
+
if (typeof def === "string") {
|
|
939
|
+
errors.push(`\u5E03\u5C40 ${name} \u4ECD\u662F\u5B57\u7B26\u4E32\u5F15\u7528\uFF08target \u8981\u6C42\u5185\u8054\u4E3A\u5BF9\u8C61\uFF09`);
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
const dslDir = (0, import_node_path9.join)(moduleDir, dslRoot);
|
|
946
|
+
for (const file of listFiles(dslDir)) {
|
|
947
|
+
if ((0, import_node_fs9.readFileSync)(file, "utf8").includes(INCLUDE_KEY)) {
|
|
948
|
+
errors.push(`$include \u6B8B\u7559: ${(0, import_node_path9.relative)(moduleDir, file)}`);
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
if (typeof manifest.clientEntry === "string") {
|
|
952
|
+
const clientFile = (0, import_node_path9.join)(moduleDir, manifest.clientEntry);
|
|
953
|
+
if (!(0, import_node_fs9.existsSync)(clientFile)) {
|
|
954
|
+
errors.push(`client bundle \u4E0D\u5B58\u5728: ${manifest.clientEntry}`);
|
|
955
|
+
} else {
|
|
956
|
+
const text = (0, import_node_fs9.readFileSync)(clientFile, "utf8");
|
|
957
|
+
if (/\bvar React\b|react\.production\.min|__REACT_DEVTOOLS_GLOBAL_HOOK__/.test(text)) {
|
|
958
|
+
errors.push("client bundle \u7591\u4F3C\u5185\u5D4C react\uFF08react \u5FC5\u987B\u4FDD\u6301 external\uFF0C\u907F\u514D\u53CC\u5B9E\u4F8B\uFF09");
|
|
959
|
+
}
|
|
960
|
+
if (/node_modules\/@pactor-app\//.test(text) || /node_modules\/pactor-app\//.test(text)) {
|
|
961
|
+
errors.push("client bundle \u7591\u4F3C\u5185\u5D4C pactor \u8FD0\u884C\u65F6\u4EE3\u7801\uFF08@pactor-app/* \u5FC5\u987B\u4FDD\u6301 external\uFF09");
|
|
962
|
+
}
|
|
963
|
+
const sizeKb = Math.round((0, import_node_fs9.statSync)(clientFile).size / 1024);
|
|
964
|
+
if (sizeKb > 512) {
|
|
965
|
+
warnings.push(`client bundle \u4F53\u79EF\u8F83\u5927\uFF08${sizeKb}KB\uFF09\uFF0C\u8BF7\u786E\u8BA4 react / pactor \u5DF2 external`);
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
const hasServerEntry = typeof manifest.serverEntry === "string";
|
|
970
|
+
const hasApiPrefixes = Array.isArray(manifest.apiPrefixes);
|
|
971
|
+
if (hasServerEntry !== hasApiPrefixes) {
|
|
972
|
+
errors.push("manifest.serverEntry \u4E0E apiPrefixes \u5FC5\u987B\u6210\u5BF9\u51FA\u73B0");
|
|
973
|
+
}
|
|
974
|
+
if (hasServerEntry) {
|
|
975
|
+
const serverRel = manifest.serverEntry;
|
|
976
|
+
const serverFile = (0, import_node_path9.resolve)(moduleDir, serverRel);
|
|
977
|
+
if (!isInsideDir(moduleDir, serverFile)) {
|
|
978
|
+
errors.push(`server bundle \u8DEF\u5F84\u8D8A\u754C: ${serverRel}`);
|
|
979
|
+
} else if (!(0, import_node_fs9.existsSync)(serverFile)) {
|
|
980
|
+
errors.push(`server bundle \u4E0D\u5B58\u5728: ${serverRel}`);
|
|
981
|
+
} else {
|
|
982
|
+
const text = (0, import_node_fs9.readFileSync)(serverFile, "utf8");
|
|
983
|
+
if (/node_modules\/(?:next|react|react-dom|@pactor-app|pactor-app)\//.test(text)) {
|
|
984
|
+
warnings.push(
|
|
985
|
+
"server bundle \u7591\u4F3C\u5185\u5D4C next / react / pactor\uFF08\u5E94\u4FDD\u6301 external\uFF0C\u7531\u5BBF\u4E3B\u63D0\u4F9B\uFF09"
|
|
986
|
+
);
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
if (!Array.isArray(manifest.apiPrefixes) || manifest.apiPrefixes.length === 0) {
|
|
990
|
+
errors.push("manifest.apiPrefixes \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4");
|
|
991
|
+
} else if (manifest.apiPrefixes.some((prefix) => typeof prefix !== "string")) {
|
|
992
|
+
errors.push("manifest.apiPrefixes \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6570\u7EC4");
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
const pkgFile = (0, import_node_path9.join)(projectDir, "package.json");
|
|
996
|
+
if ((0, import_node_fs9.existsSync)(pkgFile)) {
|
|
997
|
+
try {
|
|
998
|
+
const pkg = JSON.parse((0, import_node_fs9.readFileSync)(pkgFile, "utf8"));
|
|
999
|
+
const exportsMap = pkg.exports ?? {};
|
|
1000
|
+
if (exportsMap["./manifest"] === void 0) {
|
|
1001
|
+
errors.push('package.json exports \u7F3A\u5C11 "./manifest"\uFF08Shell \u88C5\u914D\u5668\u7ECF require.resolve("<pkg>/manifest") \u5B9A\u4F4D\uFF09');
|
|
1002
|
+
}
|
|
1003
|
+
if (typeof manifest.clientEntry === "string" && exportsMap["./client"] === void 0) {
|
|
1004
|
+
errors.push('package.json exports \u7F3A\u5C11 "./client"\uFF08client-registry \u9759\u6001 import "<pkg>/client"\uFF09');
|
|
1005
|
+
}
|
|
1006
|
+
if (typeof manifest.serverEntry === "string" && exportsMap["./server"] === void 0) {
|
|
1007
|
+
errors.push('package.json exports \u7F3A\u5C11 "./server"\uFF08Shell \u88C5\u914D\u5668\u7ECF require.resolve("<pkg>/server") \u5B9A\u4F4D\uFF09');
|
|
1008
|
+
}
|
|
1009
|
+
if (typeof pkg.version === "string" && typeof manifest.version === "string" && pkg.version !== manifest.version) {
|
|
1010
|
+
warnings.push(
|
|
1011
|
+
`manifest.version (${manifest.version}) \u4E0E package.json version (${pkg.version}) \u4E0D\u4E00\u81F4\uFF0C\u8BF7\u91CD\u65B0 build`
|
|
1012
|
+
);
|
|
1013
|
+
}
|
|
1014
|
+
} catch {
|
|
1015
|
+
warnings.push("package.json \u89E3\u6790\u5931\u8D25\uFF0C\u8DF3\u8FC7 exports \u68C0\u67E5");
|
|
1016
|
+
}
|
|
1017
|
+
} else {
|
|
1018
|
+
warnings.push("\u672A\u627E\u5230 package.json\uFF0C\u8DF3\u8FC7 exports \u68C0\u67E5");
|
|
1019
|
+
}
|
|
1020
|
+
return { ok: errors.length === 0, errors, warnings };
|
|
1021
|
+
}
|
|
1022
|
+
function isInsideDir(dir, file) {
|
|
1023
|
+
const root = (0, import_node_path9.resolve)(dir);
|
|
1024
|
+
return file.startsWith(`${root}${import_node_path9.sep}`);
|
|
1025
|
+
}
|
|
1026
|
+
function findPageDslFile(dslRootDir, pageId) {
|
|
1027
|
+
if (!(0, import_node_fs9.existsSync)(dslRootDir)) return null;
|
|
1028
|
+
const queue = [dslRootDir];
|
|
1029
|
+
while (queue.length > 0) {
|
|
1030
|
+
const dir = queue.pop();
|
|
1031
|
+
for (const entry of (0, import_node_fs9.readdirSync)(dir, { withFileTypes: true })) {
|
|
1032
|
+
const full = (0, import_node_path9.join)(dir, entry.name);
|
|
1033
|
+
if (entry.isDirectory()) {
|
|
1034
|
+
queue.push(full);
|
|
1035
|
+
continue;
|
|
1036
|
+
}
|
|
1037
|
+
if (entry.name === `${pageId}.yaml`) return full;
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
return null;
|
|
1041
|
+
}
|
|
1042
|
+
function listFiles(dir) {
|
|
1043
|
+
if (!(0, import_node_fs9.existsSync)(dir)) return [];
|
|
1044
|
+
const files = [];
|
|
1045
|
+
const walk = (target) => {
|
|
1046
|
+
for (const entry of (0, import_node_fs9.readdirSync)(target, { withFileTypes: true })) {
|
|
1047
|
+
const full = (0, import_node_path9.join)(target, entry.name);
|
|
1048
|
+
if (entry.isDirectory()) {
|
|
1049
|
+
walk(full);
|
|
1050
|
+
} else if (entry.isFile()) {
|
|
1051
|
+
files.push(full);
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
};
|
|
1055
|
+
walk(dir);
|
|
1056
|
+
return files;
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
// src/build.ts
|
|
1060
|
+
var ModuleBuildError = class extends Error {
|
|
1061
|
+
constructor(message, errors) {
|
|
1062
|
+
super(message);
|
|
1063
|
+
this.errors = errors;
|
|
1064
|
+
}
|
|
1065
|
+
};
|
|
1066
|
+
function buildModule(options = {}) {
|
|
1067
|
+
const projectDir = (0, import_node_path10.resolve)(options.dir ?? process.cwd());
|
|
1068
|
+
const config = loadModuleConfig(projectDir, options.config);
|
|
1069
|
+
const profile = getProfile(config.target);
|
|
1070
|
+
if (profile.forbidRootBasePath && config.basePath === "/") {
|
|
1071
|
+
throw new ModuleBuildError(
|
|
1072
|
+
`target ${config.target} \u7981\u6B62 basePath: "/"\uFF08Shell joinPublicPath \u4F1A\u4EA7\u751F "//login" \u8FD9\u7C7B\u574F\u8DEF\u5F84\uFF09`,
|
|
1073
|
+
[`basePath: "/" \u4E0E profile ${config.target} \u7684 forbidRootBasePath \u51B2\u7A81\uFF0C\u8BF7\u6539\u7528\u5982 /${config.id} \u7684\u524D\u7F00`]
|
|
1074
|
+
);
|
|
1075
|
+
}
|
|
1076
|
+
if (config.serverEntry !== void 0 && !profile.moduleServerApi) {
|
|
1077
|
+
throw new ModuleBuildError(
|
|
1078
|
+
`target ${config.target} \u4E0D\u652F\u6301\u6A21\u5757 server entry\uFF08\u9700\u8981 innospots-web-shell@3\uFF09`,
|
|
1079
|
+
[
|
|
1080
|
+
`\u914D\u7F6E\u4E86 serverEntry / apiPrefixes\uFF0C\u4F46 profile ${config.target} \u7684 moduleServerApi=false`,
|
|
1081
|
+
'\u8BF7\u628A pactor.module.json \u7684 target \u5347\u5230 "innospots-web-shell@3" \u540E\u91CD\u65B0\u6784\u5EFA'
|
|
1082
|
+
]
|
|
1083
|
+
);
|
|
1084
|
+
}
|
|
1085
|
+
const yamlRoot = (0, import_node_path10.join)(projectDir, config.yamlRoot);
|
|
1086
|
+
if (!(0, import_node_fs10.existsSync)(yamlRoot)) {
|
|
1087
|
+
throw new ModuleBuildError(`yamlRoot \u4E0D\u5B58\u5728: ${config.yamlRoot}`, [
|
|
1088
|
+
`yamlRoot \u4E0D\u5B58\u5728: ${yamlRoot}`
|
|
1089
|
+
]);
|
|
1090
|
+
}
|
|
1091
|
+
const warnings = [];
|
|
1092
|
+
const collected = collectModuleSource(yamlRoot);
|
|
1093
|
+
warnings.push(...collected.warnings);
|
|
1094
|
+
let site;
|
|
1095
|
+
try {
|
|
1096
|
+
site = loadYamlExpanded(yamlRoot, "sitemap.yaml");
|
|
1097
|
+
} catch (error) {
|
|
1098
|
+
const message = `sitemap \u5C55\u5F00\u5931\u8D25: ${error.message}`;
|
|
1099
|
+
throw new ModuleBuildError(message, [message]);
|
|
1100
|
+
}
|
|
1101
|
+
const sitePages = Array.isArray(site.pages) ? site.pages : [];
|
|
1102
|
+
const errors = [];
|
|
1103
|
+
const pageDsls = /* @__PURE__ */ new Map();
|
|
1104
|
+
for (const page of sitePages) {
|
|
1105
|
+
const id = page.id;
|
|
1106
|
+
if (typeof id !== "string") {
|
|
1107
|
+
errors.push("sitemap.pages \u5B58\u5728\u7F3A\u5C11 id \u7684\u9875\u9762\u9879");
|
|
1108
|
+
continue;
|
|
1109
|
+
}
|
|
1110
|
+
const rel = collected.pages.get(id);
|
|
1111
|
+
if (rel === void 0) {
|
|
1112
|
+
errors.push(`\u9875\u9762 DSL \u7F3A\u5931: ${id}\uFF08${config.yamlRoot} \u4E0B\u672A\u627E\u5230 ${id}.yaml / ${id}.page.yaml\uFF09`);
|
|
1113
|
+
continue;
|
|
1114
|
+
}
|
|
1115
|
+
try {
|
|
1116
|
+
pageDsls.set(id, loadYamlExpanded(yamlRoot, rel));
|
|
1117
|
+
} catch (error) {
|
|
1118
|
+
errors.push(`\u9875\u9762 ${id} \u5C55\u5F00\u5931\u8D25: ${error.message}`);
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
if (errors.length > 0) {
|
|
1122
|
+
throw new ModuleBuildError(`\u6A21\u5757\u6784\u5EFA\u5931\u8D25\uFF08${errors.length} \u4E2A\u9519\u8BEF\uFF09`, errors);
|
|
1123
|
+
}
|
|
1124
|
+
const transformed = transformSitemap(site, {
|
|
1125
|
+
profile,
|
|
1126
|
+
accessDefault: config.access.default,
|
|
1127
|
+
loadLayout: (rel) => loadYamlExpanded(yamlRoot, rel)
|
|
1128
|
+
});
|
|
1129
|
+
const version = readProjectVersion(projectDir);
|
|
1130
|
+
const siteAuth = site.auth !== null && typeof site.auth === "object" && !Array.isArray(site.auth) ? site.auth : {};
|
|
1131
|
+
const rewriteCtx = {
|
|
1132
|
+
basePath: config.basePath,
|
|
1133
|
+
pagePaths: sitePages.map((page) => page.path).filter((path) => typeof path === "string"),
|
|
1134
|
+
loginPath: typeof siteAuth.loginPath === "string" ? siteAuth.loginPath : "/login",
|
|
1135
|
+
publicDir: (0, import_node_path10.join)(projectDir, config.publicDir),
|
|
1136
|
+
rewriteNavigation: profile.rewriteNavigation.basePath,
|
|
1137
|
+
rewriteAssets: true,
|
|
1138
|
+
assetPrefix: profile.rewriteAssetUrls(config.id, version).replace(/\/+$/, ""),
|
|
1139
|
+
absoluteApiToRelative: config.rewrite.absoluteApiToRelative,
|
|
1140
|
+
moduleId: config.id,
|
|
1141
|
+
apiPrefixes: config.apiPrefixes
|
|
1142
|
+
};
|
|
1143
|
+
const sitemapRewrite = rewriteDslUrls(transformed.site, rewriteCtx);
|
|
1144
|
+
warnings.push(...sitemapRewrite.warnings);
|
|
1145
|
+
const rewrittenPages = /* @__PURE__ */ new Map();
|
|
1146
|
+
for (const [id, dsl] of pageDsls) {
|
|
1147
|
+
const result = rewriteDslUrls(dsl, rewriteCtx);
|
|
1148
|
+
warnings.push(...result.warnings.map((warning) => `${id}: ${warning}`));
|
|
1149
|
+
rewrittenPages.set(id, result.value);
|
|
1150
|
+
}
|
|
1151
|
+
const outDir = (0, import_node_path10.join)(projectDir, config.outDir);
|
|
1152
|
+
const temp = (0, import_node_fs10.mkdtempSync)((0, import_node_path10.join)(projectDir, ".module-pack-"));
|
|
1153
|
+
try {
|
|
1154
|
+
const bundle = bundleClient({
|
|
1155
|
+
projectDir,
|
|
1156
|
+
clientEntry: config.clientEntry,
|
|
1157
|
+
outDir: (0, import_node_path10.join)(temp, "client")
|
|
1158
|
+
});
|
|
1159
|
+
if (bundle.message !== void 0) {
|
|
1160
|
+
warnings.push(bundle.message);
|
|
1161
|
+
}
|
|
1162
|
+
const server = config.serverEntry ? bundleServer({
|
|
1163
|
+
projectDir,
|
|
1164
|
+
serverEntry: config.serverEntry,
|
|
1165
|
+
outDir: (0, import_node_path10.join)(temp, "server")
|
|
1166
|
+
}) : void 0;
|
|
1167
|
+
const emitted = emitDsl({
|
|
1168
|
+
config,
|
|
1169
|
+
projectDir,
|
|
1170
|
+
outDir: temp,
|
|
1171
|
+
site: sitemapRewrite.value,
|
|
1172
|
+
pages: rewrittenPages
|
|
1173
|
+
});
|
|
1174
|
+
if (bundle.bundled && config.tailwind.enabled) {
|
|
1175
|
+
const tailwind = compileTailwind({
|
|
1176
|
+
projectDir,
|
|
1177
|
+
tailwind: config.tailwind,
|
|
1178
|
+
scanDirs: [(0, import_node_path10.join)(temp, "dsl"), (0, import_node_path10.dirname)((0, import_node_path10.join)(projectDir, config.clientEntry))],
|
|
1179
|
+
cssFile: (0, import_node_path10.join)(temp, "client", "index.css")
|
|
1180
|
+
});
|
|
1181
|
+
warnings.push(...tailwind.warnings);
|
|
1182
|
+
}
|
|
1183
|
+
const hasCss = (0, import_node_fs10.existsSync)((0, import_node_path10.join)(temp, "client", "index.css"));
|
|
1184
|
+
writeManifest({
|
|
1185
|
+
config,
|
|
1186
|
+
projectDir,
|
|
1187
|
+
outDir: temp,
|
|
1188
|
+
clientEntry: bundle.bundled ? "client/index.js" : void 0,
|
|
1189
|
+
styles: bundle.bundled && hasCss ? ["client/index.css"] : void 0,
|
|
1190
|
+
serverEntry: server ? "server/index.mjs" : void 0,
|
|
1191
|
+
apiPrefixes: server ? config.apiPrefixes : void 0,
|
|
1192
|
+
warnings
|
|
1193
|
+
});
|
|
1194
|
+
const validation = validateModule({ dir: projectDir, config: options.config, moduleDir: temp });
|
|
1195
|
+
warnings.push(...validation.warnings);
|
|
1196
|
+
if (!validation.ok) {
|
|
1197
|
+
throw new ModuleBuildError(
|
|
1198
|
+
`\u4EA7\u7269\u6821\u9A8C\u5931\u8D25\uFF08${validation.errors.length} \u4E2A\u9519\u8BEF\uFF09`,
|
|
1199
|
+
validation.errors
|
|
1200
|
+
);
|
|
1201
|
+
}
|
|
1202
|
+
(0, import_node_fs10.rmSync)(outDir, { recursive: true, force: true });
|
|
1203
|
+
(0, import_node_fs10.mkdirSync)((0, import_node_path10.dirname)(outDir), { recursive: true });
|
|
1204
|
+
(0, import_node_fs10.renameSync)(temp, outDir);
|
|
1205
|
+
return {
|
|
1206
|
+
outDir,
|
|
1207
|
+
stats: {
|
|
1208
|
+
pages: transformed.pageCount,
|
|
1209
|
+
menus: transformed.menuCount,
|
|
1210
|
+
layouts: transformed.layoutCount,
|
|
1211
|
+
assets: emitted.assetCount
|
|
1212
|
+
},
|
|
1213
|
+
clientBundled: bundle.bundled,
|
|
1214
|
+
serverBundled: server !== void 0,
|
|
1215
|
+
warnings
|
|
1216
|
+
};
|
|
1217
|
+
} catch (error) {
|
|
1218
|
+
(0, import_node_fs10.rmSync)(temp, { recursive: true, force: true });
|
|
1219
|
+
throw error;
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
// src/init.ts
|
|
1224
|
+
var import_node_fs11 = require("fs");
|
|
1225
|
+
var import_node_path11 = require("path");
|
|
1226
|
+
var CLIENT_STYLES_ENTRY = "module/module.css";
|
|
1227
|
+
var SERVER_ENTRY = "module/server.ts";
|
|
1228
|
+
function initModule(options = {}) {
|
|
1229
|
+
const projectDir = (0, import_node_path11.resolve)(options.dir ?? process.cwd());
|
|
1230
|
+
const overwrite = options.overwrite ?? false;
|
|
1231
|
+
const server = options.server ?? false;
|
|
1232
|
+
const result = { created: [], overwritten: [], skipped: [], warnings: [] };
|
|
1233
|
+
const pkgFile = (0, import_node_path11.join)(projectDir, "package.json");
|
|
1234
|
+
if (!(0, import_node_fs11.existsSync)(pkgFile)) {
|
|
1235
|
+
throw new Error(`\u672A\u627E\u5230 package.json: ${projectDir}\uFF08\u8BF7\u5728\u76EE\u6807\u5DE5\u7A0B\u6839\u6267\u884C\uFF09`);
|
|
1236
|
+
}
|
|
1237
|
+
const pkg = JSON.parse((0, import_node_fs11.readFileSync)(pkgFile, "utf8"));
|
|
1238
|
+
const id = deriveModuleId(pkg.name);
|
|
1239
|
+
const actions = discoverActions(projectDir);
|
|
1240
|
+
const hasComponents = discoverComponents(projectDir);
|
|
1241
|
+
const configFile = (0, import_node_path11.join)(projectDir, CONFIG_FILE);
|
|
1242
|
+
const renderConfig = () => ({
|
|
1243
|
+
id,
|
|
1244
|
+
name: typeof pkg.name === "string" ? pkg.name : id,
|
|
1245
|
+
basePath: `/${id}`,
|
|
1246
|
+
yamlRoot: CONFIG_DEFAULTS.yamlRoot,
|
|
1247
|
+
clientEntry: CONFIG_DEFAULTS.clientEntry,
|
|
1248
|
+
// 只有显式 --server 才写入,避免纯 DSL 模块被迫启用 server entry
|
|
1249
|
+
...server ? { serverEntry: SERVER_ENTRY, apiPrefixes: [deriveApiPrefix(id)] } : {},
|
|
1250
|
+
actions: actions.map((action) => action.specifier.replace(/^\.\.\//, "")),
|
|
1251
|
+
publicDir: CONFIG_DEFAULTS.publicDir,
|
|
1252
|
+
target: DEFAULT_TARGET
|
|
1253
|
+
});
|
|
1254
|
+
const configExisted = (0, import_node_fs11.existsSync)(configFile);
|
|
1255
|
+
if (configExisted && !overwrite) {
|
|
1256
|
+
result.skipped.push(`${CONFIG_FILE}\uFF08\u5DF2\u5B58\u5728\uFF09`);
|
|
1257
|
+
} else {
|
|
1258
|
+
(0, import_node_fs11.writeFileSync)(configFile, `${JSON.stringify(renderConfig(), null, 2)}
|
|
1259
|
+
`, "utf8");
|
|
1260
|
+
if (configExisted) {
|
|
1261
|
+
result.overwritten.push(CONFIG_FILE);
|
|
1262
|
+
} else {
|
|
1263
|
+
result.created.push(CONFIG_FILE);
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
const clientFile = (0, import_node_path11.join)(projectDir, CONFIG_DEFAULTS.clientEntry);
|
|
1267
|
+
if ((0, import_node_fs11.existsSync)(clientFile) && !overwrite) {
|
|
1268
|
+
result.skipped.push(`${CONFIG_DEFAULTS.clientEntry}\uFF08\u5DF2\u5B58\u5728\uFF09`);
|
|
1269
|
+
} else {
|
|
1270
|
+
const clientExisted = (0, import_node_fs11.existsSync)(clientFile);
|
|
1271
|
+
(0, import_node_fs11.mkdirSync)((0, import_node_path11.dirname)(clientFile), { recursive: true });
|
|
1272
|
+
(0, import_node_fs11.writeFileSync)(clientFile, renderClientEntry(hasComponents, actions), "utf8");
|
|
1273
|
+
if (clientExisted) {
|
|
1274
|
+
result.overwritten.push(CONFIG_DEFAULTS.clientEntry);
|
|
1275
|
+
} else {
|
|
1276
|
+
result.created.push(CONFIG_DEFAULTS.clientEntry);
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
const stylesFile = (0, import_node_path11.join)(projectDir, CLIENT_STYLES_ENTRY);
|
|
1280
|
+
if ((0, import_node_fs11.existsSync)(stylesFile) && !overwrite) {
|
|
1281
|
+
result.skipped.push(`${CLIENT_STYLES_ENTRY}\uFF08\u5DF2\u5B58\u5728\uFF09`);
|
|
1282
|
+
} else {
|
|
1283
|
+
const stylesExisted = (0, import_node_fs11.existsSync)(stylesFile);
|
|
1284
|
+
(0, import_node_fs11.mkdirSync)((0, import_node_path11.dirname)(stylesFile), { recursive: true });
|
|
1285
|
+
(0, import_node_fs11.writeFileSync)(stylesFile, renderModuleStyles(), "utf8");
|
|
1286
|
+
if (stylesExisted) {
|
|
1287
|
+
result.overwritten.push(CLIENT_STYLES_ENTRY);
|
|
1288
|
+
} else {
|
|
1289
|
+
result.created.push(CLIENT_STYLES_ENTRY);
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
if (server) {
|
|
1293
|
+
const serverFile = (0, import_node_path11.join)(projectDir, SERVER_ENTRY);
|
|
1294
|
+
if ((0, import_node_fs11.existsSync)(serverFile) && !overwrite) {
|
|
1295
|
+
result.skipped.push(`${SERVER_ENTRY}\uFF08\u5DF2\u5B58\u5728\uFF09`);
|
|
1296
|
+
} else {
|
|
1297
|
+
const serverExisted = (0, import_node_fs11.existsSync)(serverFile);
|
|
1298
|
+
(0, import_node_fs11.mkdirSync)((0, import_node_path11.dirname)(serverFile), { recursive: true });
|
|
1299
|
+
(0, import_node_fs11.writeFileSync)(serverFile, renderServerEntry(id), "utf8");
|
|
1300
|
+
if (serverExisted) {
|
|
1301
|
+
result.overwritten.push(SERVER_ENTRY);
|
|
1302
|
+
} else {
|
|
1303
|
+
result.created.push(SERVER_ENTRY);
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
const hasServerEntry = (0, import_node_fs11.existsSync)((0, import_node_path11.join)(projectDir, SERVER_ENTRY));
|
|
1308
|
+
injectPackageJson(pkg, result, hasServerEntry);
|
|
1309
|
+
if (hasServerEntry && !configDeclaresServerEntry(configFile)) {
|
|
1310
|
+
result.warnings.push(
|
|
1311
|
+
'\u68C0\u6D4B\u5230 module/server.ts\uFF1A\u5DF2\u6CE8\u5165 "./server" export\uFF1B\u8BF7\u5728 pactor.module.json \u4E2D\u540C\u65F6\u914D\u7F6E serverEntry \u4E0E apiPrefixes \u540E\u518D\u6784\u5EFA\uFF08\u7F3A\u4E00\u6784\u5EFA\u4F1A\u5931\u8D25\uFF09'
|
|
1312
|
+
);
|
|
1313
|
+
}
|
|
1314
|
+
(0, import_node_fs11.writeFileSync)(pkgFile, `${JSON.stringify(pkg, null, 2)}
|
|
1315
|
+
`, "utf8");
|
|
1316
|
+
result.created.push("package.json\uFF08\u6CE8\u5165 files / exports / scripts / peerDependencies\uFF09");
|
|
1317
|
+
return result;
|
|
1318
|
+
}
|
|
1319
|
+
function configDeclaresServerEntry(configFile) {
|
|
1320
|
+
if (!(0, import_node_fs11.existsSync)(configFile)) return false;
|
|
1321
|
+
try {
|
|
1322
|
+
const raw = JSON.parse((0, import_node_fs11.readFileSync)(configFile, "utf8"));
|
|
1323
|
+
return raw.serverEntry === SERVER_ENTRY;
|
|
1324
|
+
} catch {
|
|
1325
|
+
return false;
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
var MODULE_ID_PREFIX = "pactor-app-";
|
|
1329
|
+
function deriveModuleId(name) {
|
|
1330
|
+
const base2 = typeof name === "string" && name.length > 0 ? name : "module";
|
|
1331
|
+
const withoutScope = base2.startsWith("@") ? base2.slice(base2.indexOf("/") + 1) : base2;
|
|
1332
|
+
const kebab = withoutScope.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
1333
|
+
const id = kebab.length > 0 ? kebab : "module";
|
|
1334
|
+
return id.startsWith(MODULE_ID_PREFIX) ? id : `${MODULE_ID_PREFIX}${id}`;
|
|
1335
|
+
}
|
|
1336
|
+
function deriveApiPrefix(moduleId) {
|
|
1337
|
+
const slug = moduleId.startsWith(MODULE_ID_PREFIX) ? moduleId.slice(MODULE_ID_PREFIX.length) : moduleId;
|
|
1338
|
+
return `/api/${slug.length > 0 ? slug : "module"}`;
|
|
1339
|
+
}
|
|
1340
|
+
function discoverActions(projectDir) {
|
|
1341
|
+
const dir = (0, import_node_path11.join)(projectDir, "src/pactor");
|
|
1342
|
+
if (!(0, import_node_fs11.existsSync)(dir)) return [];
|
|
1343
|
+
const sources = [];
|
|
1344
|
+
for (const entry of (0, import_node_fs11.readdirSync)(dir, { withFileTypes: true }).sort(
|
|
1345
|
+
(a, b) => a.name.localeCompare(b.name)
|
|
1346
|
+
)) {
|
|
1347
|
+
if (!entry.isFile() || !entry.name.endsWith("-actions.ts")) continue;
|
|
1348
|
+
const file = (0, import_node_path11.join)(dir, entry.name);
|
|
1349
|
+
const content = (0, import_node_fs11.readFileSync)(file, "utf8");
|
|
1350
|
+
const exports2 = [...content.matchAll(/export\s+const\s+([A-Za-z_$][\w$]*)/g)].map(
|
|
1351
|
+
(match) => match[1]
|
|
1352
|
+
);
|
|
1353
|
+
if (exports2.length === 0) continue;
|
|
1354
|
+
sources.push({
|
|
1355
|
+
specifier: `../src/pactor/${entry.name.replace(/\.ts$/, "")}`,
|
|
1356
|
+
exports: exports2
|
|
1357
|
+
});
|
|
1358
|
+
}
|
|
1359
|
+
return sources;
|
|
1360
|
+
}
|
|
1361
|
+
function discoverComponents(projectDir) {
|
|
1362
|
+
const file = (0, import_node_path11.join)(projectDir, "src/pactor/components/index.ts");
|
|
1363
|
+
if (!(0, import_node_fs11.existsSync)(file)) return false;
|
|
1364
|
+
return /export\s+(const|\{[^}]*)\s*pactorComponents/.test((0, import_node_fs11.readFileSync)(file, "utf8"));
|
|
1365
|
+
}
|
|
1366
|
+
function renderClientEntry(hasComponents, actions) {
|
|
1367
|
+
const imports = [];
|
|
1368
|
+
const spreads = [];
|
|
1369
|
+
if (hasComponents) {
|
|
1370
|
+
imports.push("import { pactorComponents } from '../src/pactor/components';");
|
|
1371
|
+
}
|
|
1372
|
+
for (const action of actions) {
|
|
1373
|
+
imports.push(
|
|
1374
|
+
`import { ${action.exports.join(", ")} } from '${action.specifier}';`
|
|
1375
|
+
);
|
|
1376
|
+
spreads.push(...action.exports.map((name) => `...${name}`));
|
|
1377
|
+
}
|
|
1378
|
+
const components = hasComponents ? "pactorComponents" : "{}";
|
|
1379
|
+
const actionsExpr = spreads.length > 0 ? `{ ${spreads.join(", ")} }` : "{}";
|
|
1380
|
+
const importsBlock = imports.length > 0 ? `${imports.join("\n")}
|
|
1381
|
+
` : "";
|
|
1382
|
+
return `// \u7531 \`pactor module init\` \u751F\u6210\uFF1A\u6A21\u5757 client \u5165\u53E3\u3002
|
|
1383
|
+
// Shell \u88C5\u914D\u5668\u751F\u6210 client-registry.ts \u65F6\u9759\u6001 import "<pkg>/client"\uFF0C
|
|
1384
|
+
// \u8981\u6C42\u6B64\u5904\u5177\u540D\u5BFC\u51FA extensions\uFF08components / actions \u6CE8\u518C\u8868\uFF09\u3002
|
|
1385
|
+
// module.css \u7531 esbuild \u62BD\u6210 client/index.css\uFF0CShell \u6309 manifest.styles \u52A0\u8F7D\u3002
|
|
1386
|
+
import './module.css';
|
|
1387
|
+
${importsBlock}
|
|
1388
|
+
export const extensions = {
|
|
1389
|
+
components: ${components},
|
|
1390
|
+
actions: ${actionsExpr},
|
|
1391
|
+
};
|
|
1392
|
+
`;
|
|
1393
|
+
}
|
|
1394
|
+
function renderModuleStyles() {
|
|
1395
|
+
return `/**
|
|
1396
|
+
* \u6A21\u5757\u81EA\u5E26\u6837\u5F0F\uFF08\u7531 \`pactor module init\` \u751F\u6210\uFF09\u3002
|
|
1397
|
+
*
|
|
1398
|
+
* \u672C\u6587\u4EF6\u7531 module/client.ts import\uFF1Aesbuild \u6253\u5305\u65F6\u4F1A\u62BD\u53D6\u4E3A
|
|
1399
|
+
* dist-module/client/index.css \u5E76\u5199\u5165 manifest.styles\uFF0CShell \u636E\u6B64\u81EA\u52A8\u52A0\u8F7D\u3002
|
|
1400
|
+
* Tailwind \u57FA\u7840\u6837\u5F0F\u3001pactor-app \u805A\u5408\u6837\u5F0F\u4E0E\u4E3B\u9898\u53D8\u91CF\u7531 Shell \u7EDF\u4E00\u63D0\u4F9B\uFF0C
|
|
1401
|
+
* \u6A21\u5757\u5185\u4E0D\u8981\u91CD\u590D\u5F15\u5165\uFF0C\u907F\u514D\u4EA7\u751F\u7B2C\u4E8C\u4EFD reset / \u4EE4\u724C\u3002
|
|
1402
|
+
*/
|
|
1403
|
+
|
|
1404
|
+
/* \u6A21\u5757\u7EA7\u6837\u5F0F\u5199\u5728\u8FD9\u91CC\uFF1A\u5EFA\u8BAE\u4F7F\u7528\u5E26\u6A21\u5757\u524D\u7F00\u7684\u7C7B\u540D\uFF0C\u907F\u514D\u4E0E Shell \u5168\u5C40\u6837\u5F0F\u51B2\u7A81\u3002 */
|
|
1405
|
+
`;
|
|
1406
|
+
}
|
|
1407
|
+
function renderServerEntry(moduleId) {
|
|
1408
|
+
const prefix = deriveApiPrefix(moduleId);
|
|
1409
|
+
return `// \u7531 \`pactor module init --server\` \u751F\u6210\uFF1A\u6A21\u5757\u670D\u52A1\u7AEF\u5165\u53E3\u3002
|
|
1410
|
+
// \u5BFC\u51FA\u300C\u903B\u8F91\u8DEF\u5F84 \u2192 \u65B9\u6CD5\u5904\u7406\u51FD\u6570\u300D\u6620\u5C04\uFF1A\u8DEF\u5F84\u952E\u4F7F\u7528\u539F\u59CB /api/... \u903B\u8F91\u8DEF\u5F84\uFF0C
|
|
1411
|
+
// Shell \u901A\u8FC7 /api/modules/<moduleId>/* \u7EDF\u4E00\u5206\u53D1\uFF08\u89C1 pactor.module.json \u7684 apiPrefixes\uFF09\u3002
|
|
1412
|
+
// handler \u53EA\u4F9D\u8D56 Web \u6807\u51C6 Request / Response\uFF0Ccontext.url \u4E3A\u903B\u8F91 URL\uFF08\u542B query\uFF09\u3002
|
|
1413
|
+
|
|
1414
|
+
export const handlers = {
|
|
1415
|
+
// '${prefix}/hello': {
|
|
1416
|
+
// GET: () => Response.json({ code: 0, data: { ok: true }, message: 'ok' }),
|
|
1417
|
+
// },
|
|
1418
|
+
};
|
|
1419
|
+
`;
|
|
1420
|
+
}
|
|
1421
|
+
function injectPackageJson(pkg, result, hasServerEntry) {
|
|
1422
|
+
const outDir = CONFIG_DEFAULTS.outDir;
|
|
1423
|
+
const files = Array.isArray(pkg.files) ? pkg.files : [];
|
|
1424
|
+
if (!files.includes(outDir)) {
|
|
1425
|
+
pkg.files = [...files, outDir];
|
|
1426
|
+
}
|
|
1427
|
+
const exportsMap = isRecord4(pkg.exports) ? { ...pkg.exports } : {};
|
|
1428
|
+
const wantedExports = {
|
|
1429
|
+
"./manifest": `./${outDir}/manifest.json`,
|
|
1430
|
+
"./client": `./${outDir}/client/index.js`,
|
|
1431
|
+
"./styles.css": `./${outDir}/client/index.css`,
|
|
1432
|
+
...hasServerEntry ? { "./server": `./${outDir}/server/index.mjs` } : {}
|
|
1433
|
+
};
|
|
1434
|
+
for (const [key, value] of Object.entries(wantedExports)) {
|
|
1435
|
+
if (exportsMap[key] === void 0) {
|
|
1436
|
+
exportsMap[key] = value;
|
|
1437
|
+
} else if (exportsMap[key] !== value) {
|
|
1438
|
+
result.warnings.push(`package.json exports["${key}"] \u5DF2\u5B58\u5728\u4E14\u4E0E\u5EFA\u8BAE\u503C\u4E0D\u540C\uFF0C\u672A\u8986\u76D6\uFF08\u5F53\u524D: ${JSON.stringify(exportsMap[key])}\uFF09`);
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
pkg.exports = exportsMap;
|
|
1442
|
+
const scripts = isRecord4(pkg.scripts) ? { ...pkg.scripts } : {};
|
|
1443
|
+
const wantedScripts = {
|
|
1444
|
+
"build:module": "pactor module build",
|
|
1445
|
+
"pack:module": "pactor module pack",
|
|
1446
|
+
"publish:module": "pactor module publish"
|
|
1447
|
+
};
|
|
1448
|
+
for (const [key, value] of Object.entries(wantedScripts)) {
|
|
1449
|
+
if (scripts[key] === void 0) {
|
|
1450
|
+
scripts[key] = value;
|
|
1451
|
+
} else if (scripts[key] !== value) {
|
|
1452
|
+
result.warnings.push(`package.json scripts["${key}"] \u5DF2\u5B58\u5728\uFF0C\u672A\u8986\u76D6\uFF08\u5F53\u524D: ${JSON.stringify(scripts[key])}\uFF09`);
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
pkg.scripts = scripts;
|
|
1456
|
+
const peers = isRecord4(pkg.peerDependencies) ? { ...pkg.peerDependencies } : {};
|
|
1457
|
+
const dependencies = isRecord4(pkg.dependencies) ? pkg.dependencies : {};
|
|
1458
|
+
const defaults = {
|
|
1459
|
+
react: "^18.0.0 || ^19.0.0",
|
|
1460
|
+
"react-dom": "^18.0.0 || ^19.0.0",
|
|
1461
|
+
next: "^14.0.0 || ^15.0.0",
|
|
1462
|
+
"pactor-app": "^1.54.0"
|
|
1463
|
+
};
|
|
1464
|
+
for (const [name, fallback] of Object.entries(defaults)) {
|
|
1465
|
+
if (peers[name] !== void 0) continue;
|
|
1466
|
+
const declared = dependencies[name];
|
|
1467
|
+
peers[name] = typeof declared === "string" && declared.length > 0 ? declared : fallback;
|
|
1468
|
+
}
|
|
1469
|
+
pkg.peerDependencies = peers;
|
|
1470
|
+
}
|
|
1471
|
+
function isRecord4(value) {
|
|
1472
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
// src/version.ts
|
|
1476
|
+
var import_node_fs12 = require("fs");
|
|
1477
|
+
var import_node_path12 = require("path");
|
|
1478
|
+
var SEMVER_RE = /^(\d+)\.(\d+)\.(\d+)(-[0-9A-Za-z.-]+)?$/;
|
|
1479
|
+
function bumpVersion(current, release) {
|
|
1480
|
+
if (release === "major" || release === "minor" || release === "patch") {
|
|
1481
|
+
const match = SEMVER_RE.exec(current);
|
|
1482
|
+
if (!match) {
|
|
1483
|
+
throw new ConfigError(`package.json \u7248\u672C\u53F7\u975E\u6CD5: ${current}\uFF08\u671F\u671B x.y.z\uFF09`);
|
|
1484
|
+
}
|
|
1485
|
+
const [, major, minor, patch] = match;
|
|
1486
|
+
if (release === "major") return `${Number(major) + 1}.0.0`;
|
|
1487
|
+
if (release === "minor") return `${major}.${Number(minor) + 1}.0`;
|
|
1488
|
+
return `${major}.${minor}.${Number(patch) + 1}`;
|
|
1489
|
+
}
|
|
1490
|
+
if (!SEMVER_RE.test(release)) {
|
|
1491
|
+
throw new ConfigError(
|
|
1492
|
+
`--bump \u53D6\u503C\u975E\u6CD5: ${release}\uFF08\u652F\u6301 patch | minor | major | \u663E\u5F0F\u7248\u672C\u53F7 x.y.z\uFF09`
|
|
1493
|
+
);
|
|
1494
|
+
}
|
|
1495
|
+
return release;
|
|
1496
|
+
}
|
|
1497
|
+
function bumpPackageVersion(options) {
|
|
1498
|
+
const dir = (0, import_node_path12.resolve)(options.dir ?? process.cwd());
|
|
1499
|
+
const pkgFile = (0, import_node_path12.resolve)(dir, "package.json");
|
|
1500
|
+
if (!(0, import_node_fs12.existsSync)(pkgFile)) {
|
|
1501
|
+
throw new ConfigError(`\u672A\u627E\u5230 package.json: ${dir}\uFF08\u8BF7\u5728\u76EE\u6807\u5DE5\u7A0B\u6839\u6267\u884C\uFF09`);
|
|
1502
|
+
}
|
|
1503
|
+
const pkg = JSON.parse((0, import_node_fs12.readFileSync)(pkgFile, "utf8"));
|
|
1504
|
+
const name = typeof pkg.name === "string" ? pkg.name : "(\u672A\u547D\u540D)";
|
|
1505
|
+
if (typeof pkg.version !== "string" || pkg.version === "") {
|
|
1506
|
+
throw new ConfigError(`package.json \u7F3A\u5C11 version \u5B57\u6BB5: ${pkgFile}`);
|
|
1507
|
+
}
|
|
1508
|
+
const from = pkg.version;
|
|
1509
|
+
const to = bumpVersion(from, options.release);
|
|
1510
|
+
pkg.version = to;
|
|
1511
|
+
(0, import_node_fs12.writeFileSync)(pkgFile, `${JSON.stringify(pkg, null, 2)}
|
|
1512
|
+
`, "utf8");
|
|
1513
|
+
return { name, from, to };
|
|
1514
|
+
}
|
|
1515
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1516
|
+
0 && (module.exports = {
|
|
1517
|
+
CLIENT_EXTERNALS,
|
|
1518
|
+
CLIENT_STYLES_ENTRY,
|
|
1519
|
+
CONFIG_DEFAULTS,
|
|
1520
|
+
CONFIG_FILE,
|
|
1521
|
+
ConfigError,
|
|
1522
|
+
DEFAULT_TARGET,
|
|
1523
|
+
INCLUDE_KEY,
|
|
1524
|
+
IncludeError,
|
|
1525
|
+
MODULE_ID_PREFIX,
|
|
1526
|
+
ModuleBuildError,
|
|
1527
|
+
ProfileError,
|
|
1528
|
+
SERVER_BUNDLE_FILE,
|
|
1529
|
+
SERVER_ENTRY,
|
|
1530
|
+
SERVER_EXTERNALS,
|
|
1531
|
+
ServerBundleError,
|
|
1532
|
+
buildModule,
|
|
1533
|
+
bumpPackageVersion,
|
|
1534
|
+
bumpVersion,
|
|
1535
|
+
bundleClient,
|
|
1536
|
+
bundleServer,
|
|
1537
|
+
collectModuleSource,
|
|
1538
|
+
compileTailwind,
|
|
1539
|
+
deriveApiPrefix,
|
|
1540
|
+
deriveModuleId,
|
|
1541
|
+
discoverActions,
|
|
1542
|
+
discoverComponents,
|
|
1543
|
+
emitDsl,
|
|
1544
|
+
emitModule,
|
|
1545
|
+
expandIncludes,
|
|
1546
|
+
getProfile,
|
|
1547
|
+
initModule,
|
|
1548
|
+
innospotsWebShellV1,
|
|
1549
|
+
innospotsWebShellV2,
|
|
1550
|
+
innospotsWebShellV3,
|
|
1551
|
+
listProfiles,
|
|
1552
|
+
loadModuleConfig,
|
|
1553
|
+
loadYamlExpanded,
|
|
1554
|
+
matchPathPattern,
|
|
1555
|
+
parseJsonc,
|
|
1556
|
+
parseYamlFile,
|
|
1557
|
+
readProjectVersion,
|
|
1558
|
+
renderClientEntry,
|
|
1559
|
+
renderModuleStyles,
|
|
1560
|
+
renderServerEntry,
|
|
1561
|
+
resolvePactorVersionRange,
|
|
1562
|
+
rewriteDslUrls,
|
|
1563
|
+
rewriteNavigationTo,
|
|
1564
|
+
transformSitemap,
|
|
1565
|
+
tsconfigAliases,
|
|
1566
|
+
validateModule,
|
|
1567
|
+
writeManifest
|
|
1568
|
+
});
|