@pactor-app/module-pack 0.0.0-stage → 1.55.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/dist/index.cjs ADDED
@@ -0,0 +1,1217 @@
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
+ CONFIG_DEFAULTS: () => CONFIG_DEFAULTS,
25
+ CONFIG_FILE: () => CONFIG_FILE,
26
+ ConfigError: () => ConfigError,
27
+ DEFAULT_TARGET: () => DEFAULT_TARGET,
28
+ INCLUDE_KEY: () => INCLUDE_KEY,
29
+ IncludeError: () => IncludeError,
30
+ ModuleBuildError: () => ModuleBuildError,
31
+ ProfileError: () => ProfileError,
32
+ buildModule: () => buildModule,
33
+ bundleClient: () => bundleClient,
34
+ collectModuleSource: () => collectModuleSource,
35
+ compileTailwind: () => compileTailwind,
36
+ deriveModuleId: () => deriveModuleId,
37
+ discoverActions: () => discoverActions,
38
+ discoverComponents: () => discoverComponents,
39
+ emitDsl: () => emitDsl,
40
+ emitModule: () => emitModule,
41
+ expandIncludes: () => expandIncludes,
42
+ getProfile: () => getProfile,
43
+ initModule: () => initModule,
44
+ innospotsWebShellV1: () => innospotsWebShellV1,
45
+ innospotsWebShellV2: () => innospotsWebShellV2,
46
+ listProfiles: () => listProfiles,
47
+ loadModuleConfig: () => loadModuleConfig,
48
+ loadYamlExpanded: () => loadYamlExpanded,
49
+ matchPathPattern: () => matchPathPattern,
50
+ parseJsonc: () => parseJsonc,
51
+ parseYamlFile: () => parseYamlFile,
52
+ readProjectVersion: () => readProjectVersion,
53
+ renderClientEntry: () => renderClientEntry,
54
+ resolvePactorVersionRange: () => resolvePactorVersionRange,
55
+ rewriteDslUrls: () => rewriteDslUrls,
56
+ rewriteNavigationTo: () => rewriteNavigationTo,
57
+ transformSitemap: () => transformSitemap,
58
+ tsconfigAliases: () => tsconfigAliases,
59
+ validateModule: () => validateModule,
60
+ writeManifest: () => writeManifest
61
+ });
62
+ module.exports = __toCommonJS(index_exports);
63
+
64
+ // src/build.ts
65
+ var import_node_fs9 = require("fs");
66
+ var import_node_path9 = require("path");
67
+
68
+ // src/bundle-client.ts
69
+ var import_node_fs = require("fs");
70
+ var import_node_path = require("path");
71
+ var import_esbuild = require("esbuild");
72
+ var CLIENT_EXTERNALS = [
73
+ "react",
74
+ "react-dom",
75
+ "react-dom/client",
76
+ "next",
77
+ "next/*",
78
+ "pactor-app",
79
+ "pactor-app/*",
80
+ "@pactor-app/*"
81
+ ];
82
+ function bundleClient(options) {
83
+ const entry = (0, import_node_path.join)(options.projectDir, options.clientEntry);
84
+ if (!(0, import_node_fs.existsSync)(entry)) {
85
+ return {
86
+ bundled: false,
87
+ css: false,
88
+ message: `client \u5165\u53E3\u4E0D\u5B58\u5728: ${options.clientEntry}\uFF08\u6309\u7EAF DSL \u6A21\u5757\u5904\u7406\uFF0C\u8DF3\u8FC7 client \u6253\u5305\uFF09`
89
+ };
90
+ }
91
+ (0, import_node_fs.mkdirSync)(options.outDir, { recursive: true });
92
+ (0, import_esbuild.buildSync)({
93
+ entryPoints: [entry],
94
+ bundle: true,
95
+ format: "esm",
96
+ platform: "browser",
97
+ outdir: options.outDir,
98
+ entryNames: "index",
99
+ sourcemap: true,
100
+ alias: tsconfigAliases(options.projectDir),
101
+ external: [...CLIENT_EXTERNALS],
102
+ logLevel: "silent"
103
+ });
104
+ return {
105
+ bundled: true,
106
+ css: (0, import_node_fs.existsSync)((0, import_node_path.join)(options.outDir, "index.css"))
107
+ };
108
+ }
109
+ function tsconfigAliases(projectDir) {
110
+ const file = (0, import_node_path.join)(projectDir, "tsconfig.json");
111
+ if (!(0, import_node_fs.existsSync)(file)) return {};
112
+ const compilerOptions = readTsconfig(file);
113
+ const paths = compilerOptions.paths ?? {};
114
+ const baseUrl = compilerOptions.baseUrl ?? ".";
115
+ const alias = {};
116
+ for (const [key, targets] of Object.entries(paths)) {
117
+ const target = targets[0];
118
+ if (typeof target !== "string") continue;
119
+ const name = key.endsWith("/*") ? key.slice(0, -2) : key;
120
+ const rel = target.endsWith("/*") ? target.slice(0, -2) : target;
121
+ alias[name] = (0, import_node_path.resolve)((0, import_node_path.dirname)(file), baseUrl, rel);
122
+ }
123
+ return alias;
124
+ }
125
+ function readTsconfig(file, seen = /* @__PURE__ */ new Set()) {
126
+ if (seen.has(file) || !(0, import_node_fs.existsSync)(file)) return {};
127
+ seen.add(file);
128
+ let raw;
129
+ try {
130
+ raw = parseJsonc((0, import_node_fs.readFileSync)(file, "utf8"));
131
+ } catch {
132
+ return {};
133
+ }
134
+ let base2 = {};
135
+ if (typeof raw.extends === "string" && raw.extends.startsWith(".")) {
136
+ base2 = readTsconfig((0, import_node_path.resolve)((0, import_node_path.dirname)(file), raw.extends), seen);
137
+ }
138
+ const own = raw.compilerOptions ?? {};
139
+ return {
140
+ baseUrl: own.baseUrl ?? base2.baseUrl,
141
+ paths: { ...base2.paths ?? {}, ...own.paths ?? {} }
142
+ };
143
+ }
144
+ function parseJsonc(text) {
145
+ let out = "";
146
+ let inString = false;
147
+ let i = 0;
148
+ while (i < text.length) {
149
+ const c = text[i];
150
+ if (inString) {
151
+ out += c;
152
+ if (c === "\\") {
153
+ out += text[i + 1] ?? "";
154
+ i += 2;
155
+ continue;
156
+ }
157
+ if (c === '"') inString = false;
158
+ i += 1;
159
+ continue;
160
+ }
161
+ if (c === '"') {
162
+ inString = true;
163
+ out += c;
164
+ i += 1;
165
+ continue;
166
+ }
167
+ if (c === "/" && text[i + 1] === "/") {
168
+ while (i < text.length && text[i] !== "\n") i += 1;
169
+ continue;
170
+ }
171
+ if (c === "/" && text[i + 1] === "*") {
172
+ i += 2;
173
+ while (i < text.length && !(text[i] === "*" && text[i + 1] === "/")) i += 1;
174
+ i += 2;
175
+ continue;
176
+ }
177
+ out += c;
178
+ i += 1;
179
+ }
180
+ return JSON.parse(out.replace(/,(\s*[}\]])/g, "$1"));
181
+ }
182
+
183
+ // src/collect.ts
184
+ var import_node_fs2 = require("fs");
185
+ var import_node_path2 = require("path");
186
+ function collectModuleSource(yamlRoot) {
187
+ const pages = /* @__PURE__ */ new Map();
188
+ const layouts = [];
189
+ const fragments = [];
190
+ const warnings = [];
191
+ const walk = (dir) => {
192
+ for (const entry of (0, import_node_fs2.readdirSync)(dir, { withFileTypes: true })) {
193
+ const full = (0, import_node_path2.join)(dir, entry.name);
194
+ if (entry.isDirectory()) {
195
+ walk(full);
196
+ continue;
197
+ }
198
+ if (!entry.name.endsWith(".yaml") || entry.name === "sitemap.yaml") {
199
+ continue;
200
+ }
201
+ const rel = (0, import_node_path2.relative)(yamlRoot, full);
202
+ if (entry.name.endsWith(".layout.yaml")) {
203
+ layouts.push(rel);
204
+ continue;
205
+ }
206
+ if (entry.name.endsWith(".fragment.yaml")) {
207
+ fragments.push(rel);
208
+ continue;
209
+ }
210
+ let id = entry.name.slice(0, -".yaml".length);
211
+ if (id.endsWith(".page")) {
212
+ id = id.slice(0, -".page".length);
213
+ }
214
+ if (pages.has(id)) {
215
+ warnings.push(`\u9875\u9762 id \u91CD\u590D: ${id}\uFF08${rel} \u8986\u76D6 ${pages.get(id)}\uFF09`);
216
+ }
217
+ pages.set(id, rel);
218
+ }
219
+ };
220
+ walk(yamlRoot);
221
+ layouts.sort();
222
+ fragments.sort();
223
+ return { yamlRoot, pages, layouts, fragments, warnings };
224
+ }
225
+
226
+ // src/compile-styles.ts
227
+ var import_node_child_process = require("child_process");
228
+ var import_node_fs3 = require("fs");
229
+ var import_node_os = require("os");
230
+ var import_node_path3 = require("path");
231
+ function compileTailwind(options) {
232
+ const warnings = [];
233
+ if (!options.tailwind.enabled) {
234
+ return { compiled: false, warnings };
235
+ }
236
+ const work = (0, import_node_fs3.mkdtempSync)((0, import_node_path3.join)((0, import_node_os.tmpdir)(), "pactor-tailwind-"));
237
+ try {
238
+ let input;
239
+ if (options.tailwind.input !== void 0) {
240
+ input = (0, import_node_path3.join)(options.projectDir, options.tailwind.input);
241
+ if (!(0, import_node_fs3.existsSync)(input)) {
242
+ warnings.push(`tailwind.input \u4E0D\u5B58\u5728: ${options.tailwind.input}\uFF0C\u8DF3\u8FC7\u9884\u7F16\u8BD1`);
243
+ return { compiled: false, warnings };
244
+ }
245
+ } else {
246
+ const scan = (options.tailwind.scan ?? options.scanDirs).map(
247
+ (dir) => `@source "${dir.replace(/\\/g, "/")}";`
248
+ );
249
+ input = (0, import_node_path3.join)(work, "input.css");
250
+ (0, import_node_fs3.writeFileSync)(input, `@import "tailwindcss";
251
+ ${scan.join("\n")}
252
+ `, "utf8");
253
+ }
254
+ const out = (0, import_node_path3.join)(work, "tailwind.css");
255
+ (0, import_node_child_process.execFileSync)(
256
+ "npx",
257
+ ["--no-install", "tailwindcss", "--input", input, "--output", out],
258
+ { cwd: options.projectDir, stdio: "pipe" }
259
+ );
260
+ if ((0, import_node_fs3.existsSync)(out)) {
261
+ const css = (0, import_node_fs3.readFileSync)(out, "utf8");
262
+ if (css.trim().length > 0) {
263
+ (0, import_node_fs3.mkdirSync)((0, import_node_path3.dirname)(options.cssFile), { recursive: true });
264
+ (0, import_node_fs3.appendFileSync)(
265
+ options.cssFile,
266
+ `
267
+ /* tailwind utilities\uFF08pactor module build \u9884\u7F16\u8BD1\uFF09 */
268
+ ${css}`,
269
+ "utf8"
270
+ );
271
+ return { compiled: true, warnings };
272
+ }
273
+ }
274
+ warnings.push("tailwind \u9884\u7F16\u8BD1\u4EA7\u7269\u4E3A\u7A7A\uFF0C\u5DF2\u8DF3\u8FC7");
275
+ return { compiled: false, warnings };
276
+ } catch (error) {
277
+ const firstLine = error.message.split("\n")[0] ?? "\u672A\u77E5\u9519\u8BEF";
278
+ warnings.push(`tailwind \u4E0D\u53EF\u7528\u6216\u7F16\u8BD1\u5931\u8D25\uFF0C\u5DF2\u964D\u7EA7\u8DF3\u8FC7\u9884\u7F16\u8BD1\uFF08${firstLine}\uFF09`);
279
+ return { compiled: false, warnings };
280
+ } finally {
281
+ (0, import_node_fs3.rmSync)(work, { recursive: true, force: true });
282
+ }
283
+ }
284
+
285
+ // src/config.ts
286
+ var import_node_fs4 = require("fs");
287
+ var import_node_path4 = require("path");
288
+
289
+ // src/profiles/innospots-web-shell.ts
290
+ var base = {
291
+ name: "innospots-web-shell",
292
+ inlineStringLayouts: true,
293
+ stripMenuPaths: true,
294
+ rewriteNavigation: { basePath: true, excludeApiUrls: true },
295
+ rewriteAssetUrls: (id, version) => `/modules/${id}/${version}/`,
296
+ forbidRootBasePath: true
297
+ };
298
+ var innospotsWebShellV1 = {
299
+ ...base,
300
+ version: 1,
301
+ forceInlinePages: true
302
+ };
303
+ var innospotsWebShellV2 = {
304
+ ...base,
305
+ version: 2,
306
+ forceInlinePages: false
307
+ };
308
+
309
+ // src/profiles/index.ts
310
+ var ProfileError = class extends Error {
311
+ };
312
+ var registry = /* @__PURE__ */ new Map([
313
+ [`${innospotsWebShellV1.name}@${innospotsWebShellV1.version}`, innospotsWebShellV1],
314
+ [`${innospotsWebShellV2.name}@${innospotsWebShellV2.version}`, innospotsWebShellV2]
315
+ ]);
316
+ var DEFAULT_TARGET = `${innospotsWebShellV2.name}@${innospotsWebShellV2.version}`;
317
+ function listProfiles() {
318
+ return [...registry.keys()];
319
+ }
320
+ function getProfile(id) {
321
+ const profile = registry.get(id);
322
+ if (!profile) {
323
+ throw new ProfileError(`\u672A\u77E5 target profile: ${id}\uFF08\u53EF\u7528: ${listProfiles().join(", ")}\uFF09`);
324
+ }
325
+ return profile;
326
+ }
327
+
328
+ // src/config.ts
329
+ var ConfigError = class extends Error {
330
+ };
331
+ var CONFIG_FILE = "pactor.module.json";
332
+ var CONFIG_DEFAULTS = {
333
+ yamlRoot: "src/server/yaml",
334
+ clientEntry: "module/client.ts",
335
+ publicDir: "public",
336
+ target: DEFAULT_TARGET,
337
+ outDir: "dist-module"
338
+ };
339
+ function loadModuleConfig(projectDir, configPath) {
340
+ const file = configPath ? (0, import_node_path4.resolve)(projectDir, configPath) : (0, import_node_path4.join)(projectDir, CONFIG_FILE);
341
+ if (!(0, import_node_fs4.existsSync)(file)) {
342
+ throw new ConfigError(`\u7F3A\u5C11\u914D\u7F6E\u6587\u4EF6: ${file}\uFF08\u53EF\u5148\u6267\u884C pactor module init \u751F\u6210\uFF09`);
343
+ }
344
+ let raw;
345
+ try {
346
+ raw = JSON.parse((0, import_node_fs4.readFileSync)(file, "utf8"));
347
+ } catch (error) {
348
+ throw new ConfigError(`\u914D\u7F6E\u89E3\u6790\u5931\u8D25: ${file}: ${error.message}`);
349
+ }
350
+ if (!isRecord(raw)) {
351
+ throw new ConfigError(`${file}: \u914D\u7F6E\u5FC5\u987B\u662F JSON \u5BF9\u8C61`);
352
+ }
353
+ const id = readString(raw, "id", file);
354
+ if (!id) {
355
+ throw new ConfigError(`${file}: \u7F3A\u5C11\u5FC5\u586B\u5B57\u6BB5 id\uFF08\u6A21\u5757 id\uFF0C\u8FDB\u5165 globalPageId \u524D\u7F00\uFF09`);
356
+ }
357
+ const name = readString(raw, "name", file) ?? id;
358
+ let basePath = readString(raw, "basePath", file) ?? `/${id}`;
359
+ if (!basePath.startsWith("/")) basePath = `/${basePath}`;
360
+ if (basePath.length > 1 && basePath.endsWith("/")) basePath = basePath.slice(0, -1);
361
+ const actions = raw.actions === void 0 ? [] : readStringArray(raw.actions, "actions", file);
362
+ const demo = isRecord(raw.demo) ? raw.demo : {};
363
+ const tailwind = isRecord(raw.tailwind) ? raw.tailwind : {};
364
+ const rewrite = isRecord(raw.rewrite) ? raw.rewrite : {};
365
+ return {
366
+ id,
367
+ name,
368
+ basePath,
369
+ yamlRoot: readString(raw, "yamlRoot", file) ?? CONFIG_DEFAULTS.yamlRoot,
370
+ clientEntry: readString(raw, "clientEntry", file) ?? CONFIG_DEFAULTS.clientEntry,
371
+ actions,
372
+ publicDir: readString(raw, "publicDir", file) ?? CONFIG_DEFAULTS.publicDir,
373
+ target: readString(raw, "target", file) ?? CONFIG_DEFAULTS.target,
374
+ demo: { public: readBoolean(demo, "public", file, "demo") ?? false },
375
+ tailwind: {
376
+ enabled: readBoolean(tailwind, "enabled", file, "tailwind") ?? false,
377
+ input: readString(tailwind, "input", file, "tailwind"),
378
+ scan: tailwind.scan === void 0 ? void 0 : readStringArray(tailwind.scan, "tailwind.scan", file)
379
+ },
380
+ rewrite: {
381
+ absoluteApiToRelative: readBoolean(rewrite, "absoluteApiToRelative", file, "rewrite") ?? true
382
+ },
383
+ outDir: readString(raw, "outDir", file) ?? CONFIG_DEFAULTS.outDir
384
+ };
385
+ }
386
+ function isRecord(value) {
387
+ return value !== null && typeof value === "object" && !Array.isArray(value);
388
+ }
389
+ function readString(record, key, file, parent) {
390
+ const value = record[key];
391
+ if (value === void 0) return void 0;
392
+ const label = parent ? `${parent}.${key}` : key;
393
+ if (typeof value !== "string" || value.length === 0) {
394
+ throw new ConfigError(`${file}: ${label} \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32`);
395
+ }
396
+ return value;
397
+ }
398
+ function readBoolean(record, key, file, parent) {
399
+ const value = record[key];
400
+ if (value === void 0) return void 0;
401
+ if (typeof value !== "boolean") {
402
+ throw new ConfigError(`${file}: ${parent}.${key} \u5FC5\u987B\u662F\u5E03\u5C14\u503C`);
403
+ }
404
+ return value;
405
+ }
406
+ function readStringArray(value, label, file) {
407
+ if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) {
408
+ throw new ConfigError(`${file}: ${label} \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6570\u7EC4`);
409
+ }
410
+ return value;
411
+ }
412
+
413
+ // src/emit-manifest.ts
414
+ var import_node_crypto = require("crypto");
415
+ var import_node_fs5 = require("fs");
416
+ var import_node_module = require("module");
417
+ var import_node_path5 = require("path");
418
+ var import_yaml = require("yaml");
419
+ function emitModule(input) {
420
+ const dslResult = emitDsl(input);
421
+ const manifest = writeManifest(input);
422
+ return { ...dslResult, manifest };
423
+ }
424
+ function emitDsl(input) {
425
+ const { config, projectDir, outDir, site, pages } = input;
426
+ const dslDir = (0, import_node_path5.join)(outDir, "dsl");
427
+ (0, import_node_fs5.mkdirSync)(dslDir, { recursive: true });
428
+ (0, import_node_fs5.writeFileSync)((0, import_node_path5.join)(dslDir, "sitemap.yaml"), (0, import_yaml.stringify)(site, { lineWidth: 0 }), "utf8");
429
+ for (const [id, dsl] of pages) {
430
+ (0, import_node_fs5.writeFileSync)((0, import_node_path5.join)(dslDir, `${id}.yaml`), (0, import_yaml.stringify)(dsl, { lineWidth: 0 }), "utf8");
431
+ }
432
+ const publicDir = (0, import_node_path5.join)(projectDir, config.publicDir);
433
+ const assetsDir = (0, import_node_path5.join)(outDir, "assets");
434
+ if ((0, import_node_fs5.existsSync)(publicDir)) {
435
+ (0, import_node_fs5.cpSync)(publicDir, assetsDir, { recursive: true });
436
+ } else {
437
+ (0, import_node_fs5.mkdirSync)(assetsDir, { recursive: true });
438
+ }
439
+ const assets = hashAssets(assetsDir, assetsDir);
440
+ (0, import_node_fs5.writeFileSync)(
441
+ (0, import_node_path5.join)(outDir, "module-assets.json"),
442
+ `${JSON.stringify({ module: config.id, assets }, null, 2)}
443
+ `,
444
+ "utf8"
445
+ );
446
+ return { assetCount: assets.length };
447
+ }
448
+ function writeManifest(input) {
449
+ const { config, projectDir, outDir } = input;
450
+ const version = readProjectVersion(projectDir);
451
+ const manifest = {
452
+ schemaVersion: "1",
453
+ id: config.id,
454
+ name: config.name,
455
+ version,
456
+ pactorVersionRange: resolvePactorVersionRange(projectDir, input.warnings),
457
+ basePath: config.basePath,
458
+ sitemap: "dsl/sitemap.yaml",
459
+ dslRoot: "dsl",
460
+ assetsRoot: "assets",
461
+ ...input.clientEntry ? { clientEntry: input.clientEntry } : {},
462
+ ...input.styles ? { styles: input.styles } : {}
463
+ };
464
+ (0, import_node_fs5.writeFileSync)(
465
+ (0, import_node_path5.join)(outDir, "manifest.json"),
466
+ `${JSON.stringify(manifest, null, 2)}
467
+ `,
468
+ "utf8"
469
+ );
470
+ return manifest;
471
+ }
472
+ function readProjectVersion(projectDir) {
473
+ const pkgFile = (0, import_node_path5.join)(projectDir, "package.json");
474
+ if (!(0, import_node_fs5.existsSync)(pkgFile)) return "0.0.0";
475
+ try {
476
+ const pkg = JSON.parse((0, import_node_fs5.readFileSync)(pkgFile, "utf8"));
477
+ return typeof pkg.version === "string" && pkg.version.length > 0 ? pkg.version : "0.0.0";
478
+ } catch {
479
+ return "0.0.0";
480
+ }
481
+ }
482
+ function resolvePactorVersionRange(projectDir, warnings) {
483
+ try {
484
+ const require2 = (0, import_node_module.createRequire)((0, import_node_path5.join)(projectDir, "package.json"));
485
+ for (const name of ["pactor-app/package.json", "@pactor-app/app/package.json"]) {
486
+ try {
487
+ const pkgFile = require2.resolve(name);
488
+ const pkg2 = JSON.parse((0, import_node_fs5.readFileSync)(pkgFile, "utf8"));
489
+ if (typeof pkg2.version === "string" && pkg2.version.length > 0) {
490
+ return `^${pkg2.version}`;
491
+ }
492
+ } catch {
493
+ }
494
+ }
495
+ const pkg = JSON.parse((0, import_node_fs5.readFileSync)((0, import_node_path5.join)(projectDir, "package.json"), "utf8"));
496
+ for (const section of ["dependencies", "peerDependencies", "devDependencies"]) {
497
+ const range = pkg[section]?.["pactor-app"];
498
+ if (typeof range === "string" && range.length > 0) {
499
+ return range;
500
+ }
501
+ }
502
+ } catch {
503
+ }
504
+ warnings.push("\u672A\u80FD\u63A8\u5BFC\u76EE\u6807\u5DE5\u7A0B\u7684 pactor-app \u7248\u672C\uFF0CpactorVersionRange \u56DE\u9000\u4E3A ^1.54.0");
505
+ return "^1.54.0";
506
+ }
507
+ function hashAssets(dir, root) {
508
+ const entries = [];
509
+ if (!(0, import_node_fs5.existsSync)(dir)) return entries;
510
+ for (const entry of (0, import_node_fs5.readdirSync)(dir, { withFileTypes: true }).sort(
511
+ (a, b) => a.name.localeCompare(b.name)
512
+ )) {
513
+ const full = (0, import_node_path5.join)(dir, entry.name);
514
+ if (entry.isDirectory()) {
515
+ entries.push(...hashAssets(full, root));
516
+ continue;
517
+ }
518
+ if (!entry.isFile()) continue;
519
+ const content = (0, import_node_fs5.readFileSync)(full);
520
+ entries.push({
521
+ path: full.slice(root.length + 1).split("\\").join("/"),
522
+ sha256: (0, import_node_crypto.createHash)("sha256").update(content).digest("hex"),
523
+ size: (0, import_node_fs5.statSync)(full).size
524
+ });
525
+ }
526
+ return entries;
527
+ }
528
+
529
+ // src/expand-include.ts
530
+ var import_node_fs6 = require("fs");
531
+ var import_node_path6 = require("path");
532
+ var import_yaml2 = require("yaml");
533
+ var INCLUDE_KEY = "$include";
534
+ var IncludeError = class extends Error {
535
+ };
536
+ function parseYamlFile(file) {
537
+ const doc = (0, import_yaml2.parseDocument)((0, import_node_fs6.readFileSync)(file, "utf8"));
538
+ if (doc.errors.length > 0) {
539
+ throw new IncludeError(
540
+ `${file}: ${doc.errors.map((error) => error.message).join("; ")}`
541
+ );
542
+ }
543
+ return doc.toJS();
544
+ }
545
+ function loadYamlExpanded(yamlRoot, relPath, stack = []) {
546
+ if (stack.includes(relPath)) {
547
+ throw new IncludeError(`\u5FAA\u73AF\u5F15\u7528: ${[...stack, relPath].join(" -> ")}`);
548
+ }
549
+ const value = parseYamlFile((0, import_node_path6.join)(yamlRoot, relPath));
550
+ return expandIncludes(value, { yamlRoot, current: relPath, stack: [...stack, relPath] });
551
+ }
552
+ function expandIncludes(value, ctx) {
553
+ if (Array.isArray(value)) {
554
+ return value.map((item) => expandIncludes(item, ctx));
555
+ }
556
+ if (value === null || typeof value !== "object") {
557
+ return value;
558
+ }
559
+ const record = value;
560
+ if (INCLUDE_KEY in record) {
561
+ if (Object.keys(record).length > 1) {
562
+ throw new IncludeError(`${ctx.current}: $include \u4E0D\u80FD\u4E0E\u5176\u4ED6\u5B57\u6BB5\u5E76\u5217`);
563
+ }
564
+ const target = record[INCLUDE_KEY];
565
+ if (typeof target !== "string") {
566
+ throw new IncludeError(`${ctx.current}: $include \u5FC5\u987B\u662F\u5B57\u7B26\u4E32`);
567
+ }
568
+ return loadYamlExpanded(ctx.yamlRoot, target, ctx.stack);
569
+ }
570
+ return Object.fromEntries(
571
+ Object.entries(record).map(([key, item]) => [key, expandIncludes(item, ctx)])
572
+ );
573
+ }
574
+
575
+ // src/rewrite-urls.ts
576
+ var import_node_fs7 = require("fs");
577
+ var import_node_path7 = require("path");
578
+ var NAVIGATION_ACTIONS = /* @__PURE__ */ new Set(["navigate", "app.reload"]);
579
+ var ABSOLUTE_API_RE = /^https?:\/\/[^/]+(\/api\/.+)$/;
580
+ function rewriteDslUrls(value, ctx) {
581
+ const warnings = [];
582
+ const walk = (node) => {
583
+ if (typeof node === "string") {
584
+ return rewriteString(node, ctx, warnings);
585
+ }
586
+ if (Array.isArray(node)) {
587
+ return node.map((item) => walk(item));
588
+ }
589
+ if (node === null || typeof node !== "object") {
590
+ return node;
591
+ }
592
+ const record = node;
593
+ const next = {};
594
+ for (const [key, item] of Object.entries(record)) {
595
+ next[key] = walk(item);
596
+ }
597
+ if (ctx.rewriteNavigation && isNavigationAction(record)) {
598
+ const params = next.params;
599
+ if (isRecord2(params) && typeof params.to === "string") {
600
+ const rewritten = rewriteNavigationTo(params.to, ctx);
601
+ if (rewritten !== void 0) {
602
+ params.to = rewritten;
603
+ }
604
+ }
605
+ }
606
+ return next;
607
+ };
608
+ return { value: walk(value), warnings };
609
+ }
610
+ function isNavigationAction(record) {
611
+ return typeof record.action === "string" && NAVIGATION_ACTIONS.has(record.action);
612
+ }
613
+ function rewriteNavigationTo(to, ctx) {
614
+ if (!to.startsWith("/") || to.startsWith("//")) return void 0;
615
+ if (to.startsWith("/api/")) return void 0;
616
+ if (to === ctx.basePath || to.startsWith(`${ctx.basePath}/`)) return void 0;
617
+ const hit = [ctx.loginPath, ...ctx.pagePaths].some(
618
+ (pattern) => pattern.length > 0 && matchPathPattern(pattern, to)
619
+ );
620
+ if (!hit) return void 0;
621
+ return `${ctx.basePath}${to}`;
622
+ }
623
+ function matchPathPattern(pattern, value) {
624
+ const patternSegs = pattern.split("?")[0].split("/").filter(Boolean);
625
+ const valueSegs = value.split("?")[0].split("/").filter(Boolean);
626
+ if (patternSegs.length !== valueSegs.length) return false;
627
+ return patternSegs.every((seg, index) => seg.startsWith(":") || seg === valueSegs[index]);
628
+ }
629
+ function rewriteString(value, ctx, warnings) {
630
+ const absoluteApi = ABSOLUTE_API_RE.exec(value);
631
+ if (absoluteApi) {
632
+ warnings.push(
633
+ `\u7EDD\u5BF9 API \u5730\u5740: ${value}${ctx.absoluteApiToRelative ? "\uFF08\u5DF2\u91CD\u5199\u4E3A\u76F8\u5BF9\u8DEF\u5F84\uFF0C\u9700\u5E95\u5EA7 BFF/\u4EE3\u7406\u627F\u63A5\uFF09" : ""}`
634
+ );
635
+ return ctx.absoluteApiToRelative ? absoluteApi[1] : value;
636
+ }
637
+ if (!ctx.rewriteAssets) return value;
638
+ if (!value.startsWith("/") || value.startsWith("//")) return value;
639
+ if (value.startsWith("/api/")) return value;
640
+ if (value === ctx.basePath || value.startsWith(`${ctx.basePath}/`)) return value;
641
+ const isPagePath = [ctx.loginPath, ...ctx.pagePaths].some(
642
+ (pattern) => pattern.length > 0 && matchPathPattern(pattern, value)
643
+ );
644
+ if (isPagePath) return value;
645
+ if (!isPublicFile(ctx.publicDir, value)) return value;
646
+ return `${ctx.assetPrefix}${value}`;
647
+ }
648
+ function isPublicFile(publicDir, urlPath) {
649
+ const file = (0, import_node_path7.join)(publicDir, urlPath);
650
+ try {
651
+ return (0, import_node_fs7.existsSync)(file) && (0, import_node_fs7.statSync)(file).isFile();
652
+ } catch {
653
+ return false;
654
+ }
655
+ }
656
+ function isRecord2(value) {
657
+ return value !== null && typeof value === "object" && !Array.isArray(value);
658
+ }
659
+
660
+ // src/transform-sitemap.ts
661
+ function transformSitemap(site, options) {
662
+ const { profile, demoPublic, loadLayout } = options;
663
+ const next = { ...site };
664
+ const rawLayouts = isRecord3(site.layouts) ? site.layouts : {};
665
+ const layouts = {};
666
+ for (const [name, def] of Object.entries(rawLayouts)) {
667
+ layouts[name] = typeof def === "string" && profile.inlineStringLayouts ? loadLayout(def) : def;
668
+ }
669
+ next.layouts = layouts;
670
+ const rawPages = Array.isArray(site.pages) ? site.pages : [];
671
+ next.pages = rawPages.map((page) => {
672
+ const nextPage = { ...page };
673
+ if (profile.forceInlinePages) {
674
+ delete nextPage.lazy;
675
+ }
676
+ if (demoPublic) {
677
+ nextPage.public = true;
678
+ }
679
+ return nextPage;
680
+ });
681
+ const rawMenus = Array.isArray(site.menus) ? site.menus : [];
682
+ const transformMenu = (menu) => {
683
+ const nextMenu = { ...menu };
684
+ if (profile.stripMenuPaths) {
685
+ delete nextMenu.path;
686
+ }
687
+ if (demoPublic) {
688
+ nextMenu.public = true;
689
+ }
690
+ if (Array.isArray(nextMenu.children)) {
691
+ nextMenu.children = nextMenu.children.map(
692
+ (child) => isRecord3(child) ? transformMenu(child) : child
693
+ );
694
+ }
695
+ return nextMenu;
696
+ };
697
+ next.menus = rawMenus.map((menu) => isRecord3(menu) ? transformMenu(menu) : menu);
698
+ return {
699
+ site: next,
700
+ layoutCount: Object.keys(layouts).length,
701
+ pageCount: rawPages.length,
702
+ menuCount: rawMenus.length
703
+ };
704
+ }
705
+ function isRecord3(value) {
706
+ return value !== null && typeof value === "object" && !Array.isArray(value);
707
+ }
708
+
709
+ // src/validate.ts
710
+ var import_node_fs8 = require("fs");
711
+ var import_node_path8 = require("path");
712
+ var import_yaml3 = require("yaml");
713
+ var REQUIRED_MANIFEST_FIELDS = [
714
+ "schemaVersion",
715
+ "id",
716
+ "name",
717
+ "version",
718
+ "pactorVersionRange",
719
+ "basePath",
720
+ "sitemap",
721
+ "dslRoot",
722
+ "assetsRoot"
723
+ ];
724
+ function validateModule(options = {}) {
725
+ const projectDir = (0, import_node_path8.resolve)(options.dir ?? process.cwd());
726
+ const errors = [];
727
+ const warnings = [];
728
+ let config;
729
+ if (options.moduleDir === void 0) {
730
+ try {
731
+ config = loadModuleConfig(projectDir, options.config);
732
+ } catch (error) {
733
+ errors.push(error.message);
734
+ return { ok: false, errors, warnings };
735
+ }
736
+ } else {
737
+ try {
738
+ config = loadModuleConfig(projectDir, options.config);
739
+ } catch {
740
+ config = void 0;
741
+ }
742
+ }
743
+ const moduleDir = options.moduleDir ?? (0, import_node_path8.join)(projectDir, config?.outDir ?? CONFIG_DEFAULTS.outDir);
744
+ const manifestFile = (0, import_node_path8.join)(moduleDir, "manifest.json");
745
+ if (!(0, import_node_fs8.existsSync)(manifestFile)) {
746
+ errors.push(`\u4EA7\u7269\u4E0D\u5B58\u5728: ${manifestFile}\uFF08\u5148\u6267\u884C pactor module build\uFF09`);
747
+ return { ok: false, errors, warnings };
748
+ }
749
+ let manifest;
750
+ try {
751
+ manifest = JSON.parse((0, import_node_fs8.readFileSync)(manifestFile, "utf8"));
752
+ } catch (error) {
753
+ errors.push(`manifest.json \u89E3\u6790\u5931\u8D25: ${error.message}`);
754
+ return { ok: false, errors, warnings };
755
+ }
756
+ for (const field of REQUIRED_MANIFEST_FIELDS) {
757
+ if (!(field in manifest)) {
758
+ errors.push(`manifest \u7F3A\u5C11\u5B57\u6BB5: ${field}`);
759
+ }
760
+ }
761
+ if (manifest.schemaVersion !== "1") {
762
+ errors.push(`manifest.schemaVersion \u5FC5\u987B\u4E3A "1"\uFF08\u5F53\u524D: ${JSON.stringify(manifest.schemaVersion)}\uFF09`);
763
+ }
764
+ const dslRoot = typeof manifest.dslRoot === "string" ? manifest.dslRoot : "dsl";
765
+ const sitemapRel = typeof manifest.sitemap === "string" ? manifest.sitemap : "dsl/sitemap.yaml";
766
+ const sitemapFile = (0, import_node_path8.join)(moduleDir, sitemapRel);
767
+ if (!(0, import_node_fs8.existsSync)(sitemapFile)) {
768
+ errors.push(`sitemap \u4E0D\u5B58\u5728: ${sitemapRel}`);
769
+ } else {
770
+ const doc = (0, import_yaml3.parseDocument)((0, import_node_fs8.readFileSync)(sitemapFile, "utf8"));
771
+ if (doc.errors.length > 0) {
772
+ errors.push(`sitemap YAML \u89E3\u6790\u5931\u8D25: ${doc.errors.map((e) => e.message).join("; ")}`);
773
+ } else {
774
+ const site = doc.toJS();
775
+ const pages = Array.isArray(site.pages) ? site.pages : [];
776
+ for (const page of pages) {
777
+ const id = page.id;
778
+ if (typeof id !== "string") {
779
+ errors.push("sitemap.pages \u5B58\u5728\u7F3A\u5C11 id \u7684\u9875\u9762\u9879");
780
+ continue;
781
+ }
782
+ if (findPageDslFile((0, import_node_path8.join)(moduleDir, dslRoot), id) === null) {
783
+ errors.push(`\u9875\u9762 ${id} \u7F3A\u5C11 DSL \u6587\u4EF6\uFF08${dslRoot}/ \u4E0B\u672A\u627E\u5230 ${id}.yaml\uFF09`);
784
+ }
785
+ }
786
+ const layouts = site.layouts;
787
+ if (layouts !== null && typeof layouts === "object" && !Array.isArray(layouts)) {
788
+ for (const [name, def] of Object.entries(layouts)) {
789
+ if (typeof def === "string") {
790
+ errors.push(`\u5E03\u5C40 ${name} \u4ECD\u662F\u5B57\u7B26\u4E32\u5F15\u7528\uFF08target \u8981\u6C42\u5185\u8054\u4E3A\u5BF9\u8C61\uFF09`);
791
+ }
792
+ }
793
+ }
794
+ }
795
+ }
796
+ const dslDir = (0, import_node_path8.join)(moduleDir, dslRoot);
797
+ for (const file of listFiles(dslDir)) {
798
+ if ((0, import_node_fs8.readFileSync)(file, "utf8").includes(INCLUDE_KEY)) {
799
+ errors.push(`$include \u6B8B\u7559: ${(0, import_node_path8.relative)(moduleDir, file)}`);
800
+ }
801
+ }
802
+ if (typeof manifest.clientEntry === "string") {
803
+ const clientFile = (0, import_node_path8.join)(moduleDir, manifest.clientEntry);
804
+ if (!(0, import_node_fs8.existsSync)(clientFile)) {
805
+ errors.push(`client bundle \u4E0D\u5B58\u5728: ${manifest.clientEntry}`);
806
+ } else {
807
+ const text = (0, import_node_fs8.readFileSync)(clientFile, "utf8");
808
+ if (/\bvar React\b|react\.production\.min|__REACT_DEVTOOLS_GLOBAL_HOOK__/.test(text)) {
809
+ errors.push("client bundle \u7591\u4F3C\u5185\u5D4C react\uFF08react \u5FC5\u987B\u4FDD\u6301 external\uFF0C\u907F\u514D\u53CC\u5B9E\u4F8B\uFF09");
810
+ }
811
+ if (/node_modules\/@pactor-app\//.test(text) || /node_modules\/pactor-app\//.test(text)) {
812
+ errors.push("client bundle \u7591\u4F3C\u5185\u5D4C pactor \u8FD0\u884C\u65F6\u4EE3\u7801\uFF08@pactor-app/* \u5FC5\u987B\u4FDD\u6301 external\uFF09");
813
+ }
814
+ const sizeKb = Math.round((0, import_node_fs8.statSync)(clientFile).size / 1024);
815
+ if (sizeKb > 512) {
816
+ warnings.push(`client bundle \u4F53\u79EF\u8F83\u5927\uFF08${sizeKb}KB\uFF09\uFF0C\u8BF7\u786E\u8BA4 react / pactor \u5DF2 external`);
817
+ }
818
+ }
819
+ }
820
+ const pkgFile = (0, import_node_path8.join)(projectDir, "package.json");
821
+ if ((0, import_node_fs8.existsSync)(pkgFile)) {
822
+ try {
823
+ const pkg = JSON.parse((0, import_node_fs8.readFileSync)(pkgFile, "utf8"));
824
+ const exportsMap = pkg.exports ?? {};
825
+ if (exportsMap["./manifest"] === void 0) {
826
+ errors.push('package.json exports \u7F3A\u5C11 "./manifest"\uFF08Shell \u88C5\u914D\u5668\u7ECF require.resolve("<pkg>/manifest") \u5B9A\u4F4D\uFF09');
827
+ }
828
+ if (typeof manifest.clientEntry === "string" && exportsMap["./client"] === void 0) {
829
+ errors.push('package.json exports \u7F3A\u5C11 "./client"\uFF08client-registry \u9759\u6001 import "<pkg>/client"\uFF09');
830
+ }
831
+ if (typeof pkg.version === "string" && typeof manifest.version === "string" && pkg.version !== manifest.version) {
832
+ warnings.push(
833
+ `manifest.version (${manifest.version}) \u4E0E package.json version (${pkg.version}) \u4E0D\u4E00\u81F4\uFF0C\u8BF7\u91CD\u65B0 build`
834
+ );
835
+ }
836
+ } catch {
837
+ warnings.push("package.json \u89E3\u6790\u5931\u8D25\uFF0C\u8DF3\u8FC7 exports \u68C0\u67E5");
838
+ }
839
+ } else {
840
+ warnings.push("\u672A\u627E\u5230 package.json\uFF0C\u8DF3\u8FC7 exports \u68C0\u67E5");
841
+ }
842
+ return { ok: errors.length === 0, errors, warnings };
843
+ }
844
+ function findPageDslFile(dslRootDir, pageId) {
845
+ if (!(0, import_node_fs8.existsSync)(dslRootDir)) return null;
846
+ const queue = [dslRootDir];
847
+ while (queue.length > 0) {
848
+ const dir = queue.pop();
849
+ for (const entry of (0, import_node_fs8.readdirSync)(dir, { withFileTypes: true })) {
850
+ const full = (0, import_node_path8.join)(dir, entry.name);
851
+ if (entry.isDirectory()) {
852
+ queue.push(full);
853
+ continue;
854
+ }
855
+ if (entry.name === `${pageId}.yaml`) return full;
856
+ }
857
+ }
858
+ return null;
859
+ }
860
+ function listFiles(dir) {
861
+ if (!(0, import_node_fs8.existsSync)(dir)) return [];
862
+ const files = [];
863
+ const walk = (target) => {
864
+ for (const entry of (0, import_node_fs8.readdirSync)(target, { withFileTypes: true })) {
865
+ const full = (0, import_node_path8.join)(target, entry.name);
866
+ if (entry.isDirectory()) {
867
+ walk(full);
868
+ } else if (entry.isFile()) {
869
+ files.push(full);
870
+ }
871
+ }
872
+ };
873
+ walk(dir);
874
+ return files;
875
+ }
876
+
877
+ // src/build.ts
878
+ var ModuleBuildError = class extends Error {
879
+ constructor(message, errors) {
880
+ super(message);
881
+ this.errors = errors;
882
+ }
883
+ };
884
+ function buildModule(options = {}) {
885
+ const projectDir = (0, import_node_path9.resolve)(options.dir ?? process.cwd());
886
+ const config = loadModuleConfig(projectDir, options.config);
887
+ const profile = getProfile(config.target);
888
+ if (profile.forbidRootBasePath && config.basePath === "/") {
889
+ throw new ModuleBuildError(
890
+ `target ${config.target} \u7981\u6B62 basePath: "/"\uFF08Shell joinPublicPath \u4F1A\u4EA7\u751F "//login" \u8FD9\u7C7B\u574F\u8DEF\u5F84\uFF09`,
891
+ [`basePath: "/" \u4E0E profile ${config.target} \u7684 forbidRootBasePath \u51B2\u7A81\uFF0C\u8BF7\u6539\u7528\u5982 /${config.id} \u7684\u524D\u7F00`]
892
+ );
893
+ }
894
+ const yamlRoot = (0, import_node_path9.join)(projectDir, config.yamlRoot);
895
+ if (!(0, import_node_fs9.existsSync)(yamlRoot)) {
896
+ throw new ModuleBuildError(`yamlRoot \u4E0D\u5B58\u5728: ${config.yamlRoot}`, [
897
+ `yamlRoot \u4E0D\u5B58\u5728: ${yamlRoot}`
898
+ ]);
899
+ }
900
+ const warnings = [];
901
+ const collected = collectModuleSource(yamlRoot);
902
+ warnings.push(...collected.warnings);
903
+ let site;
904
+ try {
905
+ site = loadYamlExpanded(yamlRoot, "sitemap.yaml");
906
+ } catch (error) {
907
+ const message = `sitemap \u5C55\u5F00\u5931\u8D25: ${error.message}`;
908
+ throw new ModuleBuildError(message, [message]);
909
+ }
910
+ const sitePages = Array.isArray(site.pages) ? site.pages : [];
911
+ const errors = [];
912
+ const pageDsls = /* @__PURE__ */ new Map();
913
+ for (const page of sitePages) {
914
+ const id = page.id;
915
+ if (typeof id !== "string") {
916
+ errors.push("sitemap.pages \u5B58\u5728\u7F3A\u5C11 id \u7684\u9875\u9762\u9879");
917
+ continue;
918
+ }
919
+ const rel = collected.pages.get(id);
920
+ if (rel === void 0) {
921
+ errors.push(`\u9875\u9762 DSL \u7F3A\u5931: ${id}\uFF08${config.yamlRoot} \u4E0B\u672A\u627E\u5230 ${id}.yaml / ${id}.page.yaml\uFF09`);
922
+ continue;
923
+ }
924
+ try {
925
+ pageDsls.set(id, loadYamlExpanded(yamlRoot, rel));
926
+ } catch (error) {
927
+ errors.push(`\u9875\u9762 ${id} \u5C55\u5F00\u5931\u8D25: ${error.message}`);
928
+ }
929
+ }
930
+ if (errors.length > 0) {
931
+ throw new ModuleBuildError(`\u6A21\u5757\u6784\u5EFA\u5931\u8D25\uFF08${errors.length} \u4E2A\u9519\u8BEF\uFF09`, errors);
932
+ }
933
+ const transformed = transformSitemap(site, {
934
+ profile,
935
+ demoPublic: config.demo.public,
936
+ loadLayout: (rel) => loadYamlExpanded(yamlRoot, rel)
937
+ });
938
+ const version = readProjectVersion(projectDir);
939
+ const siteAuth = site.auth !== null && typeof site.auth === "object" && !Array.isArray(site.auth) ? site.auth : {};
940
+ const rewriteCtx = {
941
+ basePath: config.basePath,
942
+ pagePaths: sitePages.map((page) => page.path).filter((path) => typeof path === "string"),
943
+ loginPath: typeof siteAuth.loginPath === "string" ? siteAuth.loginPath : "/login",
944
+ publicDir: (0, import_node_path9.join)(projectDir, config.publicDir),
945
+ rewriteNavigation: profile.rewriteNavigation.basePath,
946
+ rewriteAssets: true,
947
+ assetPrefix: profile.rewriteAssetUrls(config.id, version).replace(/\/+$/, ""),
948
+ absoluteApiToRelative: config.rewrite.absoluteApiToRelative
949
+ };
950
+ const sitemapRewrite = rewriteDslUrls(transformed.site, rewriteCtx);
951
+ warnings.push(...sitemapRewrite.warnings);
952
+ const rewrittenPages = /* @__PURE__ */ new Map();
953
+ for (const [id, dsl] of pageDsls) {
954
+ const result = rewriteDslUrls(dsl, rewriteCtx);
955
+ warnings.push(...result.warnings.map((warning) => `${id}: ${warning}`));
956
+ rewrittenPages.set(id, result.value);
957
+ }
958
+ const outDir = (0, import_node_path9.join)(projectDir, config.outDir);
959
+ const temp = (0, import_node_fs9.mkdtempSync)((0, import_node_path9.join)(projectDir, ".module-pack-"));
960
+ try {
961
+ const bundle = bundleClient({
962
+ projectDir,
963
+ clientEntry: config.clientEntry,
964
+ outDir: (0, import_node_path9.join)(temp, "client")
965
+ });
966
+ if (bundle.message !== void 0) {
967
+ warnings.push(bundle.message);
968
+ }
969
+ const emitted = emitDsl({
970
+ config,
971
+ projectDir,
972
+ outDir: temp,
973
+ site: sitemapRewrite.value,
974
+ pages: rewrittenPages
975
+ });
976
+ if (bundle.bundled && config.tailwind.enabled) {
977
+ const tailwind = compileTailwind({
978
+ projectDir,
979
+ tailwind: config.tailwind,
980
+ scanDirs: [(0, import_node_path9.join)(temp, "dsl"), (0, import_node_path9.dirname)((0, import_node_path9.join)(projectDir, config.clientEntry))],
981
+ cssFile: (0, import_node_path9.join)(temp, "client", "index.css")
982
+ });
983
+ warnings.push(...tailwind.warnings);
984
+ }
985
+ const hasCss = (0, import_node_fs9.existsSync)((0, import_node_path9.join)(temp, "client", "index.css"));
986
+ writeManifest({
987
+ config,
988
+ projectDir,
989
+ outDir: temp,
990
+ clientEntry: bundle.bundled ? "client/index.js" : void 0,
991
+ styles: bundle.bundled && hasCss ? ["client/index.css"] : void 0,
992
+ warnings
993
+ });
994
+ const validation = validateModule({ dir: projectDir, config: options.config, moduleDir: temp });
995
+ warnings.push(...validation.warnings);
996
+ if (!validation.ok) {
997
+ throw new ModuleBuildError(
998
+ `\u4EA7\u7269\u6821\u9A8C\u5931\u8D25\uFF08${validation.errors.length} \u4E2A\u9519\u8BEF\uFF09`,
999
+ validation.errors
1000
+ );
1001
+ }
1002
+ (0, import_node_fs9.rmSync)(outDir, { recursive: true, force: true });
1003
+ (0, import_node_fs9.mkdirSync)((0, import_node_path9.dirname)(outDir), { recursive: true });
1004
+ (0, import_node_fs9.renameSync)(temp, outDir);
1005
+ return {
1006
+ outDir,
1007
+ stats: {
1008
+ pages: transformed.pageCount,
1009
+ menus: transformed.menuCount,
1010
+ layouts: transformed.layoutCount,
1011
+ assets: emitted.assetCount
1012
+ },
1013
+ clientBundled: bundle.bundled,
1014
+ warnings
1015
+ };
1016
+ } catch (error) {
1017
+ (0, import_node_fs9.rmSync)(temp, { recursive: true, force: true });
1018
+ throw error;
1019
+ }
1020
+ }
1021
+
1022
+ // src/init.ts
1023
+ var import_node_fs10 = require("fs");
1024
+ var import_node_path10 = require("path");
1025
+ function initModule(options = {}) {
1026
+ const projectDir = (0, import_node_path10.resolve)(options.dir ?? process.cwd());
1027
+ const result = { created: [], skipped: [], warnings: [] };
1028
+ const pkgFile = (0, import_node_path10.join)(projectDir, "package.json");
1029
+ if (!(0, import_node_fs10.existsSync)(pkgFile)) {
1030
+ throw new Error(`\u672A\u627E\u5230 package.json: ${projectDir}\uFF08\u8BF7\u5728\u76EE\u6807\u5DE5\u7A0B\u6839\u6267\u884C\uFF09`);
1031
+ }
1032
+ const pkg = JSON.parse((0, import_node_fs10.readFileSync)(pkgFile, "utf8"));
1033
+ const id = deriveModuleId(pkg.name);
1034
+ const actions = discoverActions(projectDir);
1035
+ const hasComponents = discoverComponents(projectDir);
1036
+ const configFile = (0, import_node_path10.join)(projectDir, CONFIG_FILE);
1037
+ if ((0, import_node_fs10.existsSync)(configFile)) {
1038
+ result.skipped.push(`${CONFIG_FILE}\uFF08\u5DF2\u5B58\u5728\uFF09`);
1039
+ } else {
1040
+ const config = {
1041
+ id,
1042
+ name: typeof pkg.name === "string" ? pkg.name : id,
1043
+ basePath: `/${id}`,
1044
+ yamlRoot: CONFIG_DEFAULTS.yamlRoot,
1045
+ clientEntry: CONFIG_DEFAULTS.clientEntry,
1046
+ actions: actions.map((action) => action.specifier.replace(/^\.\.\//, "")),
1047
+ publicDir: CONFIG_DEFAULTS.publicDir,
1048
+ target: DEFAULT_TARGET,
1049
+ demo: { public: false }
1050
+ };
1051
+ (0, import_node_fs10.writeFileSync)(configFile, `${JSON.stringify(config, null, 2)}
1052
+ `, "utf8");
1053
+ result.created.push(CONFIG_FILE);
1054
+ }
1055
+ const clientFile = (0, import_node_path10.join)(projectDir, CONFIG_DEFAULTS.clientEntry);
1056
+ if ((0, import_node_fs10.existsSync)(clientFile)) {
1057
+ result.skipped.push(`${CONFIG_DEFAULTS.clientEntry}\uFF08\u5DF2\u5B58\u5728\uFF09`);
1058
+ } else {
1059
+ (0, import_node_fs10.mkdirSync)((0, import_node_path10.join)(projectDir, "module"), { recursive: true });
1060
+ (0, import_node_fs10.writeFileSync)(clientFile, renderClientEntry(hasComponents, actions), "utf8");
1061
+ result.created.push(CONFIG_DEFAULTS.clientEntry);
1062
+ }
1063
+ injectPackageJson(pkg, result);
1064
+ (0, import_node_fs10.writeFileSync)(pkgFile, `${JSON.stringify(pkg, null, 2)}
1065
+ `, "utf8");
1066
+ result.created.push("package.json\uFF08\u6CE8\u5165 files / exports / scripts / peerDependencies\uFF09");
1067
+ return result;
1068
+ }
1069
+ function deriveModuleId(name) {
1070
+ const base2 = typeof name === "string" && name.length > 0 ? name : "module";
1071
+ const withoutScope = base2.startsWith("@") ? base2.slice(base2.indexOf("/") + 1) : base2;
1072
+ const kebab = withoutScope.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
1073
+ return kebab.length > 0 ? kebab : "module";
1074
+ }
1075
+ function discoverActions(projectDir) {
1076
+ const dir = (0, import_node_path10.join)(projectDir, "src/pactor");
1077
+ if (!(0, import_node_fs10.existsSync)(dir)) return [];
1078
+ const sources = [];
1079
+ for (const entry of (0, import_node_fs10.readdirSync)(dir, { withFileTypes: true }).sort(
1080
+ (a, b) => a.name.localeCompare(b.name)
1081
+ )) {
1082
+ if (!entry.isFile() || !entry.name.endsWith("-actions.ts")) continue;
1083
+ const file = (0, import_node_path10.join)(dir, entry.name);
1084
+ const content = (0, import_node_fs10.readFileSync)(file, "utf8");
1085
+ const exports2 = [...content.matchAll(/export\s+const\s+([A-Za-z_$][\w$]*)/g)].map(
1086
+ (match) => match[1]
1087
+ );
1088
+ if (exports2.length === 0) continue;
1089
+ sources.push({
1090
+ specifier: `../src/pactor/${entry.name.replace(/\.ts$/, "")}`,
1091
+ exports: exports2
1092
+ });
1093
+ }
1094
+ return sources;
1095
+ }
1096
+ function discoverComponents(projectDir) {
1097
+ const file = (0, import_node_path10.join)(projectDir, "src/pactor/components/index.ts");
1098
+ if (!(0, import_node_fs10.existsSync)(file)) return false;
1099
+ return /export\s+(const|\{[^}]*)\s*pactorComponents/.test((0, import_node_fs10.readFileSync)(file, "utf8"));
1100
+ }
1101
+ function renderClientEntry(hasComponents, actions) {
1102
+ const imports = [];
1103
+ const spreads = [];
1104
+ if (hasComponents) {
1105
+ imports.push("import { pactorComponents } from '../src/pactor/components';");
1106
+ }
1107
+ for (const action of actions) {
1108
+ imports.push(
1109
+ `import { ${action.exports.join(", ")} } from '${action.specifier}';`
1110
+ );
1111
+ spreads.push(...action.exports.map((name) => `...${name}`));
1112
+ }
1113
+ const components = hasComponents ? "pactorComponents" : "{}";
1114
+ const actionsExpr = spreads.length > 0 ? `{ ${spreads.join(", ")} }` : "{}";
1115
+ return `// \u7531 \`pactor module init\` \u751F\u6210\uFF1A\u6A21\u5757 client \u5165\u53E3\u3002
1116
+ // Shell \u88C5\u914D\u5668\u751F\u6210 client-registry.ts \u65F6\u9759\u6001 import "<pkg>/client"\uFF0C
1117
+ // \u8981\u6C42\u6B64\u5904\u5177\u540D\u5BFC\u51FA extensions\uFF08components / actions \u6CE8\u518C\u8868\uFF09\u3002
1118
+ ${imports.join("\n")}
1119
+
1120
+ export const extensions = {
1121
+ components: ${components},
1122
+ actions: ${actionsExpr},
1123
+ };
1124
+ `;
1125
+ }
1126
+ function injectPackageJson(pkg, result) {
1127
+ const outDir = CONFIG_DEFAULTS.outDir;
1128
+ const files = Array.isArray(pkg.files) ? pkg.files : [];
1129
+ if (!files.includes(outDir)) {
1130
+ pkg.files = [...files, outDir];
1131
+ }
1132
+ const exportsMap = isRecord4(pkg.exports) ? { ...pkg.exports } : {};
1133
+ const wantedExports = {
1134
+ "./manifest": `./${outDir}/manifest.json`,
1135
+ "./client": `./${outDir}/client/index.js`,
1136
+ "./styles.css": `./${outDir}/client/index.css`
1137
+ };
1138
+ for (const [key, value] of Object.entries(wantedExports)) {
1139
+ if (exportsMap[key] === void 0) {
1140
+ exportsMap[key] = value;
1141
+ } else if (exportsMap[key] !== value) {
1142
+ 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`);
1143
+ }
1144
+ }
1145
+ pkg.exports = exportsMap;
1146
+ const scripts = isRecord4(pkg.scripts) ? { ...pkg.scripts } : {};
1147
+ const wantedScripts = {
1148
+ "build:module": "pactor module build",
1149
+ "pack:module": "pactor module pack"
1150
+ };
1151
+ for (const [key, value] of Object.entries(wantedScripts)) {
1152
+ if (scripts[key] === void 0) {
1153
+ scripts[key] = value;
1154
+ } else if (scripts[key] !== value) {
1155
+ result.warnings.push(`package.json scripts["${key}"] \u5DF2\u5B58\u5728\uFF0C\u672A\u8986\u76D6\uFF08\u5F53\u524D: ${JSON.stringify(scripts[key])}\uFF09`);
1156
+ }
1157
+ }
1158
+ pkg.scripts = scripts;
1159
+ const peers = isRecord4(pkg.peerDependencies) ? { ...pkg.peerDependencies } : {};
1160
+ const dependencies = isRecord4(pkg.dependencies) ? pkg.dependencies : {};
1161
+ const defaults = {
1162
+ react: "^18.0.0 || ^19.0.0",
1163
+ "react-dom": "^18.0.0 || ^19.0.0",
1164
+ next: "^14.0.0 || ^15.0.0",
1165
+ "pactor-app": "^1.54.0"
1166
+ };
1167
+ for (const [name, fallback] of Object.entries(defaults)) {
1168
+ if (peers[name] !== void 0) continue;
1169
+ const declared = dependencies[name];
1170
+ peers[name] = typeof declared === "string" && declared.length > 0 ? declared : fallback;
1171
+ }
1172
+ pkg.peerDependencies = peers;
1173
+ }
1174
+ function isRecord4(value) {
1175
+ return value !== null && typeof value === "object" && !Array.isArray(value);
1176
+ }
1177
+ // Annotate the CommonJS export names for ESM import in node:
1178
+ 0 && (module.exports = {
1179
+ CLIENT_EXTERNALS,
1180
+ CONFIG_DEFAULTS,
1181
+ CONFIG_FILE,
1182
+ ConfigError,
1183
+ DEFAULT_TARGET,
1184
+ INCLUDE_KEY,
1185
+ IncludeError,
1186
+ ModuleBuildError,
1187
+ ProfileError,
1188
+ buildModule,
1189
+ bundleClient,
1190
+ collectModuleSource,
1191
+ compileTailwind,
1192
+ deriveModuleId,
1193
+ discoverActions,
1194
+ discoverComponents,
1195
+ emitDsl,
1196
+ emitModule,
1197
+ expandIncludes,
1198
+ getProfile,
1199
+ initModule,
1200
+ innospotsWebShellV1,
1201
+ innospotsWebShellV2,
1202
+ listProfiles,
1203
+ loadModuleConfig,
1204
+ loadYamlExpanded,
1205
+ matchPathPattern,
1206
+ parseJsonc,
1207
+ parseYamlFile,
1208
+ readProjectVersion,
1209
+ renderClientEntry,
1210
+ resolvePactorVersionRange,
1211
+ rewriteDslUrls,
1212
+ rewriteNavigationTo,
1213
+ transformSitemap,
1214
+ tsconfigAliases,
1215
+ validateModule,
1216
+ writeManifest
1217
+ });